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

安卓开发:如何从相册选择PDF并在PDF查看器中打开?

解决Android选择PDF后Bitmap为null的问题

兄弟,你这踩了个新手常犯的坑——PDF是文档格式,不是图像文件,根本没法直接转成Bitmap!之前处理图片那套编码转Bitmap的逻辑对PDF完全不适用,这就是你得到null的核心原因。下面给你一步步讲怎么正确搞定从相册选PDF并显示的需求:

第一步:修正选择PDF的Intent

你之前的Intent大概率还是按选图片写的,得改成专门针对PDF的配置:

SelectButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("application/pdf"); // 指定只筛选PDF文件
        intent.addCategory(Intent.CATEGORY_OPENABLE); // 确保能打开选中的文件
        startActivityForResult(intent, 1001); // 用你自己定义的请求码就行
    }
});

如果是Android 10及以上版本,更推荐用ActivityResultContracts替代已废弃的startActivityForResult:

// 先注册文件选择的回调
private ActivityResultLauncher<Intent> pdfPickerLauncher = registerForActivityResult(
    new ActivityResultContracts.StartActivityForResult(),
    result -> {
        if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) {
            Uri pdfUri = result.getData().getData();
            // 拿到PDF的Uri后,去执行显示逻辑
            displayPdf(pdfUri);
        }
    }
);

// 按钮点击时触发选择
SelectButton.setOnClickListener(v -> {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("application/pdf");
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    pdfPickerLauncher.launch(intent);
});

第二步:显示PDF的两种常用方案

方案1:调用系统自带PDF查看器(最简单)

直接把Uri传给系统PDF应用,不用自己写渲染逻辑,省心省力:

private void displayPdf(Uri pdfUri) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(pdfUri, "application/pdf");
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 必须加这个,否则系统应用读不到文件
    try {
        startActivity(intent);
    } catch (ActivityNotFoundException e) {
        // 提示用户没有安装PDF查看工具
        Toast.makeText(this, "请先安装PDF查看应用", Toast.LENGTH_SHORT).show();
    }
}

方案2:用系统PdfRenderer自行渲染(适合嵌入到自己的界面)

Android自带了PdfRenderer类,可以把PDF的单页转成Bitmap显示(多页需要自己处理翻页逻辑):

private void displayPdfWithRenderer(Uri pdfUri) {
    try {
        // 获取文件描述符
        ParcelFileDescriptor fd = getContentResolver().openFileDescriptor(pdfUri, "r");
        if (fd == null) return;
        
        PdfRenderer renderer = new PdfRenderer(fd);
        // 打开PDF的第一页(索引从0开始)
        PdfRenderer.Page page = renderer.openPage(0);
        
        // 创建Bitmap用来渲染页面
        Bitmap bitmap = Bitmap.createBitmap(page.getWidth(), page.getHeight(), Bitmap.Config.ARGB_8888);
        page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
        
        // 把Bitmap显示到ImageView
        yourTargetImageView.setImageBitmap(bitmap);
        
        // 记得关闭资源,避免内存泄漏
        page.close();
        renderer.close();
        fd.close();
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this, "PDF加载失败", Toast.LENGTH_SHORT).show();
    }
}

注意:PdfRenderer只支持能获取文件描述符的Uri,如果是云存储类的Uri,可能需要先把文件下载到本地再处理。

第三步:权限提醒

  • Android 12及以下:需要动态申请READ_EXTERNAL_STORAGE权限;
  • Android 13+:不需要READ_EXTERNAL_STORAGE,但从相册选PDF需要动态申请READ_MEDIA_DOCUMENTS权限。

最后再敲个黑板:别再拿处理图片的逻辑套PDF了,完全是两种不同类型的文件,逻辑自然不一样~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:31:38