Compare commits

...

19 Commits

Author SHA1 Message Date
sanjay
1a31d26bc1 Merge branch 'dev-check-apk-update' of https://gitlab.com/sminnovations/hpos into dev-check-apk-update 2024-03-06 11:30:30 +05:30
sanjay
3199caae5c changed gradle value 2024-03-06 11:28:51 +05:30
Mariya Varghese
a52538e72d Merge branch 'dev' into 'dev-check-apk-update'
# Conflicts:
#   app/build.gradle
#   app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt
#   app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
#   app/src/main/java/com/example/hpostesting/presentation/hemocube/HemocubeActivity.kt
#   build.gradle
#   gradle/wrapper/gradle-wrapper.properties
2024-03-04 11:11:13 +00:00
chandrashekhar reddy
78cc79eef8 changes in HomeFragment added deviceId global and added default values 2024-03-04 15:37:32 +05:30
Mariya
c9d0c440e3 added code for sanitize result upload values if if the result is NAN or infinity for molbio integration 2024-03-04 14:48:43 +05:30
chandrashekhar reddy
99da2fc094 error in HomeFragment and DashboardActivity solved registering broadcast receiver was giving issue solved by adding checks 2024-03-04 14:26:44 +05:30
Mariya
20f408230e api calls managing, and error resolving for molbio 2024-03-02 19:37:24 +05:30
Mariya
c8d5d41c81 api calls maintaining for molbio 2024-03-02 15:41:17 +05:30
Mariya
210c9fed5d added code for usb permission 2024-03-01 16:21:27 +05:30
Mariya
b68ec45642 reduced number of api calls in home screen 2024-03-01 13:37:16 +05:30
Mariya
1e5afa0a5c reduced number api calls for bigtec 2024-03-01 12:38:19 +05:30
Mariya
80ab69c772 added code for uploading logs only once 2024-02-29 14:18:09 +05:30
Mariya
f7dc879c75 added code related offline bulkupload 2024-02-28 15:17:36 +05:30
Mariya
e8b5d12db5 removed unwanted toast messages 2024-02-28 15:12:21 +05:30
Mariya
626dd380ab Apk update successfully added 2024-02-28 14:46:06 +05:30
Mariya
70b0b93f57 Apk Update Code Added 2024-02-27 20:44:32 +05:30
Mariya
5cdc156f33 Apk Update Code Added 2024-02-27 16:49:25 +05:30
Mariya
71d298cd69 Apk Update Code Added 2024-02-27 14:59:03 +05:30
Mariya
bb6f4ee859 Apk Update Code Added 2024-02-27 12:43:14 +05:30
14 changed files with 367 additions and 245 deletions

View File

@@ -25,6 +25,7 @@
<application <application
android:name="com.example.hpostesting.HPOSTestingApplication" android:name="com.example.hpostesting.HPOSTestingApplication"
android:largeHeap="true"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"

View File

@@ -8,7 +8,7 @@ object Constants {
const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb" const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb"
const val ABHA_APP_PACKAGE = "in.ndhm.phr" const val ABHA_APP_PACKAGE = "in.ndhm.phr"
const val MOLBIO_INTEGRATION = false const val MOLBIO_INTEGRATION = true
const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in" const val deviceProvisionEmail = "HPOS_provisioner@bigtec.co.in"
const val deviceProvisionPassword = "f2ab0e7f9d69" const val deviceProvisionPassword = "f2ab0e7f9d69"
const val DEVICE_ID_API = "deviceIDAPI" const val DEVICE_ID_API = "deviceIDAPI"

View File

@@ -10,7 +10,7 @@ import com.example.hpostesting.data.model.patient.UserData
@Database( @Database(
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class], entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class],
version = 27, version = 28,
exportSchema = false exportSchema = false
) )
@TypeConverters(Converters::class) @TypeConverters(Converters::class)

View File

