diff --git a/app/build.gradle b/app/build.gradle
index 494a6b9..9343354 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -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'
+
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 153965f..abc813f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,8 @@
+
+
@@ -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">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt b/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt
index c190408..f1481a5 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt
@@ -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()
}
diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
index 4741cd2..6591f33 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
@@ -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()
diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
index 9fa3604..2e89400 100644
--- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
+++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt
@@ -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)
diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml
new file mode 100644
index 0000000..6e9c380
--- /dev/null
+++ b/app/src/main/res/xml/file_paths.xml
@@ -0,0 +1,3 @@
+
+
+