diff --git a/apps/flipcash/app/src/main/AndroidManifest.xml b/apps/flipcash/app/src/main/AndroidManifest.xml
index 361f0a0c3..525dd6a7c 100644
--- a/apps/flipcash/app/src/main/AndroidManifest.xml
+++ b/apps/flipcash/app/src/main/AndroidManifest.xml
@@ -9,8 +9,6 @@
-
-
diff --git a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/internal/extensions/Bitmap.kt b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/internal/extensions/Bitmap.kt
index f6502ed16..fb5ce9e91 100644
--- a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/internal/extensions/Bitmap.kt
+++ b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/internal/extensions/Bitmap.kt
@@ -1,29 +1,45 @@
package com.flipcash.app.core.internal.extensions
+import android.content.ContentResolver
+import android.content.ContentValues
import android.graphics.Bitmap
+import android.os.Environment
+import android.provider.MediaStore
import com.getcode.utils.ErrorUtils
import com.getcode.utils.timedTrace
-import java.io.File
-import java.io.FileOutputStream
-fun Bitmap.save(destination: File, name: () -> String): Boolean {
+fun Bitmap.save(contentResolver: ContentResolver, name: () -> String): Boolean {
val filename = name()
- if (!destination.exists()) {
- if (!destination.mkdirs()) {
- return false
- }
- }
- val dest = File(destination, filename)
return timedTrace("saving bitmap") {
try {
- FileOutputStream(dest).use { out ->
+ val contentValues = ContentValues().apply {
+ put(MediaStore.Images.Media.DISPLAY_NAME, filename)
+ put(MediaStore.Images.Media.MIME_TYPE, "image/png")
+ put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
+ put(MediaStore.Images.Media.IS_PENDING, 1)
+ }
+
+ val uri = contentResolver.insert(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ contentValues
+ ) ?: return@timedTrace false
+
+ contentResolver.openOutputStream(uri)?.use { out ->
compress(Bitmap.CompressFormat.PNG, 90, out)
+ } ?: run {
+ contentResolver.delete(uri, null, null)
+ return@timedTrace false
}
+
+ contentValues.clear()
+ contentValues.put(MediaStore.Images.Media.IS_PENDING, 0)
+ contentResolver.update(uri, contentValues, null, null)
+
+ return@timedTrace true
} catch (e: Exception) {
ErrorUtils.handleError(e)
return@timedTrace false
}
- return@timedTrace true
}
}
\ No newline at end of file
diff --git a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/storage/MediaSaver.kt b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/storage/MediaSaver.kt
new file mode 100644
index 000000000..19070c9b5
--- /dev/null
+++ b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/storage/MediaSaver.kt
@@ -0,0 +1,15 @@
+package com.flipcash.app.core.storage
+
+import android.content.Context
+import android.graphics.Bitmap
+import com.flipcash.app.core.internal.extensions.save
+import dagger.hilt.android.qualifiers.ApplicationContext
+import javax.inject.Inject
+
+class MediaSaver @Inject constructor(
+ @ApplicationContext private val context: Context
+) {
+ fun saveBitmap(bitmap: Bitmap, filename: String): Boolean {
+ return bitmap.save(context.contentResolver) { filename }
+ }
+}
diff --git a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/storage/MediaScanner.kt b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/storage/MediaScanner.kt
deleted file mode 100644
index 2a82803b9..000000000
--- a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/storage/MediaScanner.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.flipcash.app.core.storage
-
-import android.content.Context
-import android.media.MediaScannerConnection
-import dagger.hilt.android.qualifiers.ApplicationContext
-import java.io.File
-import javax.inject.Inject
-
-class MediaScanner @Inject constructor(
- @ApplicationContext private val context: Context
-) {
- fun scan(directory: File) {
- MediaScannerConnection.scanFile(context, arrayOf(directory.toString()), null, null)
- }
-}
\ No newline at end of file
diff --git a/apps/flipcash/features/backupkey/src/main/kotlin/com/flipcash/app/backupkey/internal/BackupKeyScreenViewModel.kt b/apps/flipcash/features/backupkey/src/main/kotlin/com/flipcash/app/backupkey/internal/BackupKeyScreenViewModel.kt
index cec48a104..7cca89286 100644
--- a/apps/flipcash/features/backupkey/src/main/kotlin/com/flipcash/app/backupkey/internal/BackupKeyScreenViewModel.kt
+++ b/apps/flipcash/features/backupkey/src/main/kotlin/com/flipcash/app/backupkey/internal/BackupKeyScreenViewModel.kt
@@ -1,7 +1,7 @@
package com.flipcash.app.backupkey.internal
import com.flipcash.app.accesskey.BaseAccessKeyViewModel
-import com.flipcash.app.core.storage.MediaScanner
+import com.flipcash.app.core.storage.MediaSaver
import com.flipcash.services.user.UserManager
import com.getcode.libs.qr.QRCodeGenerator
import com.getcode.opencode.managers.MnemonicManager
@@ -17,13 +17,13 @@ import kotlin.time.Duration.Companion.seconds
internal class BackupKeyScreenViewModel @Inject constructor(
resources: ResourceHelper,
mnemonicManager: MnemonicManager,
- mediaScanner: MediaScanner,
+ mediaSaver: MediaSaver,
userManager: UserManager,
qrCodeGenerator: QRCodeGenerator,
) : BaseAccessKeyViewModel(
resources,
mnemonicManager,
- mediaScanner,
+ mediaSaver,
userManager,
qrCodeGenerator
) {
diff --git a/apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/accesskey/LoginAccessKeyViewModel.kt b/apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/accesskey/LoginAccessKeyViewModel.kt
index 96c73a78c..7c545c92d 100644
--- a/apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/accesskey/LoginAccessKeyViewModel.kt
+++ b/apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/accesskey/LoginAccessKeyViewModel.kt
@@ -5,7 +5,7 @@ import com.flipcash.app.analytics.Action
import com.flipcash.app.analytics.Button
import com.flipcash.app.analytics.FlipcashAnalyticsService
import com.flipcash.app.auth.AuthManager
-import com.flipcash.app.core.storage.MediaScanner
+import com.flipcash.app.core.storage.MediaSaver
import com.flipcash.app.userflags.UserFlagsCoordinator
import com.flipcash.services.user.UserManager
import com.getcode.libs.qr.QRCodeGenerator
@@ -22,12 +22,12 @@ class LoginAccessKeyViewModel @Inject constructor(
resources: ResourceHelper,
mnemonicManager: MnemonicManager,
qrCodeGenerator: QRCodeGenerator,
- mediaScanner: MediaScanner,
+ mediaSaver: MediaSaver,
userManager: UserManager,
private val userFlags: UserFlagsCoordinator,
private val authManager: AuthManager,
private val analytics: FlipcashAnalyticsService,
-): BaseAccessKeyViewModel(resources, mnemonicManager, mediaScanner, userManager, qrCodeGenerator) {
+): BaseAccessKeyViewModel(resources, mnemonicManager, mediaSaver, userManager, qrCodeGenerator) {
suspend fun onWroteDownInstead(): Result {
trackButton(Button.WroteAccessKey)
diff --git a/apps/flipcash/shared/accesskey/src/main/kotlin/com/flipcash/app/accesskey/BaseAccessKeyViewModel.kt b/apps/flipcash/shared/accesskey/src/main/kotlin/com/flipcash/app/accesskey/BaseAccessKeyViewModel.kt
index 42996fd37..10edc9b5f 100644
--- a/apps/flipcash/shared/accesskey/src/main/kotlin/com/flipcash/app/accesskey/BaseAccessKeyViewModel.kt
+++ b/apps/flipcash/shared/accesskey/src/main/kotlin/com/flipcash/app/accesskey/BaseAccessKeyViewModel.kt
@@ -8,13 +8,11 @@ import android.graphics.Path
import android.graphics.RectF
import android.graphics.Shader
import android.graphics.Typeface
-import android.os.Environment
import androidx.core.graphics.applyCanvas
import androidx.core.graphics.createBitmap
import androidx.core.graphics.drawable.toBitmap
import androidx.lifecycle.viewModelScope
-import com.flipcash.app.core.internal.extensions.save
-import com.flipcash.app.core.storage.MediaScanner
+import com.flipcash.app.core.storage.MediaSaver
import com.flipcash.app.theme.internal.Flipcash2ColorSpec
import com.flipcash.services.user.UserManager
import com.flipcash.shared.accesskey.R
@@ -63,7 +61,7 @@ data class AccessKeyUiModel(
abstract class BaseAccessKeyViewModel(
private val resources: ResourceHelper,
private val mnemonicManager: MnemonicManager,
- private val mediaScanner: MediaScanner,
+ private val mediaSaver: MediaSaver,
userManager: UserManager,
private val qrCodeGenerator: QRCodeGenerator
) : ViewModel() {
@@ -129,22 +127,12 @@ abstract class BaseAccessKeyViewModel(
uiFlow.update { it.copy(exportState = LoadingSuccessState(loading = true)) }
val bitmap = uiFlow.value.accessKeyBitmap
?: return Result.failure(IllegalStateException("No access key?"))
- val destination =
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
return withContext(Dispatchers.IO) {
runCatching {
- val result = bitmap.save(
- destination = destination,
- name = {
- val date: DateFormat = SimpleDateFormat("yyy-MM-dd-h-mm", Locale.CANADA)
- "Flipcash-Recovery-${date.format(Date())}.png"
- }
- )
- if (result) {
- mediaScanner.scan(destination)
- }
- result
+ val date: DateFormat = SimpleDateFormat("yyy-MM-dd-h-mm", Locale.CANADA)
+ val filename = "Flipcash-Recovery-${date.format(Date())}.png"
+ mediaSaver.saveBitmap(bitmap, filename)
}
}.onFailure {
getAccessKeySaveError()