From 53bf35ac383a1e0bcc67fc0e8def37b39174340f Mon Sep 17 00:00:00 2001 From: Mariya Date: Tue, 12 Dec 2023 12:18:42 +0530 Subject: [PATCH] OFFLINE FEATURE ADDED- with csv file data downloading format added --- app/src/debug/res/drawable/downloads.xml | 5 ++ .../com/example/hpostesting/data/CsvWriter.kt | 50 +++++++++++++++++++ .../adapter/OfflineUserListAdapter.kt | 2 +- .../dashboard/DashboardActivity.kt | 6 ++- .../presentation/dashboard/HomeFragment.kt | 24 ++++++++- .../dashboard/ui/home/HomeViewModel.kt | 13 ----- .../presentation/hemocube/HemoCubeFragment.kt | 3 ++ .../hemocube/HemoCubeViewModel.kt | 39 +++++++++++++++ app/src/main/res/layout/fragment_home.xml | 10 ++++ .../res/layout/offline_user_list_view.xml | 4 +- 10 files changed, 138 insertions(+), 18 deletions(-) create mode 100644 app/src/debug/res/drawable/downloads.xml create mode 100644 app/src/main/java/com/example/hpostesting/data/CsvWriter.kt delete mode 100644 app/src/main/java/com/example/hpostesting/presentation/dashboard/ui/home/HomeViewModel.kt diff --git a/app/src/debug/res/drawable/downloads.xml b/app/src/debug/res/drawable/downloads.xml new file mode 100644 index 0000000..772735f --- /dev/null +++ b/app/src/debug/res/drawable/downloads.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/java/com/example/hpostesting/data/CsvWriter.kt b/app/src/main/java/com/example/hpostesting/data/CsvWriter.kt new file mode 100644 index 0000000..c7f3c4e --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/data/CsvWriter.kt @@ -0,0 +1,50 @@ +package com.example.hpostesting.data + +import android.content.Context +import android.os.Environment +import java.io.File +import java.io.FileWriter +import java.io.IOException + +class CsvWriter(private val context: Context) { + + fun writeCsv(fileName: String, data: List>): Boolean { + try { + val filePath = File(getExternalStorageDirectory(), fileName) + val writer = FileWriter(filePath) + + // Write header row + val header = arrayOf( + "ID", + "Blood Group", + "Birth Year", + "Classification Result", + "Test Time", + "User Image URL", + "Name" + ) + writer.write(header.joinToString(",") + "\n") + + // Write data rows + for (line in data) { + writer.write(line.joinToString(",") + "\n") + } + + writer.close() + return true + } catch (e: IOException) { + e.printStackTrace() + return false + } + } + + private fun getExternalStorageDirectory(): File { + val folder = File(Environment.getExternalStorageDirectory(), "HposFolder") + + if (!folder.exists()) { + folder.mkdirs() + } + + return folder + } +} 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 afa492b..dbeaf5e 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 @@ -97,7 +97,7 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int) DataHolder.selectedTest = UserData( _id = userList._id, bloodGroup = userList.bloodGroup, - incubationTime = userList.incubationTime + incubationTime = userList.incubationTime, ) view.findNavController() .navigate(R.id.action_nav_home_to_mainActivity) 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 02b1df6..9eb8374 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 @@ -3,6 +3,7 @@ package com.example.hpostesting.presentation.dashboard import android.os.Bundle import android.view.Menu import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.drawerlayout.widget.DrawerLayout import androidx.navigation.findNavController @@ -10,6 +11,7 @@ import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.navigateUp import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController +import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.google.android.material.navigation.NavigationView import com.google.firebase.appdistribution.FirebaseAppDistribution import com.google.firebase.appdistribution.FirebaseAppDistributionException @@ -26,7 +28,7 @@ class DashboardActivity : AppCompatActivity() { private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var binding: ActivityDashboardBinding - + private val viewModel: HemoCubeViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -60,6 +62,8 @@ class DashboardActivity : AppCompatActivity() { } + + override fun onResume() { super.onResume() diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt index 9b41ee5..ac87e7b 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt @@ -47,7 +47,7 @@ class HomeFragment : Fragment() { private lateinit var rvAdapter: UserListAdapter private var batLevel: Int = 0 // Initialize with a default value, or obtain the actual battery level private lateinit var adapter: OfflineUserListAdapter - + private val homeViewModel: HemoCubeViewModel by activityViewModels() private lateinit var sharedPreference: SharedPreferences override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -121,6 +121,10 @@ class HomeFragment : Fragment() { binding.uploadData.setOnClickListener { showUploadDialog(requireContext()) } + + binding.btnSaveLocal.setOnClickListener { + downloadCsv() + } binding.btnNewKit.setOnClickListener { with(sharedPreference.edit()) { putString(Constants.KIT_NUMBER, "") @@ -376,4 +380,22 @@ class HomeFragment : Fragment() { super.onDestroyView() _binding = null } + + + + private fun downloadCsv() { + context?.let { context -> + val success = homeViewModel.getLocalUserDataForCsv(context) + if (success) { + // Provide feedback to the user if needed + Toast.makeText(context, "CSV file downloaded successfully", Toast.LENGTH_SHORT).show() + } else { + // Handle the case where CSV file generation failed + Toast.makeText(context, "Failed to download CSV file", Toast.LENGTH_SHORT).show() + } + } + } + + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/ui/home/HomeViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/ui/home/HomeViewModel.kt deleted file mode 100644 index 4b02588..0000000 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/ui/home/HomeViewModel.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.hpostesting.presentation.dashboard.ui.home - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel - -class HomeViewModel : ViewModel() { - - private val _text = MutableLiveData().apply { - value = "This is home Fragment" - } - val text: LiveData = _text -} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt index eb271c5..a698df9 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeFragment.kt @@ -373,6 +373,9 @@ class HemoCubeFragment : Fragment() { led1Buffer = led1BufferForDevice led2Buffer = led2BufferForDevice appVersion = version + this.name = testDetails?.name.toString() + this.birthYear = testDetails?.birthYear.toString() + this.userImageURL = testDetails?.userImageURL.toString() this.led1Sample = led1Sample this.led2Sample = led2Sample this.led1Average = led1Average 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 868e255..5f2318a 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 @@ -7,6 +7,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.example.hpostesting.data.CsvWriter import com.example.hpostesting.data.DataHolder import com.example.hpostesting.data.NetworkStatusLiveData import com.example.hpostesting.data.constant.Constants @@ -102,6 +103,9 @@ class HemoCubeViewModel @Inject constructor( testDetails?.deviceRatio = DataHolder.hemoCubeTestData?.deviceRatio testDetails?.calculatedRatio = DataHolder.hemoCubeTestData?.calculatedRatio testDetails?.coefficients = DataHolder.hemoCubeTestData?.coefficients + testDetails?.name = DataHolder.hemoCubeTestData?.name.toString() + testDetails?.birthYear = DataHolder.hemoCubeTestData?.birthYear.toString() + testDetails?.userImageURL = DataHolder.hemoCubeTestData?.userImageURL.toString() testDetails?.classificationResult = DataHolder.hemoCubeTestData?.classificationResult!! } @@ -187,6 +191,41 @@ class HemoCubeViewModel @Inject constructor( hemoCubeDao.insertAll(userData) } + + fun getLocalUserDataForCsv(context: Context): Boolean { + val localUserDataLiveData: LiveData> = hemoCubeDao.getAll() + + // Observe the LiveData to get the actual data when available + localUserDataLiveData.observeForever { localUserData -> + localUserData?.let { + val csvData = mutableListOf>() + + it.forEach { userData -> + csvData.add( + arrayOf( + userData._id, + userData.name, + userData.bloodGroup, + userData.birthYear, + userData.classificationResult, + userData.testTime.toString(), + userData.userImageURL + ) + ) + } + + val csvWriter = CsvWriter(context) + csvWriter.writeCsv("userData.csv", csvData) + + // Remove the observer to avoid leaks + localUserDataLiveData.removeObserver {} + } + } + + return true // Assuming success, you might want to modify this based on your actual logic + } + + fun deleteById(userId: String) = viewModelScope.launch { hemoCubeDao.deleteById(id = userId) } diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 87f4636..c56295c 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -100,6 +100,16 @@ app:layout_constraintTop_toBottomOf="@+id/btn_submit" tools:listitem="@layout/offline_user_list_view" /> + + + + tools:text="Name: Mariya" /> + tools:text="UserID: Mariya" />