Merge remote-tracking branch 'origin/preprod-temp-App-Updation-API-Version' into dev

This commit is contained in:
Pritimay Sarkar
2024-01-16 10:53:54 +05:30
6 changed files with 168 additions and 11 deletions

View File

@@ -83,7 +83,7 @@ dependencies {
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'com.google.android.play:core:1.10.3'
implementation 'io.nats:jnats:2.11.2'
@@ -142,5 +142,7 @@ dependencies {
implementation("androidx.work:work-runtime-ktx:2.9.0")
implementation("io.nats:jnats:2.11.2")
// implementation("io.nats:jnats:2.11.2")
implementation 'com.google.android.play:core:1.10.3'
}

View File

@@ -5,6 +5,8 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission
android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" />
@@ -81,7 +83,17 @@
android:exported="false"
android:label="@string/title_activity_dashboard"
android:theme="@style/Theme.HPOS.NoActionBar"
tools:ignore="MissingClass" />
tools:ignore="AppLinkUrlError,MissingClass">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
<data android:scheme="file" />
<data android:mimeType="application/vnd.android.package-archive" />
</intent-filter>
</activity>
<service
android:name="com.example.hpostesting.presentation.testRight.UsbService"
@@ -133,6 +145,17 @@
android:screenOrientation="portrait"
android:stateNotNeeded="true"
tools:replace="android:screenOrientation" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.hpostesting.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

View File

@@ -64,7 +64,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
if (false) {
Toast.makeText(
view.context,
context?.getString(R.string.low_battery_warning),
view.context.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
@@ -73,7 +73,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
if (userList.testStatus!!) {
Toast.makeText(
view.context,
context?.getString(R.string.test_already_conducted),
view.context.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT
).show()
} else {
@@ -81,13 +81,14 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_completed),
view.context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
} else
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_crossed_30_minutes),
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
@@ -102,7 +103,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
} else {
Toast.makeText(
view.context,
context?.getString(R.string.incubation_not_started),
view.context.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}

View File

@@ -1,29 +1,42 @@
package com.example.hpostesting.presentation.dashboard
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.presentation.NatsManager
import com.google.android.material.navigation.NavigationView
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException
import com.google.firebase.crashlytics.FirebaseCrashlytics
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import okhttp3.ResponseBody
import java.io.File
open interface IDataCollector {
fun setConnect(connect: Boolean)
@@ -36,6 +49,10 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
private lateinit var binding: ActivityDashboardBinding
var responses: String = ""
lateinit var nats: NatsManager
private var downloadId: Long = 0
// TODO: Remove hemocube viewmodel
private val hemocubeViewModel: HemoCubeViewModel by viewModels()
override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode)
@@ -52,6 +69,42 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
nats.connect()
nats.pub("server.hpos.HCV-000-3001.ping", "THIS IS A TEST MSG")
hemocubeViewModel.deviceUpdate.observe(this) { result ->
when (result) {
is Result.Success -> {
// Handle success
val apkUrl = result.data
// val apkUrl = "https://dl.dropboxusercontent.com/s/fi/1c3nn7t0co431hicl3hrt/app-debug.apk?rlkey=e4uf13ty1dpcked614vy1aaqp&dl=0"
initiateUpdate(apkUrl.toString())
Log.d("ApI", "APK URL: $apkUrl")
Toast.makeText(
this,
"APK UPLOAD ${result.data}",
Toast.LENGTH_SHORT
).show()
// The APK URL LiveData will be updated automatically
}
is Result.Error -> {
result.exception.let { message ->
Toast.makeText(this, "An error occurred On Updating App: $message", Toast.LENGTH_LONG)
.show()
}
}
is Result.Loading -> {
}
else -> {
}
}
}
val drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_content_dashboard)
@@ -63,7 +116,6 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -77,6 +129,82 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
private fun initiateUpdate(responseBody: String) {
// Extract the URL from the ResponseBody
val apkUrl = responseBody
// Check if the extracted APK URL is valid
if (!isValidHttpUrl(apkUrl)) {
// Handle the case where the URL is not valid
return
}
val request = DownloadManager.Request(Uri.parse(apkUrl))
request.setTitle("App Update")
request.setDescription("Downloading update...")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalFilesDir(this, "Updates", "update.apk")
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request)
// Register a BroadcastReceiver to receive the download complete event
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
registerReceiver(downloadReceiver, filter)
}
// Function to check if a URL has a valid HTTP/HTTPS scheme
// Function to extract the APK URL from the ResponseBody
private fun extractApkUrl(responseBody: ResponseBody): String {
// Assuming your ResponseBody contains the APK URL as a string
return responseBody.string()
}
// Function to check if a URL has a valid HTTP/HTTPS scheme
private fun isValidHttpUrl(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://")
}
private val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadId) {
// Install the downloaded APK
installApk()
}
}
}
private fun installApk() {
val file = File(getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
val uri: Uri = FileProvider.getUriForFile(
this,
"com.example.hpostesting.fileprovider",
file
)
// Create an intent to install the APK
val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE)
installIntent.data = uri
installIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP
installIntent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
// Start the installation
startActivity(installIntent)
Log.d("InstallApk", "Install Intent URI: $uri")
Log.d("InstallApk", "Package Name: $packageName")
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(downloadReceiver)
}
override fun onResume() {
super.onResume()

View File

@@ -169,7 +169,7 @@ class HemoCubeViewModel @Inject constructor(
val logFile = logFileManager.createLogFile().let { file ->
val requestBody = file?.asRequestBody("multipart/form-data".toMediaTypeOrNull())
val multipartFile =
requestBody?.let { MultipartBody.Part.createFormData("logFile", file.name, it) }
requestBody?.let { MultipartBody.Part.createFormData("logFile", file?.name, it) }
multipartFile?.let { partFile ->
databaseRepository.uploadLogs(partFile).let { result ->
uploadLogs.postValue(result)

View File

@@ -0,0 +1,3 @@
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="Updates" path="." />
</paths>