You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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无法获取,清单中配置无效。

修复步骤

  1. 持久化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();
            }
        }
    }
}
  1. 删除无效权限
    从清单中移除MANAGE_DOCUMENTS权限:
<!-- 移除该行 -->
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" tools:ignore="ProtectedPermissions" />
  1. 权限校验补充
    重启后加载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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:41:03