如何使用FileProvider在内部存储/缓存中创建并显示PDF?
如何用FileProvider在Android内部存储/缓存创建并显示PDF
嘿,我来帮你搞定这个问题!你已经有外部存储创建PDF的代码了,接下来我们调整成内部存储/缓存的方案,再配合FileProvider实现文件共享显示:
1. 调整代码,在内部存储/缓存创建PDF
内部存储是应用的私有目录,不需要额外权限,我们可以用getFilesDir()(永久存储,不会被系统主动清理)或者getCacheDir()(缓存目录,内存不足时可能被系统清理)来替换原来的外部存储路径。
修改你的CreatePDF类里的文件路径逻辑:
public class CreatePDF { private static String FILE; private static Font catFont = new Font(Font.FontFamily.TIMES_ROMAN, 18, Font.BOLD); private static Font redFont = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.NORMAL, BaseColor.RED); private static Font subFont = new Font(Font.FontFamily.TIMES_ROMAN, 16, Font.BOLD); private static Font smallBold = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.BOLD); // 初始化文件路径,需要传入上下文获取内部存储目录 private static void initFilePath(Context context) { // 方案1:用永久内部存储目录 FILE = new File(context.getFilesDir(), "xyz.pdf").getAbsolutePath(); // 方案2:用缓存目录(适合临时PDF文件) // FILE = new File(context.getCacheDir(), "xyz.pdf").getAbsolutePath(); } // 生成PDF的核心方法 public static void create(Context context) throws IOException, DocumentException { initFilePath(context); // 先初始化路径 Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream(FILE)); document.open(); addContent(document); // 保留你原来的内容填充逻辑 document.close(); } // 你的PDF内容生成方法,和原来的逻辑一致即可 private static void addContent(Document document) throws DocumentException { // 这里写你原来的段落、字体、排版代码... } }
2. 配置FileProvider实现文件共享
内部存储的文件默认是应用私有的,要让PDF阅读器这类外部应用能访问,必须配置FileProvider:
2.1 在AndroidManifest.xml注册FileProvider
在<application>标签内添加如下配置:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
${applicationId}会自动替换成你的应用包名,也可以手动写死(比如com.your.app.id.fileprovider),注意后面要和代码里的authorities保持一致。
2.2 创建路径配置文件
在res/xml/目录下新建file_paths.xml(没有xml目录就手动创建),添加对应内部存储的路径规则:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 对应getFilesDir()的永久内部存储 --> <files-path name="internal_files" path="." /> <!-- 如果用缓存目录,就添加下面这行 --> <cache-path name="internal_cache" path="." /> </paths>
path="."表示共享该目录下的所有文件,你也可以指定子目录(比如path="pdfs/")来缩小共享范围。
3. 获取Content URI并打开PDF
生成PDF后,通过FileProvider获取文件的Content URI,再用Intent启动PDF阅读器:
// 生成PDF后调用这个方法打开 private void openPdfFile(Context context) { // 根据你选择的存储目录创建文件对象 File pdfFile = new File(context.getFilesDir(), "xyz.pdf"); // 如果用缓存目录就换成:new File(context.getCacheDir(), "xyz.pdf"); if (pdfFile.exists()) { // 获取FileProvider的Content URI Uri pdfUri = FileProvider.getUriForFile( context, context.getPackageName() + ".fileprovider", // 和Manifest里的authorities一致 pdfFile ); // 创建打开PDF的Intent Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(pdfUri, "application/pdf"); // 授予外部应用临时读取权限,必须加! intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 检查是否有应用能处理这个Intent if (intent.resolveActivity(context.getPackageManager()) != null) { context.startActivity(intent); } else { Toast.makeText(context, "没有找到可以打开PDF的应用", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(context, "PDF文件不存在", Toast.LENGTH_SHORT).show(); } }
关键注意点
- 内部存储不需要申请
READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE权限,因为是应用私有目录。 - 必须添加
Intent.FLAG_GRANT_READ_URI_PERMISSION,否则外部应用无法读取你的私有文件。 - 缓存目录的文件可能被系统自动清理,适合存放临时PDF文件,永久文件建议用
getFilesDir()目录。
内容的提问来源于stack exchange,提问作者Umang
相关产品推荐
相关产品推荐

