Android 11系统下PDF下载异常(空文件/无法保存)问题咨询
Android 11 PDF下载保存异常修复方案
问题1:ACTION_CREATE_DOCUMENT创建文件为空
- 故障原因:仅完成了文件创建的唤起逻辑,没有处理文件创建成功后的写入流程。
ACTION_CREATE_DOCUMENT唤起系统文件选择器确认后,会在回调中返回创建好的文件Uri,需要在回调中拿到这个Uri,将下载好的PDF二进制内容写入对应文件。 - 修复代码示例:
// 注册文件创建回调(使用官方推荐的Activity Result API,也可兼容原有onActivityResult写法) ActivityResultLauncher<Intent> createFileLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { Uri pdfUri = result.getData().getData(); // 拿到uri后执行写入操作,pdfContent为你下载到的PDF字节数组 writePdfToUri(pdfUri, pdfContent); } } ); // 写入逻辑实现 private void writePdfToUri(Uri uri, byte[] pdfContent) { try (OutputStream outputStream = getContentResolver().openOutputStream(uri)) { outputStream.write(pdfContent); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } } // 原createFile方法修改为用launcher唤起 private void createFile(Uri pickerInitialUri, String title) { Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("application/pdf"); intent.putExtra(Intent.EXTRA_TITLE, title); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri); } createFileLauncher.launch(intent); }
问题2:DownloadManager无法保存到公共下载目录
- 故障原因:Android 11分区存储规则变更后,不允许直接访问公共目录的File路径,但DownloadManager的
setDestinationInExternalPublicDir接口本身已适配分区存储,保存失败大多是三个原因:- 文件名包含非法字符(比如斜杠、特殊符号),或者第二个参数传入了带路径的字符串,该参数只能传入纯文件名
- 未申请
android.permission.WRITE_EXTERNAL_STORAGE权限(targetSdk>=30下载到公共下载目录仍需要该权限,仅Android13+不需要) - 清单文件中错误配置了冗余的分区存储兼容参数,导致路径解析异常
- 修复后的DownloadManager代码:
DownloadManager downloadManager = (DownloadManager) this.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(uri); String fileName = title + strDate + ".pdf"; // 先过滤文件名中的非法字符,避免创建失败 fileName = fileName.replaceAll("[\\\\/:*?\"<>|]", ""); request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE) .setAllowedOverRoaming(true) .setTitle(fileName) .setDescription(description) // 第二个参数仅传纯文件名即可,系统会自动写入公共Download目录 .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName) .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); long PDF_DOWNLOAD_ID = downloadManager.enqueue(request);
额外提示:如果targetSdkVersion >= 33,需要申请POST_NOTIFICATIONS权限才能正常显示下载完成通知,不会影响文件保存逻辑。
内容的提问来源于stack exchange,提问作者Anish Maharjan
相关产品推荐
相关产品推荐

