Offline storage

This commit is contained in:
mohamedkaif356
2023-08-18 12:20:21 +05:30
parent 5d2830d515
commit dc4291eaa8
9 changed files with 149 additions and 55 deletions

View File

@@ -65,6 +65,7 @@ dependencies {
implementation 'com.google.android.gms:play-services-auth:20.6.0' implementation 'com.google.android.gms:play-services-auth:20.6.0'
implementation 'com.google.android.gms:play-services-location:21.0.1' implementation 'com.google.android.gms:play-services-location:21.0.1'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
implementation 'com.google.android.things:androidthings:1.0'
// Testing // Testing
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'

View File

@@ -2,6 +2,7 @@ package com.example.hpostesting.data.dao
import androidx.room.TypeConverter import androidx.room.TypeConverter
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.google.common.reflect.TypeToken
import com.google.gson.Gson import com.google.gson.Gson
class Converters { class Converters {
@@ -24,23 +25,14 @@ class Converters {
} }
} }
// @TypeConverter @TypeConverter
// fun fromLocation(value: String?): UserData.Location? { fun fromList(list: List<Double>): String {
// return if (value != null) { return Gson().toJson(list)
// gson.fromJson(value, UserData.Location::class.java) }
// } else {
// null @TypeConverter
// } fun toList(json: String): List<Double> {
// } val type = object : TypeToken<List<Double>>() {}.type
// return Gson().fromJson(json, type)
// }
//
// @TypeConverter
// fun toLocation(location: UserData.Location?): String? {
// return if (location != null) {
// gson.toJson(location)
// } else {
// null
// }
// }
} }

View File

@@ -0,0 +1,24 @@
package com.example.hpostesting.data.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
@Dao
interface DeviceDao {
@Query("SELECT * from device_table")
fun getAll(): LiveData<List<HemoCubeTestData>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(deviceData: DeviceData)
@Query("SELECT * FROM device_table WHERE deviceId = :id")
suspend fun getUserByID(id: String): HemoCubeTestData
@Query("DELETE FROM device_table WHERE deviceId = :id")
suspend fun deleteById(id: String)
}

View File

