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

如何打开通过ContentResolver保存的PDF文件?执行代码后显示空白页

问题分析与修复方案

你的代码存在几个关键问题,导致PDF文件保存后打开显示空白:

  • 临时读取权限未授予:通过Intent.ACTION_VIEW打开Uri时,没有给目标PDF阅读器应用授予临时读取权限,对方无法访问文件内容
  • IS_PENDING状态更新错误:更新待处理状态时误用了MediaStore.Downloads.IS_PENDING,但插入文件时用的是MediaStore.Files的列,列名不匹配会导致文件可能仍处于锁定状态
  • 文件读取不完整:fis.read(bytes)无法保证一次性读取全部文件内容,大文件会出现写入截断的情况
  • Intent未明确MIME类型:系统可能无法精准识别文件类型,导致启动的应用不兼容

修正后的完整代码

public void saveToExternalStorage(File file, Context context) {
    ContentValues cv = new ContentValues();
    String fileName = "order" + new Date().getTime() + ".pdf";
    cv.put(MediaStore.Files.FileColumns.DISPLAY_NAME, fileName);
    cv.put(MediaStore.Files.FileColumns.MIME_TYPE, "application/pdf");
    cv.put(MediaStore.Files.FileColumns.RELATIVE_PATH, "Documents");
    cv.put(MediaStore.Files.FileColumns.IS_PENDING, 1);

    ContentResolver resolver = context.getContentResolver();
    Uri uri = resolver.insert(MediaStore.Files.getContentUri("external"), cv);
    if (uri != null) {
        InputStream fis = null;
        OutputStream outputStream = null;
        try {
            outputStream = resolver.openOutputStream(uri);
            fis = new FileInputStream(file);
            // 循环读写避免大文件读取不完整
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            Log.e("file", "saved " + uri);

            // 修正IS_PENDING列名,与插入时保持一致
            cv.clear();
            cv.put(MediaStore.Files.FileColumns.IS_PENDING, 0);
            resolver.update(uri, cv, null, null);

            // 构建Intent时添加权限并明确MIME类型
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "application/pdf");
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            // 非Activity环境下需添加新任务标记
            if (!(context instanceof Activity)) {
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
            context.startActivity(intent);

        } catch (Exception e) {
            Log.e("error", Log.getStackTraceString(e.fillInStackTrace()));
        } finally {
            // 确保流关闭,避免资源泄漏
            try {
                if (fis != null) fis.close();
                if (outputStream != null) outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

额外注意事项

  • Android 10及以上无需申请WRITE_EXTERNAL_STORAGE权限,低版本需确保已申请并授权
  • 模拟器若未安装PDF阅读器应用,也会显示空白,建议安装Adobe Acrobat等测试应用
  • 避免使用(int) file.length(),文件超过2GB会出现整数溢出问题,循环读写方式可规避此风险

内容的提问来源于stack exchange,提问作者Sahil Manchanda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:23:13