异常 java.lang.SecurityException:读取 ..MediaDocumentsProvider ... 需要 android.permission.MANAGE_DOCUMENT

Posted

技术标签:

【中文标题】异常 java.lang.SecurityException:读取 ..MediaDocumentsProvider ... 需要 android.permission.MANAGE_DOCUMENTS 或 grantUriPermission()【英文标题】:Exception java.lang.SecurityException: reading ..MediaDocumentsProvider ... requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission() 【发布时间】:2018-06-19 15:16:48 【问题描述】:

我在尝试为个人资料图片选择图片时仅在某些设备中发现了此问题。在模拟器中签入这些问题时看不到,但在应用程序的实时版本中,此问题是该用户面临的。 从 firebase 崩溃报告中截取的屏幕截图。请帮助我找出问题所在。

AndroidMenifest.xml

...
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
...

SomeActivity.java

private void pickProfilePictureTask() 

    Intent intent = null;
    if (Build.VERSION.SDK_INT > 19) 

        intent = new Intent(Intent.ACTION_OPEN_DOCUMENT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.addCategory(Intent.CATEGORY_OPENABLE);

     else 

        intent = new Intent(Intent.ACTION_GET_CONTENT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    

    intent.setType("image/*");
    startActivityForResult(intent, IMAGE_PICKER_REQUEST);





@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == IMAGE_PICKER_REQUEST && resultCode == Activity.RESULT_OK) 


        if (data != null) 
            /**Getting bitmap
             *
             * InputStream inputStream = getActivity().getContentResolver().openInputStream(data.getData());
             * Bitmap userPicBitmap = BitmapFactory.decodeStream(inputStream);
             */
            File file = new File(getFileNameFromURI(data.getData()));
            String imageName = file.getPath();
            uploadProfilePicture.setText(imageName);
            userProfilePicUri = data.getData() + "";

        


    


private String getFileNameFromURI(Uri contentURI) 
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) 
        result = contentURI.getPath();
     else 
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME);
        result = cursor.getString(idx);
        cursor.close();
    
    return result;

Android 5.1.1 中的错误 异常 java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com. android.providers.media.documents/document/image%3A6617 from pid=19207, uid=10260 需要 android.permission.MANAGE_DOCUMENTS 或 grantUriPermission()

Android 8.0.0 中的错误 异常 java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord5c1039e 5061:com.mobotechnology.cvmaker/u0a219 (pid=5061, uid=10219) 要求您使用 ACTION_OPEN_DOCUMENT 或相关 API 获取访问权限

【问题讨论】:

请提供minimal reproducible example 显示触发这些崩溃的代码。我的猜测是您正在尝试持久化 Uri 并在以后使用它,并且仅当您使用存储访问框架(ACTION_OPEN_DOCUMENT 等)并获取可持久化的 Uri 权限时才有效。 您介意详细说明答案吗? @CommonsWare 是的,我正在尝试保留 Uri 并稍后使用该 Uri。但我没有得到你的答案。那么,您介意详细说明吗? @CommonsWare 【参考方案1】:

我正在尝试保留 Uri 并在以后使用该 Uri

这适用于带有file 方案的Uri。它不适用于大多数具有content 方案的Uri 值。这些更像是一个经过身份验证的网站的 HTTP URL——当你的会话处于活动状态时 URL 是好的,但之后就没有用了。

如果你通过ACTION_OPEN_DOCUMENTACTION_CREATE_DOCUMENTACTION_OPEN_DOCUMENT_TREE获得Uri并且你在ContentResolver上调用takePersistableUriPermission()提供Uri那么你可以安全地坚持Uri。您将可以无限期地访问内容,直到用户撤销访问权限或内容发生重大变化(例如,被删除)以致其 Uri 不再有效。

任何其他 content Uri(例如,ACTION_GET_CONTENT)仅适用于 for a very short time。您唯一的选择是将内容复制到您控制的某个文件(例如,getCacheDir())并保存该文件的路径。

【讨论】:

我很难理解这个权限模型。获取“没有为 UID 找到持久的权限授予”。当调用 takePersistableUriPermission() @frankelot:您使用的是onActivityResult() 提供给您的Uri 还是合同?如果您是,那么文档提供者可能没有提供可持久的权限授予——这不是必需的。你从哪里得到文件? 感谢CommonsWare 的回复。完全是我的错,我使用 ACTION_GET_CONTENT,切换到 ACTION_OPEN_DOCUMENT 解决了问题【参考方案2】:

试试这个:

public static final int KITKAT_VALUE = 1002;

Intent intent;

if (Build.VERSION.SDK_INT < 19) 
    intent = new Intent();
    intent.setAction(Intent.ACTION_GET_CONTENT);
    intent.setType("*/*");
    startActivityForResult(intent, KITKAT_VALUE);
 else 
    intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("*/*");
    startActivityForResult(intent, KITKAT_VALUE);


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    if (requestCode == KITKAT_VALUE ) 
        if (resultCode == Activity.RESULT_OK) 
            // do something here
        
    

【讨论】:

以上是关于异常 java.lang.SecurityException:读取 ..MediaDocumentsProvider ... 需要 android.permission.MANAGE_DOCUMENT的主要内容,如果未能解决你的问题,请参考以下文章

Java异常如何解决

Kotlin 协程协程异常处理 ① ( 根协程异常处理 | 自动传播异常 | 在协程体捕获异常 | 向用户暴露异常 | 在 await 处捕获异常 | 非根协程异常处理 | 异常传播特性 )

Kotlin 协程协程异常处理 ① ( 根协程异常处理 | 自动传播异常 | 在协程体捕获异常 | 向用户暴露异常 | 在 await 处捕获异常 | 非根协程异常处理 | 异常传播特性 )

异常--异常体系异常的处理异常的捕获finally语句块和自定义异常

Java❤️认识异常异常的基本使用认识异常(异常详解)❤️

异常(异常)