Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MediaStore lost access to files after uninstalling the app or clearing its data #103

Open
TurKurT656 opened this issue Nov 7, 2022 · 7 comments
Labels
bug Something isn't working wontfix This will not be worked on

Comments

@TurKurT656
Copy link

Library version: 1.5.1
OS version: [Android 12]
Device model: [Emulator Pixel 5]

Describe the bug
I'm creating a txt file in Downloads folder with this code:

fun writeToConfig() {
    val file = MediaStoreCompat.createDownload(
        context,
        FileDescription("config-test.txt", "", "text/plain"),
        CreateMode.REUSE,
    )
    file?.openOutputStream(true).use {
        it?.write("HelloWorld\n".toByteArray())
    }
}

And I'm reading the file with this approach:

fun readConfig() {
    val file = MediaStoreCompat.fromFileName(context, MediaType.DOWNLOADS, "config-test.txt")
    file?.openInputStream()?.use {
        val text = it.readBytes().toString(Charsets.UTF_8)
        logD(text)
    }
}

Everything works fine. But after I uninstall the app and reinstall it, when I call the readConfig() function, the file variable is null. and strange thing is that when i call the writeToConfig() function again, instead of reusing the same file it creates a new file with this name: "config-test (1).txt".
So after I saw this, I tried to retest the code and I deleted the files (""config-test.txt" and "config-test (1).txt"). After force stopping and relaunching the app I got an Exception: android.database.sqlite.SQLiteConstraintException.
After this exception you cant work with this code anymore and the only way to fix this crash is that you need to wipe data from your device settings.
So we have two bugs in here

To Reproduce

  1. Use MediaStoreCompat to write/read a file in Downloads folder.
  2. Unistall the app
  3. Install the app
  4. (Bug 1 appears)
  5. Go to Downloads folder and manually delete the file.
  6. Force stop the app
  7. launch the app again.
  8. (Bug 2 --> Crash)

Stacktrace

FATAL EXCEPTION: main
Process: app.source.getcontact, PID: 8835
java.lang.RuntimeException: Unable to create application com.test.myapp.DebugApp: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: files._data (code 2067 SQLITE_CONSTRAINT_UNIQUE)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6730)
at android.app.ActivityThread.access$1500(ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2053)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: files._data (code 2067 SQLITE_CONSTRAINT_UNIQUE)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:178)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:557)
at android.content.ContentResolver.insert(ContentResolver.java:2193)
at android.content.ContentResolver.insert(ContentResolver.java:2155)
at com.anggrayudi.storage.media.MediaStoreCompat.createMedia(MediaStoreCompat.kt:143)
at com.anggrayudi.storage.media.MediaStoreCompat.createDownload(MediaStoreCompat.kt:34)
at com.test.myapp.ConfigCache.writeToConfig(ConfigCacheImpl.kt:37)
at com.test.myapp.DebugApp.onCreate(DebugApp.kt:7)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1211)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6725)
at android.app.ActivityThread.access$1500(ActivityThread.java:247) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2053) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loopOnce(Looper.java:201) 
at android.os.Looper.loop(Looper.java:288) 
at android.app.ActivityThread.main(ActivityThread.java:7839) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 
@anggrayudi
Copy link
Owner

I'm also able to reproduce these two issues. But, if you try to use another name, e.g. another-config-test.txt, then the error will be disappear. These are OS level issues, not the library. I presume the OS is trying to insert the same file name into SAF database, but the previous name still exists in the database even though the actual file was deleted, hence the unique constraint is not satisfied.

FYI, if you uninstall the app, then all of your files created with MediaStore will be unbound from your app. I don't recommend anyone to use MediaStore if you want to read the files again in the future. Use DocumentFile with storage access instead. MediaStore is only appropriate for write and forget cases, for example saving screenshots and receipts. Additionally, to avoid this crash on your app, generate unique file name for every file creation. You can append random string, integer, or timestamp to your file name.

This issue can't be fixed from my side, but I'll leave it open until Android team resolve it. I'll raise this issue on Google Issue Tracker and will put the link here soon.

@anggrayudi anggrayudi added bug Something isn't working wontfix This will not be worked on labels Nov 28, 2022
@anggrayudi anggrayudi changed the title MediaStoreCompat can't use saved files after uninstalling the app MediaStore lost access to files after uninstalling the app or clearing its data Nov 28, 2022
@TurKurT656
Copy link
Author

I'm trying to implement a ConfigHelper (a configuration file that holds list of key value pairs) that survives from uninstalling app.
As described https://developer.android.com/training/data-storage I can only use MediaStore (SharedPreferences doesn't survive from uninstall and SAF always ask from user to choose a file). So I cannot use DocumentFile because I cannot ask from user to select a file that I need to do some configurations for the app. Actually this ConfigHelper is more like SharedPreferences with the ability of surviving from uninstall.

@anggrayudi
Copy link
Owner

I didn't find any article about ConfigHelper, can you post the link here @TurKurT656?

@TurKurT656
Copy link
Author

@anggrayudi Its my own custom class that behaves like SharedPrefrences. I've named it ConfigHelper its not a public library or something :). Sorry if I confused you

@lrq3000
Copy link

lrq3000 commented Jan 4, 2023

I encountered the same issue, as discussed in lolo-io/OneList#41 (comment) . The problem is that DocumentFile and DocumentFileHelper never allow to get access to any file whatsoever. I actually reused a helper function that @anggrayudi you mentioned elsewhere, I guess you will recognize what I mean if you see my implementation:

https://github.com/lrq3000/OneList/blob/master/app/src/main/java/com/lolo/io/onelist/util/Utils.kt#L110

This helper function tries to use a DocumentFile, and if it fails, it uses a MediaStore to create or reuse a file. I noticed that in practice, it always uses a DocumentFile. All my attempts at using a DocumentFile manually just miserably failed:

https://github.com/lrq3000/OneList/blob/master/app/src/main/java/com/lolo/io/onelist/dialogs/StorageDialog.kt#L74

I will ask another related question elsewhere, but the culprit is that it appears that all the DocumentFile and DocumentFileCompat functions are now broken. So this issue needs fixing.

@ngminhkhoa
Copy link

ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION can solve your problem from api 30 and above

@lrq3000
Copy link

lrq3000 commented Mar 23, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

4 participants