diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 958b0d75..06d5123c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,8 @@ + + -> if (isGranted.all { it.value }) { // phone permissions granted - if(isGranted.containsKey(CALL_PHONE) || isGranted.containsKey(READ_PHONE_STATE)){ + if (isGranted.containsKey(CALL_PHONE) || isGranted.containsKey(READ_PHONE_STATE)) { binding.swiperefresh.isRefreshing = true setDefaultSubscriptionId() onRefresh() @@ -58,6 +58,21 @@ class MainActivity : AbstractBaseActivity(), SwipeRefreshLayout.OnRefreshListene } } + private val requestStoragePermission = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> + // Because of api version some device need permission to save file in storage + // so a contract is created + val canRead = permissions[READ_EXTERNAL_STORAGE] ?: false + val canWrite = permissions[WRITE_EXTERNAL_STORAGE] ?: false + if (canRead && canWrite) { + // when user grant read and write permission, + // export the file to download folder + exportAsCsv() + } else { + // User did not grant permission so an error is displayed for the user to see + showSnackbar(R.string.export_error_saving_file) + } + } + override fun onCreate(savedInstanceState: Bundle?) { val splashScreen = installSplashScreen() // Apply dynamic colors here to avoid losing them due to splash screen: https://github.com/material-components/material-components-android/issues/2555 @@ -117,7 +132,7 @@ class MainActivity : AbstractBaseActivity(), SwipeRefreshLayout.OnRefreshListene override fun onOptionsItemSelected(item: MenuItem): Boolean { Log.d(TAG, "onOptionsItemSelected($item)") - return when(item.itemId) { + return when (item.itemId) { R.id.preferences -> { Intent(this, PreferenceActivity::class.java).apply { startActivity(this) @@ -125,7 +140,20 @@ class MainActivity : AbstractBaseActivity(), SwipeRefreshLayout.OnRefreshListene true } R.id.export -> { - exportAsCsv() + if ( + Build.VERSION.SDK_INT <= Build.VERSION_CODES.P && + !hasPermissions(READ_EXTERNAL_STORAGE) && + !hasPermissions(WRITE_EXTERNAL_STORAGE) + ) { + // this if statement check if this device is with in the version that needs + // permission to save file. It also check if read and write permission not granted. + // It then launch the contract for the user to grant the permission + requestStoragePermission.launch(arrayOf(WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE)) + } else { + // modern device does not need permission to save file in public folder like + // download + exportAsCsv() + } true } android.R.id.home -> { @@ -136,20 +164,20 @@ class MainActivity : AbstractBaseActivity(), SwipeRefreshLayout.OnRefreshListene } } + /** + * Export a CSV file to the Downloads folder. + */ private fun exportAsCsv() { launch { - val content = buildCsv() - try { + val content = buildCsv() val filename = "prepaid-balance-${System.currentTimeMillis()}.csv" writeToFileInDownloads(content, filename) showSnackbar(getString(R.string.export_saved_file, filename)) - return@launch } catch (e: Exception) { Log.e(TAG, "Error saving file", e) + showSnackbar(R.string.export_error_saving_file) } - - showSnackbar(R.string.export_error_saving_file) } }