I am working on a widget that is built from the im...
# glance
j
I am working on a widget that is built from the images example: https://github.com/android/platform-samples/blob/main/samples/user-interface/appwidgets/src/main/java/com/example/platform/ui/appwidgets/glance/image/ImageWorker.kt The difference is I am first calling an API and storing images to cacheDir then displays them on the widget with a "next" button to cycle through images. My problem: When the widget is stopped or the Android Studio emulator runs the app again, the widget will die. I do not see any errors in the logcat related to my app, but I do see this warning:
Copy code
Permission Denial: opening provider com.thirdgate.stormtracker.ImageFileProvider from ProcessRecord{2899a4f 1117:com.google.android.apps.nexuslauncher/u0a151} (pid=1117, uid=10151) that is not exported from UID 10185
followed by a second warning:
Copy code
Error inflating RemoteViews android.widget.RemoteViews$ActionException: java.lang.SecurityException: Permission Denial: opening provider com.thirdgate.stormtracker.ImageFileProvider from ProcessRecord{2899a4f 1117:com.google.android.apps.nexuslauncher/u0a151} (pid=1117, uid=10151) that is not exported from UID 10185
I think the issue it is highlighting is that the original permission was granted to the first . This is done with essentially the same code as the above example:
Copy code
// Find the current launcher every time to ensure it has read permissions
val intent = Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_HOME) }
val resolveInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    context.packageManager.resolveActivity(
        intent,
        PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong()),
    )
} else {
    @Suppress("DEPRECATION")
    context.packageManager.resolveActivity(
        intent,
        PackageManager.MATCH_DEFAULT_ONLY,
    )
}
val launcherName = resolveInfo?.activityInfo?.packageName
if (launcherName != null) {
    context.grantUriPermission(
        launcherName,
        contentUri,
        FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_PERSISTABLE_URI_PERMISSION,
    )
}
How should I store the images so that the URI permissions persist across reinstalls or restarts? Is there any other way I can test this situation? As I mentioned, the whole widget appears to die, but no error logs are shown for my app in logcat.
s
I'm taking a look and cam across this issue : https://issuetracker.google.com/issues/233235354 Does this address your problem? It sounds like you will need to make a custom Content Provider and map the uris your widget references to files inside of there. I am trying to make some code that does this based on the sample and what you've described. Do you have a public example project with this issue? It would save some time reproducing it on my end. Thanks!
Actually I think I'm seeing the same behavior with the platform-sample. When I restart the app via android studio the widget display's a "Can't load widget" message. Is that similar to what you are seeing?
j
Meanwhile, yes I have also observed that as well. First, I was able to fix the issue in my code, the "Permission Denial" warnings, which in the end only partially fixed the issue of the widget dying after restarting. Second, I also can see that from platform-examples that sometimes the apps do NOT die when restarted, but then randomly changing unused parts of of xml documents (or any regular kotlin files) will cause the widget to fail. This might not be so important, so perhaps we could just say that most stopping and restarting in Android Studio causes the widget to die? When it dies it is completely transparent with a loading icon in the middle.