本文将深入探讨android应用中使用PDFView库打开PDF文件时,设备重启后出现SecurityException权限错误的问题,并提供详细的解决方案。主要原因是URI权限在重启后丢失,导致应用无法再次访问已选择的PDF文件。通过使用takePersistableUriPermissions()方法获取持久化URI权限,可以确保应用在重启后仍然能够访问PDF文件,从而避免权限问题。
当你在Android应用中使用barteksc/AndroidPdfViewer库打开PDF文件时,可能会遇到一个问题:当设备重启后,应用再次尝试打开之前保存的PDF文件URI时,会抛出SecurityException,提示缺少MANAGE_DOCUMENTS权限。这是因为通过ACTION_OPEN_DOCUMENT获取的URI权限在应用重启后会失效。
解决这个问题,需要利用ContentResolver的takePersistableUriPermissions()方法来获取持久化的URI权限。以下是详细的步骤和代码示例:
1. 移除不必要的Flag
首先,在启动ACTION_OPEN_DOCUMENT Intent时,移除FLAG_GRANT_PERSISTABLE_URI_PERMISSION Flag,因为我们将在onActivityResult()中手动处理持久化权限。
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");
2. 在onActivityResult()中获取持久化URI权限
在onActivityResult()方法中,当接收到ACTION_OPEN_DOCUMENT的结果时,调用takePersistableUriPermissions()方法。
@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); // 获取持久化URI权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { final int takeFlags = resultData.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); ContentResolver resolver = getContentResolver(); resolver.takePersistableUriPermission(uri, takeFlags); } db.insertRowAdmins(name, uri.toString(), R.drawable.book, 23, db.getNameTableId().get(positionTab)); setNotify(); } } }
代码解释:
- resultData.getFlags(): 获取 Intent 携带的 Flags。
- & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION): 提取出读写权限相关的 Flag。
- getContentResolver(): 获取 ContentResolver 实例。
- resolver.takePersistableUriPermission(uri, takeFlags): 关键步骤,请求系统授予应用对该 URI 的持久化读写权限。
3. 权限声明(AndroidManifest.xml)
虽然MANAGE_DOCUMENTS权限看起来相关,但实际上,对于通过ACTION_OPEN_DOCUMENT获取的URI,并不需要此权限。确保你的Manifest文件中包含以下权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
如果你的应用需要写入PDF文件,还需要:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
4. 注意事项
- 确保你的应用在处理URI时,始终检查URI的有效性。
- 如果用户删除了文件,即使有持久化URI权限,也无法访问该文件。
- 在保存URI到数据库之前,确保已经获取了持久化权限。
总结
通过移除不必要的Flag,并在onActivityResult()中使用takePersistableUriPermissions()方法,可以解决Android应用重启后PDFView库打开PDF文件时出现的SecurityException权限问题。 这种方法允许你的应用程序在重启后仍然能够访问用户选择的PDF文件,提供更好的用户体验。 记住,在处理文件URI时,始终要小心处理权限问题,并确保你的应用能够正确处理文件不存在的情况。