ParcelFileDescriptor+PdfRenderer在Android渲染显示PDF文件

news/2025/1/16 14:36:21/

ParcelFileDescriptor 是一个非常重要的类,用于表示一个文件描述符(File Descriptor,简称 FD),它可以让文件或数据通过进程间通信(IPC)进行共享。

1. 基本概念

  • ParcelFileDescriptorandroid.os 包下的类,通常用来操作文件或文件流,尤其是需要跨进程传递文件句柄时。
  • 它封装了一个底层的文件描述符,可以表示普通文件、管道、套接字等数据源。

2. 常见用途

  1. 跨进程共享文件:通过 Binder、AIDL 等机制,将文件描述符传递给其他进程。
  2. ContentProvider 配合:在 ContentProvider 中,可以使用 ParcelFileDescriptor 返回一个文件句柄,而不是整个文件内容。
  3. 与大文件交互:通过流的方式读取文件内容,避免直接将大文件加载到内存中。

3. 创建方式

ParcelFileDescriptor 的创建方式多种多样,以下是常见的几种:

(1)通过 open 方法打开文件

File file = new File("/path/to/file");
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);

常见模式:

  • MODE_READ_ONLY:只读模式。
  • MODE_WRITE_ONLY:只写模式。
  • MODE_READ_WRITE:读写模式。
  • MODE_APPEND:追加模式。

(2)通过 createPipe 创建管道

创建一个管道,用于进程间通信:

ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
ParcelFileDescriptor readSide = pipe[0];
ParcelFileDescriptor writeSide = pipe[1];

(3)通过 createSocketPair 创建套接字对

创建一对本地套接字:

ParcelFileDescriptor[] socketPair = ParcelFileDescriptor.createSocketPair();
ParcelFileDescriptor socket1 = socketPair[0];
ParcelFileDescriptor socket2 = socketPair[1];

(4)通过 fromFd 使用已有文件描述符

如果已有文件描述符,可以直接创建:

int fd = ...; // 已有的文件描述符
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fd);

4. 读取和写入数据

ParcelFileDescriptor 本身不提供直接的读写操作,通常通过它获取 FileInputStreamFileOutputStream 来操作数据:

读取数据

FileInputStream fis = new FileInputStream(pfd.getFileDescriptor());
byte[] buffer = new byte[1024];
int readBytes = fis.read(buffer);
fis.close();

写入数据

FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor());
fos.write("Hello, ParcelFileDescriptor!".getBytes());
fos.close();

5. 关闭资源

ParcelFileDescriptor 使用后需要关闭,以防资源泄漏:

pfd.close();

或者使用 try-with-resources 自动关闭:

try (ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)) {// 使用 pfd
}

6. 常见方法

方法描述
getFileDescriptor()返回底层的 FileDescriptor 对象。
detachFd()分离底层的文件描述符,用作其他用途。
close()关闭文件描述符,释放资源。
getStatSize()返回文件的大小(如果支持)。
checkError()检查是否发生错误。

7. 使用场景举例

(1)在 ContentProvider 中共享文件

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {File file = new File(context.getFilesDir(), "example.txt");return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}

(2)AIDL 中跨进程传递文件描述符

@Override
public ParcelFileDescriptor getFileDescriptor() {File file = new File("/path/to/file");return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}

PdfRenderer

