My app lets the user select images and then it animates the images. It's a simple thing and I want it to run on 4.2 and onwards. It works perfectly now.
The app is supposed to remember the chosen images and let these be default the next time the user runs the app - when the app is restarted.
This works beautifully on my Galaxy Nexus (4.2.1) but not so well on my Galaxy S8+ (7.0). Since I love how it works on 4.2.1, it's a bit frustrating that it can't simply run the same on later platforms.
This is inside onCreate()
:
((ImageButton) findViewById(R.id.imagex))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select image"), SELECT_IMAGEX);
}
});
From onActivityResult
:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// [snip unimportant code]
Uri uri = intent.getData();
Bitmap bitmap = getBitmap(uri);
final int takeFlags = intent.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
try {
getContentResolver().takePersistableUriPermission(uri, takeFlags);
} catch (SecurityException e) {
Log.w(myLog, "SecurityException: " + e.getMessage());
}
// [snip]
editor.putString("imagex", uri.toString());
editor.commit();
}
Later, the app is restarted and this part of the method onCreate()
goes:
String tmp = preferences.getString("imagex", null);
if (tmp != null) {
uri = Uri.parse(tmp);
Bitmap bitmap = getBitmap(uri);
// etc
}
On the S8+, getBitmap() gives an exception Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
(meaning the method returns null).
It's quite confusing why it would complain about one single missing permission TWICE in one single exception message. By the way, it still does so after adding <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
.
Reading on this great site, I find people talking about
final int takeFlags = intent.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(selectedImageUri, takeFlags);
which is some fairly modern invention, but unfortunately it just causes this on the S8+
SecurityException: No persistable permission grants found
and on the Galaxy Nexus it simply crashes by
java.lang.NoSuchMethodError
I solved the android.permission.MANAGE_DOCUMENTS
issues in the following way, using the very helpful comment section above.
Inside onCreate():
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
else
intent.setAction(Intent.ACTION_GET_CONTENT);
Inside onActivityResult():
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final int takeFlags = intent.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
try {
getContentResolver().takePersistableUriPermission(uri, takeFlags);
} catch (Exception e) {
Log.w(myLog, "Exception: " + e.getMessage());
}
}
For Android API24, my newer phone, it works for all images that I've tried so far, both those in the Downloads directory, and those from the camera gallery.
HOWEVER:
For Android API17, my older phone, while it does work for images in Downloads, I discover that I get the following exception for some other images on the phone during getContentResolver().openInputStream(uri)
java.lang.SecurityException: Permission Denial: opening provider
com.android.gallery3d.provider.GalleryProvider from ProcessRecord ...
requires com.google.android.gallery3d.permission.GALLERY_PROVIDER or
com.google.android.gallery3d.permission.GALLERY_PROVIDER
来源:https://stackoverflow.com/questions/48604552/android-issues-reading-images-from-persistent-uri