@@ -109,20 +109,7 @@ class DatabaseRepository @Inject constructor(
} }
override suspend fun addTestToDatabase(data: UserData?): Response<String> { override suspend fun addTestToDatabase(data: UserData?): Response<String> {
return try { TODO("Not yet implemented")
val userdata =
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("testData").add(data).await()
Response.Success(data._id)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
} }
override suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String> { override suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response<String> {
@@ -247,4 +234,22 @@ class DatabaseRepository @Inject constructor(
override fun <UserData> addTestToDatabase(testDetails: UserData): Any { override fun <UserData> addTestToDatabase(testDetails: UserData): Any {
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override suspend fun addTestToDatabasefornew(data: HemoCubeTestData?): Response<String> {
return try {
val userdata =
db.collection("patientData").whereEqualTo("_id", data!!._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("testData").add(data).await()
Response.Success(data._id)
} catch (e: Exception) {
Firebase.crashlytics.recordException(e)
Response.Error(e)
}
}
} }

View File

@@ -25,6 +25,7 @@ import okhttp3.ResponseBody
interface Repository { interface Repository {
suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String> suspend fun addTestToDatabase(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabasefornew(data: HemoCubeTestData?): Response<String>
suspend fun addTestToDatabase(data: UserData?): Response<String> suspend fun addTestToDatabase(data: UserData?): Response<String>

View File

@@ -1,7 +1,6 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.app.DownloadManager import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
@@ -24,7 +23,7 @@ import androidx.navigation.ui.setupWithNavController
import com.example.hpostesting.data.Result import com.example.hpostesting.data.Result
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.presentation.NatsManager import com.example.hpostesting.presentation.NatsManager
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.jig.JigActivity import com.example.hpostesting.presentation.jig.JigActivity
@@ -35,10 +34,16 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.BuildConfig
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
import okhttp3.ResponseBody import okhttp3.ResponseBody
import java.io.BufferedInputStream
import java.io.File import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.InputStream
import java.util.zip.ZipInputStream
interface NatsMessageCallback { interface NatsMessageCallback {
fun onMessageReceived(topic: String, message: String) fun onMessageReceived(topic: String, message: String)
@@ -53,6 +58,7 @@ open interface IDataCollector: NatsMessageCallback {
class DashboardActivity : AppCompatActivity(), IDataCollector { class DashboardActivity : AppCompatActivity(), IDataCollector {
val TAG = "DashboardActivity" val TAG = "DashboardActivity"
private var isRegistered = false
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding private lateinit var binding: ActivityDashboardBinding
lateinit var sharedPreferences: SharedPreferences lateinit var sharedPreferences: SharedPreferences
@@ -61,7 +67,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
private var downloadId: Long = 0 private var downloadId: Long = 0
// TODO: Remove hemocube viewmodel // TODO: Remove hemocube viewmodel
private val hemocubeViewModel: HemoCubeViewModel by viewModels() private val hemocubeViewModel: HemoCubeViewModel by viewModels()
private lateinit var sharedPreference: SharedPreferences
override fun attachBaseContext(newBase: Context?) { override fun attachBaseContext(newBase: Context?) {
val languageCode = LanguageManager.getSavedLanguage(newBase!!) val languageCode = LanguageManager.getSavedLanguage(newBase!!)
LanguageManager.setLocale(newBase, languageCode) LanguageManager.setLocale(newBase, languageCode)
@@ -74,6 +80,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
Log.d(TAG, "Received message on topic $topic: $message") Log.d(TAG, "Received message on topic $topic: $message")
} }
@SuppressLint("SetWorldReadable")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -95,15 +102,22 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
when (result) { when (result) {
is Result.Success -> { is Result.Success -> {
// Handle success // Handle success
val apkUrl = result.data val apk = result.data
// val apkUrl = "https://dl.dropboxusercontent.com/s/fi/1c3nn7t0co431hicl3hrt/app-debug.apk?rlkey=e4uf13ty1dpcked614vy1aaqp&dl=0" val file = File(getExternalFilesDir("Updates"), "update.apk")
initiateUpdate(apkUrl.toString()) file.setReadable(true, false) // Ensure the file is readable
Log.d("ApI", "APK URL: $apkUrl") apk.byteStream().use { input ->
// Toast.makeText( file.outputStream().use { output ->
// this, input.copyTo(output)
// "APK UPLOAD ${result.data}", }
// Toast.LENGTH_SHORT }
// ).show() Log.d("Responsebodyformat", "Responsebodyformat: ")
installApk(file)
Log.e("ApI", "APK URL: $apk")
Toast.makeText(
this,
"${result.data}",
Toast.LENGTH_SHORT
).show()
} }
is Result.Error -> { is Result.Error -> {
@@ -153,52 +167,15 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
} }
private fun initiateUpdate(url: String) {
val apkUrl = url
if (!isValidHttpUrl(apkUrl)) {
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)
}
private fun extractApkUrl(responseBody: ResponseBody): String {
return responseBody.string()
}
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) {
installApk()
}
}
}
private fun installApk() {
val file = File(getExternalFilesDir("Updates"), "update.apk")
file.setReadable(true, false) // Ensure the file is readable
private fun installApk(file: File) {
val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0) val pInfo = baseContext.packageManager.getPackageInfo(baseContext.packageName, 0)
val uri: Uri = FileProvider.getUriForFile( val uri: Uri = FileProvider.getUriForFile(
this, this,
"in.sminnovations.hpostesting.dev.fileprovider", "${BuildConfig.APPLICATION_ID}.fileprovider",
file file
) )
// Create an intent to install the APK
val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE) val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE)
installIntent.data = uri installIntent.data = uri
installIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or installIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
@@ -214,8 +191,14 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
} }
override fun onDestroy() { override fun onDestroy() {
if(isRegistered) {
try {
unregisterReceiver(downloadReceiver)
} catch (e: Exception) {
Log.d("HomeFragment", e.toString())
}
}
super.onDestroy() super.onDestroy()
unregisterReceiver(downloadReceiver)
} }
override fun onResume() { override fun onResume() {
@@ -267,6 +250,14 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
override fun setResponse(response: String) { override fun setResponse(response: String) {
responses = responses+response+"\n" responses = responses+response+"\n"
println(responses) println(responses)
Log.d("DashBoardActResponse",response) // if (response.contains("checkUpdate")) {
// hemocubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
// }
}
private fun createDeviceUpdateRequestData(): DeviceUpdateRequest {
return DeviceUpdateRequest(
serial_no = sharedPreference.getString(Constants.DEVICE_ID, "")
)
} }
} }

View File

@@ -6,12 +6,14 @@ import android.app.DownloadManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Context.BATTERY_SERVICE import android.content.Context.BATTERY_SERVICE
import android.content.Context.RECEIVER_EXPORTED
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.BatteryManager import android.os.BatteryManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
@@ -19,7 +21,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.core.content.FileProvider import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
@@ -70,6 +72,7 @@ import java.util.zip.ZipInputStream
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
private var isRegistered = false
private var downloadId: Long = 0 private var downloadId: Long = 0
private lateinit var binding: FragmentHomeBinding private lateinit var binding: FragmentHomeBinding
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
@@ -96,6 +99,7 @@ class HomeFragment : Fragment() {
return binding.root return binding.root
} }
@RequiresApi(Build.VERSION_CODES.P)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@@ -145,35 +149,67 @@ class HomeFragment : Fragment() {
checkForTokenAndUpdate() checkForTokenAndUpdate()
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> // Now re-subscribe to allUserData
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result())) hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { originalUserDataList ->
userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) { Log.d("LOCAL_DB OBSERVE", "OBSERVE CALLED")
resultList.results?.add(
MolbioV2Result( val resultList = MolbioV2ResultRequest(mutableListOf())
rawData = userData, originalUserDataList.forEach { userData ->
analysisId = userData._id, Log.d(
analysisDate = "2024-02-08 16:33:56",//userData.testTime, ": USER DATA",
analysisStatus = userData.classificationResult, originalUserDataList.count().toString() + " : " + userData._id
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(), )
interpretation = userData.classificationResult, var accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
testId = userData._id, // Upload results after processing all userData to avoid duplicates and ensure all modifications are done
testTime = "2024-02-08 16:33:56",//userData.testTime, if(accessToken.isNotEmpty()) {
collectionTime = "2024-02-08 16:33:56",//userData.testTime, if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
expiryTime = "2024-02-08 16:33:56"//userData.testTime, val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
Locale.getDefault()
).format(Calendar.getInstance().time)
val bufferIntensityThreshold =
Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId]?.toString()
?: "defaultThreshold" // Handle possible nulls safely
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = currentTimeFormatted,
analysisStatus = userData.classificationResult
?: "defaultStatus", // Handle possible nulls
thresholds = bufferIntensityThreshold,
interpretation = userData.classificationResult
?: "defaultInterpretation", // Handle possible nulls
testId = userData._id,
testTime = currentTimeFormatted,
collectionTime = currentTimeFormatted,
expiryTime = currentTimeFormatted
)
) )
) }
}
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList)
} }
}
Log.d("USER DATA LIST SIZE", resultList.results?.count().toString())
if (!userData.localFlag) { resultList.results?.forEach { result ->
userData.localFlag = true val userData = result.rawData
hemoCubeViewModel.bulkAddResultTestToDb(userData) Log.d("UserData", userData.toString())
} if (userData != null) {
if (!userData.localFlag) {
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
}
}
resultList.results?.forEach { result ->
result.rawData?.let { sanitizeDoubleValues(it) }
}
// Then, check if there are any results to upload.
if (resultList.results?.isNotEmpty() == true) {
hemoCubeViewModel.uploadResult(resultList)
Log.d("resultcount1", "Uploading sanitized results")
} }
} }
@@ -201,7 +237,7 @@ class HomeFragment : Fragment() {
} }
binding.uploadData.setOnClickListener { binding.uploadData.setOnClickListener {
showUploadDialog(requireContext()) // showUploadDialog(requireContext())
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData -> hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
@@ -250,41 +286,32 @@ class HomeFragment : Fragment() {
} }
@RequiresApi(Build.VERSION_CODES.P)
private fun checkForTokenAndUpdate() { private fun checkForTokenAndUpdate() {
var accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString() var accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
var password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString() var password = sharedPreference.getString(Constants.DEVICE_PASSWORD_API, "").toString()
var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString() var userID = sharedPreference.getString(Constants.DEVICE_ID_API, "").toString()
deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString() deviceId = sharedPreference.getString(Constants.DEVICE_ID, "").toString()
if (userID.isNotEmpty() && password.isNotEmpty()) { if(userID.isNotEmpty() && password.isNotEmpty()) {
if (!isTokenAvailable) { Log.d("istoken",isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(userID, password)) if (!isTokenAvailable) {
} else { Log.d("istoken1",isTokenAvailable.toString())
if (isTokenExpired(accessToken)) { hemoCubeViewModel.login(createLoginRequestData(userID, password))
hemoCubeViewModel.login(createLoginRequestData(userID, password)) isTokenAvailable = true
} else {
isTokenAvailable = true
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData()) }else if(isTokenAvailable){
hemoCubeViewModel.uploadLogs() Log.d("istoken7",isTokenAvailable.toString())
hemoCubeViewModel.startPeriodicCheckUpdate() isTokenAvailable = true
hemoCubeViewModel.downloadClientCertificate() hemoCubeViewModel.startPeriodicCheckUpdate()
} hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
} }else{
} else if (deviceId.isNotEmpty()) { if(isTokenExpired(accessToken)) {
Log.d("istoken8",isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(userID, password))
}
}
} else if (userID.isEmpty() && password.isEmpty() && deviceId.isNotEmpty()) {
fetchDeviceCredentials() fetchDeviceCredentials()
// This code will execute after credentials have been successfully fetched and stored.
userID = sharedPreference.getString("username", "").toString()
password = sharedPreference.getString("password", "").toString()
accessToken = sharedPreference.getString(Constants.ACCESS_TOKEN, "").toString()
if (accessToken.isEmpty()) {
hemoCubeViewModel.login(createLoginRequestData(userID, password))
} else {
// Continue with your existing logic if the token is not empty.
isTokenAvailable = true
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.startPeriodicCheckUpdate()
}
} else { } else {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
@@ -297,6 +324,9 @@ class HomeFragment : Fragment() {
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
updateTokens(response) updateTokens(response)
response.data.data?.accessToken
isTokenAvailable = true
Log.d("istoken2",isTokenAvailable.toString())
} }
is Result.Error -> { is Result.Error -> {
@@ -318,6 +348,36 @@ class HomeFragment : Fragment() {
} }
} }
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
Log.d("success,","uploded")
it.data.data?.forEach { id ->
id.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id
)
}
}
Toast.makeText(activity, "Molbio Result is successfully uploaded", Toast.LENGTH_LONG)
.show()
}
is Result.Error -> {
binding.btnSubmit.visibility = View.VISIBLE
//Remove this line of code while deploying to IOCL
it.exception.let { message ->
Toast.makeText(activity, "$message", Toast.LENGTH_LONG)
.show()
Log.d("resultuploadfail", message.toString())
}
}
else -> {}
}
}
hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response -> hemoCubeViewModel.uploadLogs.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
@@ -326,13 +386,14 @@ class HomeFragment : Fragment() {
// "Log uploaded ${response.data.data?.filename}", // "Log uploaded ${response.data.data?.filename}",
// Toast.LENGTH_SHORT // Toast.LENGTH_SHORT
// ).show() // ).show()
} }
is Result.Error -> { is Result.Error -> {
response.exception.let { message -> response.exception.let { message ->
Toast.makeText( Toast.makeText(
activity, activity,
"An error occurred in uploading logs: $message", "$message",
Toast.LENGTH_LONG Toast.LENGTH_LONG
) )
.show() .show()
@@ -347,28 +408,84 @@ class HomeFragment : Fragment() {
} }
} }
hemoCubeViewModel.checkUpdate.observe(viewLifecycleOwner) { response ->
when (response) {
is Result.Success -> {
val updatedversion = response.data.data?.version.toString()
val currentversion =
context?.let { ctx ->
val packageInfo = ctx.packageManager.getPackageInfo(ctx.packageName, 0)
val versionName = packageInfo.versionName
val versionCode: Long = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// From Android P (API level 28), versionCode is deprecated and you should use longVersionCode instead.
packageInfo.longVersionCode
} else {
// For older Android versions, use versionCode (cast it to Long for consistency).
packageInfo.versionCode.toLong()
}
// Use versionName and versionCode as needed
Log.d("AppInfo", "Version Name: $versionName, Version Code: $versionCode")
}
Log.d("versionnow",currentversion.toString())
Log.d("versionnow",updatedversion.toString())
if(updatedversion > currentversion.toString()){
hemoCubeViewModel.deviceUpdate(createDeviceUpdateRequestData())
Toast.makeText(
activity,
"new version ${response.data.data?.version} Available",
Toast.LENGTH_LONG
)
.show()
}else{
Toast.makeText(
activity,
"App is Up to date",
Toast.LENGTH_LONG
)
.show()
}
}
is Result.Error -> {
// response.exception.let { message ->
//// Toast.makeText(
//// activity,
//// "$message",
//// Toast.LENGTH_LONG
//// )
//// .show()
// }
}
is Result.Loading -> {
}
else -> {
}
}
}
hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response -> hemoCubeViewModel.downloadcertificate.observe(viewLifecycleOwner) { response ->
when (response) { when (response) {
is Result.Success -> { is Result.Success -> {
val url = response.data val url = response.data
val fileName = "nats_certificate.zip"
val downloadDirectory = "NATS" val downloadDirectory = "NATS"
val file = downloadFile(url, requireContext(), fileName, downloadDirectory) val fileName = "nats_certificate.zip"
Toast.makeText( val unzipDirectoryPath = requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory"
requireContext(),
"NATS certificate Downloaded", // Check if the directory with extracted files exists.
Toast.LENGTH_SHORT val directory = File(unzipDirectoryPath)
).show() if (directory.exists() && directory.isDirectory) {
// Assuming if the directory exists, the certificate has been downloaded and extracted.
// You can add more specific checks here, e.g., checking for specific files within the directory.
Toast.makeText(requireContext(), "NATS certificate already downloaded and extracted.", Toast.LENGTH_SHORT).show()
return@observe
}
val file = downloadFile(url, requireContext(), fileName, downloadDirectory)
val unzipDirectoryPath =
requireContext().getExternalFilesDir(null)?.absolutePath + "/$downloadDirectory"
unzip(file.absolutePath, unzipDirectoryPath) unzip(file.absolutePath, unzipDirectoryPath)
Toast.makeText(
requireContext(),
"NATS certificate Extracted",
Toast.LENGTH_SHORT
).show()
} }
is Result.Error -> { is Result.Error -> {
@@ -390,44 +507,23 @@ class HomeFragment : Fragment() {
} }
} }
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
when (it) {
is Result.Success -> {
it.data.data?.forEach { id ->
id.rawData?.let { it1 ->
hemoCubeViewModel.updateMolbioFlag(
it1._id
)
}
}
}
is Result.Error -> {
binding.btnSubmit.visibility = View.VISIBLE
//Remove this line of code while deploying to IOCL
it.exception.let { message ->
Toast.makeText(activity, "An error occurred: $message", Toast.LENGTH_LONG)
.show()
}
}
else -> {}
}
}
} }
private fun isTokenExpired(token: String): Boolean { private fun isTokenExpired(token: String): Boolean {
val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() if(token.isNotEmpty()) {
val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT)) val parts = token.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val jsonPayload = JSONObject(decodedPayload) val decodedPayload = String(Base64.decode(parts[1], Base64.DEFAULT))
val jsonPayload = JSONObject(decodedPayload)
val exp = jsonPayload.optLong("exp", 0) val exp = jsonPayload.optLong("exp", 0)
val currentTimeSeconds = System.currentTimeMillis() / 1000 val currentTimeSeconds = System.currentTimeMillis() / 1000
return exp <= currentTimeSeconds return exp <= currentTimeSeconds
}else{
return false
}
} }
private fun updateTokens(response: Result.Success<LoginResponse>) { private fun updateTokens(response: Result.Success<LoginResponse>) {
@@ -440,6 +536,7 @@ class HomeFragment : Fragment() {
apply() apply()
} }
isTokenAvailable = true isTokenAvailable = true
Log.d("istoken3",isTokenAvailable.toString())
} }
private fun createLoginRequestData(userID: String, password: String): LoginRequest { private fun createLoginRequestData(userID: String, password: String): LoginRequest {
@@ -550,6 +647,7 @@ class HomeFragment : Fragment() {
} }
} }
@RequiresApi(Build.VERSION_CODES.P)
private fun fetchDeviceCredentials() { private fun fetchDeviceCredentials() {
try { try {
val db = Firebase.firestore val db = Firebase.firestore
@@ -576,12 +674,16 @@ class HomeFragment : Fragment() {
) )
// Save credentials in SharedPreferences // Save credentials in SharedPreferences
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
putString("username", username) putString(Constants.DEVICE_ID_API, username)
putString("password", password) putString(Constants.DEVICE_PASSWORD_API, password)
putString(Constants.NATS_TOKEN, natsToken) putString(Constants.NATS_TOKEN, natsToken)
apply() apply()
} }
hemoCubeViewModel.login(createLoginRequestData(username, password)) if (!isTokenAvailable ) {
Log.d("istoken0", isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(username, password))
}
} ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.") } ?: Log.e("fetchDeviceCredentials", "Failed to parse device data.")
} else { } else {
Log.e("fetchDeviceCredentials", "Document does not exist.") Log.e("fetchDeviceCredentials", "Document does not exist.")
@@ -770,13 +872,28 @@ class HomeFragment : Fragment() {
} }
} }
private fun sanitizeDoubleValues(hemoCubeTestData: HemoCubeTestData): HemoCubeTestData {
hemoCubeTestData::class.java.declaredFields.forEach { field ->
if (field.type == Double::class.javaObjectType || field.type == Double::class.javaPrimitiveType) {
field.isAccessible = true
val value = field.get(hemoCubeTestData) as Double?
if (value != null && (value.isInfinite() || value.isNaN())) {
field.set(hemoCubeTestData, 0.0) // Replace with a suitable default value
}
}
}
return hemoCubeTestData
}
private fun showUploadDialog(context: Context) { private fun showUploadDialog(context: Context) {
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.upload_db_registration_title) builder.setTitle(R.string.upload_db_registration_title)
builder.setMessage(R.string.upload_db_registration_message) builder.setMessage(R.string.upload_db_registration_message)
builder.setPositiveButton(R.string.upload) { dialog, _ -> builder.setPositiveButton(R.string.upload) { dialog, _ ->
uploadLocalDBData(dialog) // uploadLocalDBData(dialog)
} }
builder.setNegativeButton(R.string.cancel) { dialog, _ -> builder.setNegativeButton(R.string.cancel) { dialog, _ ->
@@ -822,34 +939,34 @@ class HomeFragment : Fragment() {
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result())) val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData -> // userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable) { // if (!userData.molbioFlag && isTokenAvailable) {
resultList.results?.add( // resultList.results?.add(
MolbioV2Result( // MolbioV2Result(
rawData = userData, // rawData = userData,
analysisId = userData._id, // analysisId = userData._id,
analysisDate = "2024-02-08 16:33:56", //userData.reportUploadTime, // analysisDate = "2024-02-08 16:33:56", //userData.reportUploadTime,
analysisStatus = userData.classificationResult, // analysisStatus = userData.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(), // thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(),
interpretation = userData.classificationResult, // interpretation = userData.classificationResult,
testId = userData._id, // testId = userData._id,
testTime = userData.testTime, // testTime = userData.testTime,
collectionTime = "2024-02-08 16:33:56",//userData.testTime, // collectionTime = "2024-02-08 16:33:56",//userData.testTime,
expiryTime = "2024-02-08 16:33:56",//userData.testTime, // expiryTime = "2024-02-08 16:33:56",//userData.testTime,
) // )
) // )
//
// }
} // if (!userData.localFlag) {
// userData.localFlag = true
if (!userData.localFlag) { // hemoCubeViewModel.bulkAddResultTestToDb(userData)
userData.localFlag = true // }
hemoCubeViewModel.bulkAddResultTestToDb(userData) // if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) {
} // userData.molbioFlag = true
if (!userData.molbioFlag && isTokenAvailable && Constants.MOLBIO_INTEGRATION) { // hemoCubeViewModel.uploadResult(resultList)
userData.molbioFlag = true // }
hemoCubeViewModel.uploadResult(resultList) // }
}
}
dialog.dismiss() dialog.dismiss()
} }
@@ -862,37 +979,6 @@ class HomeFragment : Fragment() {
} }
dialog.dismiss() dialog.dismiss()
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val resultList = MolbioV2ResultRequest(mutableListOf(MolbioV2Result()))
userDataList.forEach { userData ->
if (!userData.molbioFlag && isTokenAvailable) {
resultList.results?.add(
MolbioV2Result(
rawData = userData,
analysisId = userData._id,
analysisDate = "2024-02-08 16:33:56",//userData.testTime,
analysisStatus = userData.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[userData.deviceId].toString(),
interpretation = userData.classificationResult,
testId = userData._id,
testTime = "2024-02-08 16:33:56",//userData.testTime,
collectionTime = "2024-02-08 16:33:56",//userData.testTime,
expiryTime = "2024-02-08 16:33:56"//userData.testTime,
)
)
userData.molbioFlag = true
hemoCubeViewModel.uploadResult(resultList)
}
if (!userData.localFlag) {
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
}
dialog.dismiss()
}
} }
// private fun downloadLocalDBData(dialog: DialogInterface) { // private fun downloadLocalDBData(dialog: DialogInterface) {
@@ -1013,6 +1099,7 @@ class HomeFragment : Fragment() {
} }
private fun getDeviceId() { private fun getDeviceId() {
Log.d("HomeFragmentUSb","getDeviceId")
val handler = activity as? DeviceCommunicationHandler val handler = activity as? DeviceCommunicationHandler
handler?.sendAndListenToDevice( handler?.sendAndListenToDevice(
HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND, HemoCubeCommands.DEVICE_CONFIGURATION_COMMAND,
@@ -1020,9 +1107,9 @@ class HomeFragment : Fragment() {
override fun onUsbRead(data: ByteArray?) { override fun onUsbRead(data: ByteArray?) {
data?.let { data?.let {
val receivedData = String(it, Charset.forName("UTF-8")) val receivedData = String(it, Charset.forName("UTF-8"))
Log.d("HomeFragment","USB data"+receivedData)
// Assuming the device ID is the full content of the received data. Adjust if needed. // Assuming the device ID is the full content of the received data. Adjust if needed.
deviceId = deviceId = extractDeviceId(receivedData) // Implement this method based on your data format.
extractDeviceId(receivedData) // Implement this method based on your data format.
if (deviceId.isNotEmpty()) { if (deviceId.isNotEmpty()) {
// Store the deviceId in SharedPreferences // Store the deviceId in SharedPreferences
with(sharedPreference.edit()) { with(sharedPreference.edit()) {
@@ -1039,6 +1126,7 @@ class HomeFragment : Fragment() {
override fun onUsbError(e: Exception?) { override fun onUsbError(e: Exception?) {
// Handle USB communication error // Handle USB communication error
Log.d("HomeFragment","USB read error"+e.toString())
} }
}) })
@@ -1054,8 +1142,8 @@ class HomeFragment : Fragment() {
private fun checkForUpdate() { private fun checkForUpdate() {
try { try {
val db = Firebase.firestore val db = Firebase.firestore
//val deviceId = deviceId
val deviceId="HHH-AAA-ZZZ"
val deviceRef = db.collection("deviceUpdate").document(Constants.DOCUMENT_ID_FOR_UPDATE) val deviceRef = db.collection("deviceUpdate").document(Constants.DOCUMENT_ID_FOR_UPDATE)
deviceRef.get().addOnSuccessListener { documentSnapshot -> deviceRef.get().addOnSuccessListener { documentSnapshot ->
@@ -1155,7 +1243,10 @@ class HomeFragment : Fragment() {
// Register a BroadcastReceiver to receive the download complete event // Register a BroadcastReceiver to receive the download complete event
val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE) val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
requireActivity().registerReceiver(downloadReceiver, filter) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isRegistered = true
requireActivity().registerReceiver(downloadReceiver, filter, RECEIVER_EXPORTED)
}
} }
private fun extractApkUrl(responseBody: ResponseBody): String { private fun extractApkUrl(responseBody: ResponseBody): String {
return responseBody.string() return responseBody.string()
@@ -1200,8 +1291,15 @@ class HomeFragment : Fragment() {
} }
override fun onDestroy() { override fun onDestroy() {
if(isRegistered) {
try {
requireActivity().unregisterReceiver(downloadReceiver)
} catch (e: Exception) {
Log.d("HomeFragment", e.toString())
}
}
super.onDestroy() super.onDestroy()
requireActivity().unregisterReceiver(downloadReceiver)
} }
} }

View File

@@ -116,7 +116,10 @@ class DeviceProvisionFragment : Fragment() {
password = response.data.data?.credentials?.password.toString(), password = response.data.data?.credentials?.password.toString(),
deviceProvisionResponse = response.data.data.toString(), deviceProvisionResponse = response.data.data.toString(),
natsToken = response.data.data?.device?.deviceUser?.natsToken.toString(), natsToken = response.data.data?.device?.deviceUser?.natsToken.toString(),
natsTokenExpiry = response.data.data?.device?.deviceUser?.natsTokenExpiry.toString() natsTokenExpiry = response.data.data?.device?.deviceUser?.natsTokenExpiry.toString(),
globalUpdateIgnore = false,
globalUpdateDone = false,
deviceUpdateAvailable = false
) )
) )
// viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString())) // viewModel.addDeviceId(DeviceData(deviceId = sharedPreferences.getString(Constants.DEVICE_ID, "").toString()))

View File

@@ -149,6 +149,7 @@ class HemoCubeFragment : Fragment() {
hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result -> hemoCubeViewModel.fireBaseUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") { if (result == "Success") {
uploadedToCloud = true uploadedToCloud = true
var accessToken = sharedPreferences.getString(Constants.ACCESS_TOKEN, "").toString()
showToast(R.string.test_upload) showToast(R.string.test_upload)
if (Constants.MOLBIO_INTEGRATION) { if (Constants.MOLBIO_INTEGRATION) {
hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) { hemoCubeViewModel.resultUpload.observe(viewLifecycleOwner) {
@@ -161,6 +162,8 @@ class HemoCubeFragment : Fragment() {
) )
} }
handleReadingFinish() handleReadingFinish()
hemoCubeViewModel.uploadLogs()
hemoCubeViewModel.downloadClientCertificate()
} }
is Result.Error -> { is Result.Error -> {

View File

@@ -143,6 +143,14 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
fun uploadResultfornew(molbioV2ResultRequest: MolbioV2ResultRequest) = viewModelScope.launch {
resultUpload.postValue(Result.Loading())
repository.uploadResults(molbioV2ResultRequest).let {
resultUpload.postValue(it)
}
}
fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch { fun checkUpdate(checkUpdateRequest: CheckUpdateRequest) = viewModelScope.launch {
checkUpdate.postValue(Result.Loading()) checkUpdate.postValue(Result.Loading())
repository.checkUpdate(checkUpdateRequest).let { repository.checkUpdate(checkUpdateRequest).let {
@@ -367,7 +375,7 @@ class HemoCubeViewModel @Inject constructor(
userData.reportUploadTime = SimpleDateFormat( userData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) { when (repository.addTestToDatabasefornew(userData)) {
is Response.Success -> { is Response.Success -> {
fireBaseBulkUpload.postValue("Success") fireBaseBulkUpload.postValue("Success")
updateLocalFlag(userData._id) updateLocalFlag(userData._id)

View File

@@ -11,12 +11,14 @@ import android.content.ServiceConnection
import android.hardware.usb.UsbDevice import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbManager import android.hardware.usb.UsbManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.get import androidx.core.view.get
@@ -43,6 +45,7 @@ open class HemocubeActivity : AppCompatActivity() {
private val TAG = "HemoCube" private val TAG = "HemoCube"
private val broadcastReceiver = object : BroadcastReceiver() { private val broadcastReceiver = object : BroadcastReceiver() {
@RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
synchronized(this) { synchronized(this) {
@@ -82,6 +85,7 @@ open class HemocubeActivity : AppCompatActivity() {
super.attachBaseContext(newBase) super.attachBaseContext(newBase)
} }
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityHemocubeBinding.inflate(layoutInflater) binding = ActivityHemocubeBinding.inflate(layoutInflater)
@@ -106,6 +110,7 @@ open class HemocubeActivity : AppCompatActivity() {
} }
} }
@RequiresApi(Build.VERSION_CODES.O)
open fun connectUsb(permissionGranted: Boolean) { open fun connectUsb(permissionGranted: Boolean) {
Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted") Log.d(TAG, "connectUsb() called, permission variable = $permissionGranted")
val manager = getSystemService(Context.USB_SERVICE) as UsbManager val manager = getSystemService(Context.USB_SERVICE) as UsbManager
@@ -125,6 +130,7 @@ open class HemocubeActivity : AppCompatActivity() {
} }
} }
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("MutableImplicitPendingIntent") @SuppressLint("MutableImplicitPendingIntent")
private fun requestUserPermission(manager: UsbManager, device: UsbDevice) { private fun requestUserPermission(manager: UsbManager, device: UsbDevice) {
val mPendingIntent: PendingIntent val mPendingIntent: PendingIntent
@@ -142,15 +148,21 @@ open class HemocubeActivity : AppCompatActivity() {
} }
val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION) val filter = IntentFilter(Constants.HEMOCUBE_USB_PERMISSION)
registerReceiver(broadcastReceiver, filter) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
registerReceiver(broadcastReceiver, filter, RECEIVER_EXPORTED)
}else{
registerReceiver(broadcastReceiver, filter)
}
manager.requestPermission(device, mPendingIntent) manager.requestPermission(device, mPendingIntent)
} }
fun setupService() { fun setupService() {
val intent = Intent(this, UsbService::class.java) val intent = Intent(this, UsbService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE) bindService(intent, connection, Context.BIND_AUTO_CREATE)
} }
@RequiresApi(Build.VERSION_CODES.O)
open fun reconnectDevice() { open fun reconnectDevice() {
mService.disconnect() mService.disconnect()
unbindService(connection) unbindService(connection)

View File

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

View File

@@ -3,7 +3,7 @@ buildscript {
kotlin_version = '1.8.21' kotlin_version = '1.8.21'
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.2.2' classpath 'com.android.tools.build:gradle:8.3.0'
classpath 'com.google.gms:google-services:4.4.0' classpath 'com.google.gms:google-services:4.4.0'
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.1' classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.1'
} }

View File

@@ -1,6 +1,6 @@
#Mon Jun 12 17:07:47 IST 2023 #Tue Feb 27 16:09:58 IST 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists