Android重启后barteksc库无法打开PDF的权限问题
Android PDF查看重启后权限异常问题解决
问题描述
使用barteksc库开发Android PDF查看功能,选中文件后将URI存入数据库,当时可正常打开PDF,但重启手机后加载PDF时抛出SecurityException,提示需要android.permission.MANAGE_DOCUMENTS权限。
问题报错
load pdf error java.lang.SecurityException: Permission Denial: opening provider com.android.providers.downloads.DownloadStorageProvider from ProcessRecord{f6420b9 6172:com.azizlabiod.librarypdfpro/u0a218} (pid=6172, uid=10218) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
相关代码
文件选择逻辑
final int KITKAT_VALUE = 1002; Intent intent; intent = new Intent(); if (Build.VERSION.SDK_INT < 19) { intent.setAction(Intent.ACTION_GET_CONTENT); } else { intent.setAction(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); } intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.setType("application/pdf"); try { startActivityForResult(intent, KITKAT_VALUE); } catch (ActivityNotFoundException e) { Toast.makeText(getApplicationContext(), R.string.toast_pick_file_error, Toast.LENGTH_SHORT).show(); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent resultData) { super.onActivityResult(requestCode, resultCode, resultData); if (requestCode == 1002 && resultCode == Activity.RESULT_OK) { Uri uri; if (resultData != null) { uri = resultData.getData(); String name = getFileName(uri); db.insertRowAdmins(name, uri.toString(), R.drawable.book, 23, db.getNameTableId().get(positionTab)); setNotify(); } } }
清单配置
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" tools:ignore="ProtectedPermissions" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.LibraryPDFPro" android:requestLegacyExternalStorage="true" android:usesCleartextTraffic="true" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ShowBook" android:exported="false" /> <activity android:name=".ShowDiatel" android:exported="false" /> </application>
详细报错栈
/PDFView: load pdf error java.lang.SecurityException: Permission Denial: opening provider com.android.providers.downloads.DownloadStorageProvider from ProcessRecord{f6420b9 6172:com.azizlabiod.librarypdfpro/u0a218} (pid=6172, uid=10218) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS at android.os.Parcel.readException(Parcel.java:1599) at android.os.Parcel.readException(Parcel.java:1552) at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:3776) at android.app.ActivityThread.acquireProvider(ActivityThread.java:5034) at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2044) at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517) at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1121) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:958) at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:811) at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:765) at com.github.barteksc.pdfviewer.source.UriSource.createDocument(UriSource.java:37) at com.github.barteksc.pdfviewer.DecodingAsyncTask.doInBackground(DecodingAsyncTask.java:53) at com.github.barteksc.pdfviewer.DecodingAsyncTask.doInBackground(DecodingAsyncTask.java:27) at android.os.AsyncTask$2.call(AsyncTask.java:295) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818)
解决方案
核心问题
使用ACTION_OPEN_DOCUMENT获取的URI需要主动持久化权限,你仅添加了FLAG_GRANT_PERSISTABLE_URI_PERMISSION但未调用API保存权限,重启后系统收回临时权限导致访问失败。另外MANAGE_DOCUMENTS是系统保护权限,第三方APP无法获取,清单中配置无效。
修复步骤
- 持久化URI权限
修改onActivityResult方法,在获取URI后调用takePersistableUriPermission保存权限:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent resultData) { super.onActivityResult(requestCode, resultCode, resultData); if (requestCode == KITKAT_VALUE && resultCode == Activity.RESULT_OK) { if (resultData != null) { Uri uri = resultData.getData(); if (uri != null) { // 获取并持久化权限 int takeFlags = resultData.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); getContentResolver().takePersistableUriPermission(uri, takeFlags); String name = getFileName(uri); db.insertRowAdmins(name, uri.toString(), R.drawable.book, 23, db.getNameTableId().get(positionTab)); setNotify(); } } } }
- 删除无效权限
从清单中移除MANAGE_DOCUMENTS权限:
<!-- 移除该行 --> <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" tools:ignore="ProtectedPermissions" />
- 权限校验补充
重启后加载PDF前,可检查是否持有该URI的权限,无权限则重新选择文件:
// 检查URI是否有可读权限 public boolean hasUriReadPermission(Context context, Uri uri) { for (UriPermission perm : context.getContentResolver().getPersistedUriPermissions()) { if (perm.getUri().equals(uri) && (perm.getPermissions() & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { return true; } } return false; }
注意事项
ACTION_OPEN_DOCUMENT返回的是文档提供器的永久URI,但权限必须通过takePersistableUriPermission主动持久化,否则重启后失效。- 不要尝试申请
MANAGE_DOCUMENTS权限,该权限仅授予系统应用,第三方APP无法获得授权。
内容的提问来源于stack exchange,提问作者Aziz Labiod
相关产品推荐
相关产品推荐