@@ -11,7 +11,7 @@ import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.google.android.datatransport.runtime.dagger.Provides import com.google.android.datatransport.runtime.dagger.Provides
import javax.inject.Singleton import javax.inject.Singleton
@Database(entities = [UserData::class, HemoCubeTestData::class], version = 2, exportSchema = false) @Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 3, exportSchema = false)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() { abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao

View File

@@ -1,9 +1,13 @@
package com.example.hpostesting.data.model.patient package com.example.hpostesting.data.model.patient
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.firebase.firestore.PropertyName import com.google.firebase.firestore.PropertyName
@Entity(tableName = "device_table")
data class DeviceData( data class DeviceData(
@PrimaryKey
var _id: String = "",
@get:PropertyName("deviceId") @set:PropertyName("deviceId") @get:PropertyName("deviceId") @set:PropertyName("deviceId")
var deviceId: String = "", var deviceId: String = "",
@get:PropertyName("deviceType") @set:PropertyName("deviceType") @get:PropertyName("deviceType") @set:PropertyName("deviceType")

View File

@@ -15,6 +15,7 @@ data class HemoCubeTestData(
var testType: String? = "HEMOCUBE", var testType: String? = "HEMOCUBE",
var testTime: String? = "", var testTime: String? = "",
var testStatus: Boolean? = false, var testStatus: Boolean? = false,
var localFlag: Boolean = false,
var deviceId: String? = "", var deviceId: String? = "",
var deviceSerialNumber: String = "", var deviceSerialNumber: String = "",
var deviceType: String = "HEMOCUBE", var deviceType: String = "HEMOCUBE",

View File

@@ -14,8 +14,10 @@ import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.adapter.UserListAdapter import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.firestore.ktx.firestore import com.google.firebase.firestore.ktx.firestore
@@ -30,6 +32,7 @@ class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private val viewModel: TestRightViewModel by activityViewModels() private val viewModel: TestRightViewModel by activityViewModels()
private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter private lateinit var rvAdapter: UserListAdapter
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
override fun onCreateView( override fun onCreateView(
@@ -44,8 +47,14 @@ class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel.allUserData.observe(viewLifecycleOwner) { userData -> viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
if (userData.isNotEmpty()) {
}
deleteIncompleteRegistrations(userData) deleteIncompleteRegistrations(userData)
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteHemoCubeIncompleteRegistrations(userData)
}
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected -> viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) { if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE binding.internetAvailableCL.visibility = View.VISIBLE
@@ -174,6 +183,11 @@ class HomeFragment : Fragment() {
val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE
binding.uploadData.visibility = uploadDataVisibility binding.uploadData.visibility = uploadDataVisibility
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE
binding.uploadData.visibility = uploadDataVisibility
}
} }
private fun showUploadDialog(context: Context) { private fun showUploadDialog(context: Context) {
val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
@@ -209,16 +223,41 @@ class HomeFragment : Fragment() {
).show() ).show()
} }
} }
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
if (userDataList.isEmpty()) {
dialog.dismiss()
} else {
userDataList.forEach { userData ->
userData.localFlag = true
hemoCubeViewModel.bulkAddResultTestToDb(userData)
}
dialog.dismiss()
Toast.makeText(
requireContext(),
R.string.upload_success_message,
Toast.LENGTH_SHORT
).show()
}
}
} }
private fun deleteIncompleteRegistrations(userDataList: List<UserData>) { private fun deleteIncompleteRegistrations(userDataList: List<UserData>) {
userDataList.forEach { userData -> userDataList.forEach { userData ->
if (userData._id.isEmpty()) { if (userData.csvPath.isEmpty()) {
viewModel.deleteById(userData._id) viewModel.deleteById(userData._id)
} }
} }
} }
private fun deleteHemoCubeIncompleteRegistrations(userDataList: List<HemoCubeTestData>) {
userDataList.forEach { userData ->
if (userData.testTime?.isEmpty() == false) {
hemoCubeViewModel.deleteById(userData._id)
}
}
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View File

@@ -132,6 +132,11 @@ class HemoCubeFragment : Fragment() {
showToast("Test Results Uploaded Successfully") showToast("Test Results Uploaded Successfully")
startActivity(Intent(requireActivity(), DashboardActivity::class.java)) startActivity(Intent(requireActivity(), DashboardActivity::class.java))
} }
if (result == "Local") {
showToast("Internet not available, test details stored locally")
startActivity(Intent(requireActivity(), DashboardActivity::class.java))
}
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
} }
@@ -321,11 +326,20 @@ class HemoCubeFragment : Fragment() {
} }
private fun handleValidResult(validString: String, fullReadOutput: String) { private fun handleValidResult(validString: String, fullReadOutput: String) {
try {
val result = validString.split(" ") val result = validString.split(" ")
if (result.size == 8) { if (result.size == 8) {
val deviceSerialNo = result[2] val deviceSerialNo = result[2]
val led1BufferForDevice = result[3].toDoubleOrNull() val led1BufferForDevice = if (isUsingExistingBuffer) {
val led2BufferForDevice = result[4].toDoubleOrNull() sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull()
} else {
result[3].toDoubleOrNull()
}
val led2BufferForDevice = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()
} else {
result[4].toDoubleOrNull()
}
val led1Sample = result[5].toDoubleOrNull() val led1Sample = result[5].toDoubleOrNull()
val led2Sample = result[6].toDoubleOrNull() val led2Sample = result[6].toDoubleOrNull()
val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0) val led1Average = log10(led1BufferForDevice?.div(led1Sample!!) ?: 0.0)
@@ -334,17 +348,8 @@ class HemoCubeFragment : Fragment() {
DataHolder.hemoCubeTestData?.apply { DataHolder.hemoCubeTestData?.apply {
deviceId = deviceSerialNo deviceId = deviceSerialNo
led1Buffer = if (isUsingExistingBuffer) { led1Buffer = led1BufferForDevice
sharedPreferences.getString(Constants.BUFFER_VALUE_1, "")?.toDoubleOrNull() led2Buffer = led2BufferForDevice
} else {
led1BufferForDevice
}
led2Buffer = if (isUsingExistingBuffer) {
sharedPreferences.getString(Constants.BUFFER_VALUE_2, "")?.toDoubleOrNull()
} else {
led2BufferForDevice
}
this.led1Sample = led1Sample this.led1Sample = led1Sample
this.led2Sample = led2Sample this.led2Sample = led2Sample
this.led1Average = led1Average this.led1Average = led1Average
@@ -364,6 +369,11 @@ class HemoCubeFragment : Fragment() {
) )
} }
} }
} catch (e: Exception) {
}
} }
private fun showToast(message: String) { private fun showToast(message: String) {

View File

@@ -13,6 +13,8 @@ import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import com.example.hpostesting.data.repository.DatabaseRepository import com.example.hpostesting.data.repository.DatabaseRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@@ -37,6 +39,7 @@ class HemoCubeViewModel @Inject constructor(
// Get the device ID of the device you want to retrieve data for (e.g., the first device in the list) // Get the device ID of the device you want to retrieve data for (e.g., the first device in the list)
private val _networkStatusLiveData = NetworkStatusLiveData(context) private val _networkStatusLiveData = NetworkStatusLiveData(context)
val allUserData = hemoCubeDao.getAll()
val deviceData = MutableLiveData<DeviceData?>() val deviceData = MutableLiveData<DeviceData?>()
val networkStatusLiveData: LiveData<Boolean> val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData get() = _networkStatusLiveData
@@ -56,6 +59,7 @@ class HemoCubeViewModel @Inject constructor(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
hemoCubeDao.insertAll(testDetails!!) hemoCubeDao.insertAll(testDetails!!)
fireBaseUpload.postValue("Local")
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Testdb", "Upload failed: ${e.message}") Log.e("Testdb", "Upload failed: ${e.message}")
@@ -119,4 +123,23 @@ class HemoCubeViewModel @Inject constructor(
} }
} }
} }
fun bulkAddResultTestToDb(userData: HemoCubeTestData) {
viewModelScope.launch {
userData.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
when (repository.addTestToDatabase(userData)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}
else -> {}
}
}
}
fun deleteById(userId: String) = viewModelScope.launch {
hemoCubeDao.deleteById(id = userId)
}
} }