是 Android 提供的一个类,用于解析和渲染 PDF 文件。它需要通过 ParcelFileDescriptor 来获取 PDF 文件的描述符,从而读取和渲染 PDF 文件的页面。如果需要实现类似 PDF 阅读器的分页浏览,可以将 PdfRendererParcelFileDescriptor 结合 ViewPager 或 RecyclerView。每页创建一个 Bitmap,并动态加载和回收页面内容。

    private void renderPage(File file) {Observable.create((ObservableOnSubscribe<Pair<Integer, Bitmap>>) emitter -> {try {ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);renderer = new PdfRenderer(parcelFileDescriptor);int w = getResources().getDisplayMetrics().widthPixels;int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());int h = getResources().getDisplayMetrics().heightPixels - padding;ArrayList<Bitmap> pageList = new ArrayList<>();// let us just render all pagesfinal int pageCount = renderer.getPageCount();for (int i = 0; i < pageCount; i++) {PdfRenderer.Page page = renderer.openPage(i);Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);canvas.drawColor(Color.WHITE);// say we render for showing on the screenpage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);// do stuff with the bitmappageList.add(bitmap);// mulRenderAdapter.add(i, bitmap);// close the pagepage.close();emitter.onNext(new Pair<>(i, bitmap));
//                            if (i == pageCount-1){
//                                runOnUiThread(this::dismissLoading);
//                            }}// close the renderer} catch (Exception e) {e.printStackTrace();runOnUiThread(this::dismissLoading);} finally {if (renderer != null) {renderer.close();}}}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new BaseObserver<Pair<Integer, Bitmap>>() {@Overridepublic void onSuccess(Pair<Integer, Bitmap> pair) {dismissLoading();mulRenderAdapter.add(pair.first, pair.second);}@Overridepublic void onFailure(Throwable e) {dismissLoading();}});
//        new Handler().postDelayed(this::dismissLoading, 3 * 1000);}

http://www.ppmy.cn/news/1563629.html

相关文章

【行空板K10】上传温湿度信息到EasyIoT平台

目录 引言 EasyIoT平台 程序编写 测试结果 结语 引言 今天测试一下使用行空板K10上传数据到EasyIoT平台。这个平台是DFRobot自由的物联网云平台&#xff0c;也是Mind支持的4个MQTT平台之一。 EasyIoT平台 EasyIoT平台的优点是非常简单&#xff0c;没有阿里云、华为云那…

蓝桥杯刷题第二天——背包问题

题目描述 有N件物品和一个容量是V的背包。每件物品只能使用一次。第i件物品的体积是Vi价值是Wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 第一行两个整数&#xff0c;N&#xff0c;V&am…

《分布式光纤传感:架设于桥梁监测领域的 “智慧光网” 》

桥梁作为交通基础设施的重要组成部分&#xff0c;其结构健康状况直接关系到交通运输的安全和畅通。随着桥梁建设规模的不断扩大和服役年限的增长&#xff0c;桥梁结构的安全隐患日益凸显&#xff0c;传统的监测方法已难以满足对桥梁结构健康实时、全面、准确监测的需求。分布式…

开始使用Panuon开源界面库环境配置并手写VS2019高仿界面

1. Panuon环境配置 1.1. 通过Nuget 安装 Panuon.WPF.UI1.2. xaml引用命名空间1.3. using Panuon.WPF.UI; 2. VS2019 view 2.1. 设置窗体尺寸和title2.2. 添加静态资源 2.2.1. 什么是静态资源 2.3. 主Grid 2.3.1. 盒子模型2.3.2. 嵌套布局 3. 总结 1. Panuon环境配置 1.1. 通…

Spring Boot 2 学习指南与资料分享

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今竞争激烈的 Java 后端开发领域&#xff0c;Spring Boot 2 凭借其卓越的特性&#xff0c;为开发者们开辟了一条高效、便捷的开发之路。如果你渴望深入学习 Spring Boot 2&#xff0c;以下这份精心…

vue.js+websocket+mongodb实现纯粹的聊天室项目

vue.jswebsocketmongodb实现纯粹的聊天室项目&#xff01;下面的项目的构建过程和代码展示。 1&#xff1a;项目的整体结构图 chatroom/ │ ├── backend/ # 后端服务目录 │ ├── config/ # 配置文件 │ │ └…

设计和优化用于 AR、HUD 和高级显示系统的表面浮雕光栅

表面浮雕光栅是许多光学系统中的关键组件&#xff0c;在控制增强现实 &#xff08;AR&#xff09; 显示器、平视显示器 &#xff08;HUD&#xff09; 和其他先进光子器件中的光传播方面发挥着关键作用。作为在这个领域工作的工程师和设计师&#xff0c;您了解针对特定应用优化这…

NGC容器中快速搭建Jupyter环境

本文将介绍如下内容&#xff1a; 一、搭建 Docker Container 环境二、配置 Jupyter三、访问 Jupyter 页面并后台运行服务 一、搭建 Docker Container 环境 1、拉取 Docker Image NVIDAI NGC CONTAINER # 1. 进入 NVIDAI NGC CONTAINER&#xff0c;检索。Eg: Pytorch Tag #…