Android 14及以上文件权限请求失效问题求助
Android 14(targetSdkVersion 34)下PDF文件访问权限解决方案
问题核心原因
Android 14(targetSdkVersion 34)中,WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE已被完全废弃:
- 系统不会再弹出这两个权限的请求弹窗
- 即使在Manifest中声明,调用权限请求API也不会有任何效果
MANAGE_EXTERNAL_STORAGE属于特殊权限,仅允许文件管理器类应用使用,普通应用使用会导致Google Play审核不通过,不推荐。
你的需求是访问PDF文件,完全不需要依赖这些废弃权限,以下是针对性解决方案:
解决方案步骤
1. 清理Manifest中的废弃权限
直接删除WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE的声明,Manifest只保留必要权限即可:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET" /> <!-- 移除WRITE/READ_EXTERNAL_STORAGE权限 --> <!-- 不要启用MANAGE_EXTERNAL_STORAGE --> <application android:requestLegacyExternalStorage="true" android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme"> <!-- 原有application内容保持不变 --> </application> </manifest>
2. 下载PDF文件:无需权限直接用DownloadManager
你当前的downloadFile方法完全可以保留,Android 14中使用DownloadManager下载到公共Download目录不需要任何存储权限,系统会自动处理文件存储:
private void downloadFile(String url) { DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); request.setTitle("Vertretungsplan"); request.setDescription("wird heruntergeladen"); request.allowScanningByMediaScanner(); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); String filename = URLUtil.guessFileName(url, null, MimeTypeMap.getFileExtensionFromUrl(url)); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); manager.enqueue(request); }
同时,删除MainActivity中所有权限请求相关的代码(onCreate里的权限检查、REQUEST_WRITE_STORAGE常量、onRequestPermissionsResult方法),这些代码已经无效。
3. 访问设备中已有的PDF文件:使用系统文件选择器(SAF)
如果需要让用户选择设备上已有的PDF文件,使用**存储访问框架(SAF)**的文件选择器,不需要任何权限,示例代码如下:
在MainActivity中添加打开文件选择器的方法:
private static final int REQUEST_CODE_PICK_PDF = 1001; private void openPDFFilePicker() { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); // 指定PDF类型 intent.setType("application/pdf"); startActivityForResult(intent, REQUEST_CODE_PICK_PDF); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_PICK_PDF && resultCode == RESULT_OK && data != null) { // 获取选中PDF的Uri,可直接用于读取文件内容 Uri pdfUri = data.getData(); // 在这里处理PDF文件,比如打开、读取等 // 注意:若需要长期访问该文件,需调用takePersistableUriPermission获取持久权限 getContentResolver().takePersistableUriPermission( pdfUri, Intent.FLAG_GRANT_READ_URI_PERMISSION ); } }
关键注意事项
- 不要尝试使用
MANAGE_EXTERNAL_STORAGE,普通应用使用该权限会被Google Play拒绝上架 - 如果PDF文件仅属于你的应用,不需要和其他应用共享,优先使用应用专属存储:
getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),这个目录下的文件不需要任何权限,卸载应用时会被自动删除 - 存储访问框架(SAF)是Android 10及以上版本访问公共文件的标准方式,符合系统权限规范
内容的提问来源于stack exchange,提问作者Saumya Chirania
相关产品推荐
相关产品推荐

