【问题标题】:Android issues reading images from persistent UriAndroid 从持久 Uri 读取图像时出现问题
【发布时间】:2018-02-04 03:58:43
【问题描述】:

我的应用程序允许用户选择图像,然后为图像设置动画。这是一件简单的事情,我希望它在 4.2 及更高版本上运行。现在完美运行。

应用程序应该记住选择的图像,并在用户下次运行应用程序时将这些图像设为默认值 - 当应用程序重新启动时。

这在我的 Galaxy Nexus (4.2.1) 上运行良好,但在我的 Galaxy S8+ (7.0) 上效果不佳。因为我喜欢它在 4.2.1 上的工作方式,所以它不能简单地在以后的平台上运行它有点令人沮丧。

这是在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);
        }
    });

来自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();
}

稍后,应用重新启动,这部分方法onCreate() 执行:

String tmp = preferences.getString("imagex", null);
if (tmp != null) {
    uri = Uri.parse(tmp);
    Bitmap bitmap  = getBitmap(uri);
    // etc
}

在 S8+ 上,getBitmap() 给出异常 Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS(意味着该方法返回 null)。

为什么它会在一个异常消息中抱怨一个丢失的权限 TWICE,这很令人困惑。顺便说一句,添加<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />后仍然如此。

在这个很棒的网站上阅读,我发现人们在谈论

final int takeFlags = intent.getFlags()
           & (Intent.FLAG_GRANT_READ_URI_PERMISSION
           | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(selectedImageUri, takeFlags);

这是一些相当现代的发明,但不幸的是它只是在 S8+ 上造成了这种情况

SecurityException: No persistable permission grants found

在 Galaxy Nexus 上它只是崩溃了

java.lang.NoSuchMethodError

【问题讨论】:

  • 请以您使用的意图的代码开始您的帖子。我之前要求您显示您的意图代码,否则我们不知道您在做什么。大多数事情取决于使用的意图。
  • 谢谢。我在上面添加了更多细节。
  • 使用 ACTION_GET_CONTENT 你不能获得持久权限,因为它们没有提供给你。对于持久权限,您必须使用 ACTION_OPEN_DOCUMENT。检查 getFlags() 中设置了哪些位/标志,您会看到。
  • 进步!该应用程序和以前一样具有 getFlags() = FLAG_GRANT_READ_URI_PERMISSION,如果我更改为 ACTION_OPEN_DOCUMENT 而不是 getFlags() = ACTION_OPEN_DOCUMENT | FLAG_GRANT_WRITE_URI_PERMISSION | FILL_IN_SELECTOR。我不明白,但它确实有所作为。它现在可以在较新的手机上毫无例外地运行,但在我现在无法选择图像之前工作的旧手机上运行。
  • 上面的错字,当然应该是getFlags() = FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION | FILL_IN_SELECTOR

标签: android persistence android-permissions backwards-compatibility


【解决方案1】:

我使用上面非常有用的评论部分通过以下方式解决了android.permission.MANAGE_DOCUMENTS 问题。

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);

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());
    }
}

对于 Android API24,我的新手机,它适用于我迄今为止尝试过的所有图像,包括下载目录中的图像和相机库中的图像。

但是

对于 Android API17,我的旧手机,虽然它确实适用于下载中的图像,但我发现在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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 2013-12-02
    • 1970-01-01
    • 2015-08-18
    • 2015-07-17
    相关资源
    最近更新 更多