java.lang.SecurityException: Permission Denial: reading...requires android.permi

一直在忙于Gallery,最近遇到了这样的bug,在Setting-->storage&USB->internal storage->images->选择一张-图片> home key exit,然后在Gallery删除选中的那种照片,最后在最近列表里选择Setting,画面仍保留在那张图片,点击打印men,就会报Gallery Force Close.通过log可以看到报以下错:
04-15 11:00:33.959  8427  8427 D AndroidRuntime: Shutting down VM

04-15 11:00:33.965  8427  8427 E AndroidRuntime: FATAL EXCEPTION: main

04-15 11:00:33.965  8427  8427 E AndroidRuntime: Process: com.android.gallery3d, PID: 8427

04-15 11:00:33.965  8427  8427 E AndroidRuntime: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com.android.providers.media.documents/document/image%3A593 from pid=8427, uid=10065 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()

04-15 11:00:33.965  8427  8427 E AndroidRuntime: 	at android.os.Parcel.readException(Parcel.java:1620)

04-15 11:00:33.965  8427  8427 E AndroidRuntime: 	at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)

04-15 11:00:33.965  8427  8427 E AndroidRuntime: 	at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)

04-15 11:00:33.965  8427  8427 E AndroidRuntime: 	at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)

04-15 11:00:33.965  8427  8427 E AndroidRuntime: 	at android.content.ContentResolver.query(ContentResolver.java:493)

04-15 11:00:33.965  8427  8427 E AndroidRuntime: 	at android.content.ContentResolver.query(ContentResolver.java:435)

04-15 11:00:33.965  8427  8427 E AndroidRuntime: 	at com.android.gallery3d.filtershow.cache.ImageLoader.getLocalPathFromUri(ImageLoader.java:85)



没有删除这张照片之前,选择打印是正常的,为何删除了照片就报权限问题了呢?经过代码分析,Gallery是没有权限访问MediaDocumentsProvider,MediaDocumentsProvider是可以接受 android:grantUriPermissions="true"传递权限的,而文件管理器documentsui是申请了 <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />,而文件管理器打开图片会将read的权限通过intent的方式传递了给Gallery:Intent.FLAG_GRANT_READ_URI_PERMISSION

final Intent view = new Intent(Intent.ACTION_VIEW);
            view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            view.setData(doc.derivedUri);

            try {
                startActivity(view);
            } catch (ActivityNotFoundException ex) {
                Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
            }

http://androidxref.com/6.0.0_r1/xref/frameworks/base/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
从而Gallery可以访问MediaDocumentsProvider,而删除了照片的时候,一并将该权限删除了 MediaDocumentsProvider.onMediaStoreDelete(getContext(),
4069                                            volumeName, FileColumns.MEDIA_TYPE_IMAGE, id);,所以再次访问就报权限问题了
if (mediaType == FileColumns.MEDIA_TYPE_IMAGE) {
                                    deleteIfAllowed(uri, data);
                                    MediaDocumentsProvider.onMediaStoreDelete(getContext(),
                                            volumeName, FileColumns.MEDIA_TYPE_IMAGE, id);

                                    idvalue[0] = String.valueOf(id);
                                    database.mNumQueries++;
                                    Cursor cc = db.query("thumbnails", sDataOnlyColumn,
                                                "image_id=?", idvalue, null, null, null);
                                    try {
                                        while (cc.moveToNext()) {
                                            deleteIfAllowed(uri, cc.getString(0));
                                        }
                                        database.mNumDeletes++;
                                        db.delete("thumbnails", "image_id=?", idvalue);
                                    } finally {
                                        IoUtils.closeQuietly(cc);
                                    }
                                }

http://androidxref.com/6.0.0_r1/xref/packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java


revokeUriPermission删除权限
 /**
     * When deleting an item, we need to revoke any outstanding Uri grants.
     */
    static void onMediaStoreDelete(Context context, String volumeName, int type, long id) {
        if (!"external".equals(volumeName)) return;

        if (type == FileColumns.MEDIA_TYPE_IMAGE) {
            final Uri uri = DocumentsContract.buildDocumentUri(
                    AUTHORITY, getDocIdForIdent(TYPE_IMAGE, id));
            context.revokeUriPermission(uri, ~0);
        } else if (type == FileColumns.MEDIA_TYPE_VIDEO) {
            final Uri uri = DocumentsContract.buildDocumentUri(
                    AUTHORITY, getDocIdForIdent(TYPE_VIDEO, id));
            context.revokeUriPermission(uri, ~0);
        } else if (type == FileColumns.MEDIA_TYPE_AUDIO) {
            final Uri uri = DocumentsContract.buildDocumentUri(
                    AUTHORITY, getDocIdForIdent(TYPE_AUDIO, id));
            context.revokeUriPermission(uri, ~0);
        }
    }


http://androidxref.com/6.0.0_r1/xref/packages/providers/MediaProvider/src/com/android/providers/media/MediaDocumentsProvider.java

你可能感兴趣的:(android)