如何在Android Studio中以编程方式打印包含logo和表格的PDF文件
实现安卓应用内打印已生成PDF的步骤
你可以先调整现有生成PDF的逻辑,保存生成的PDF文件路径,再调用系统打印服务完成打印,具体操作如下:
1. 调整现有PDF生成逻辑,存储生成的文件路径
你可以在SampleAdapter中新增一个成员变量存储最近生成的PDF文件实例,修改你的createPdf方法:
// 新增成员变量存储最近生成的PDF文件 private File latestGeneratedPdf; private void createPdf(String id) throws FileNotFoundException, DocumentException { File pdfFolder = new File(Environment.getExternalStorageDirectory(), "pdfdemo"); if (!pdfFolder.exists()) { pdfFolder.mkdirs(); Log.e("LOG_TAG", "Pdf Directory created"+pdfFolder); } Date date = new Date() ; String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(date); File myFile = new File(pdfFolder +"/"+ timeStamp + ".pdf"); // 把生成的文件赋值给成员变量 latestGeneratedPdf = myFile; // 后续原有生成逻辑保持不变 ... // 注意生成PDF完成后要先关闭document和输出流 document.close(); output.close(); }
2. 配置清单文件权限
在AndroidManifest.xml中添加对应权限(安卓4.4及以上系统自带打印框架,无需额外依赖):
<!-- 若你使用外置存储存储PDF,需要保留存储权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3. 实现打印PDF的方法
在打印按钮的点击事件中调用以下方法:
private void printPdf() { if (latestGeneratedPdf == null || !latestGeneratedPdf.exists()) { Toast.makeText(context, "PDF文件不存在,请先生成PDF", Toast.LENGTH_SHORT).show(); return; } // 安卓7.0及以上需要用FileProvider获取URI Uri pdfUri; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { pdfUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", latestGeneratedPdf); } else { pdfUri = Uri.fromFile(latestGeneratedPdf); } PrintManager printManager = (PrintManager) context.getSystemService(Context.PRINT_SERVICE); String jobName = context.getString(R.string.app_name) + " 文档打印"; PrintDocumentAdapter adapter = new PrintDocumentAdapter() { @Override public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) { try { InputStream input = new FileInputStream(latestGeneratedPdf); OutputStream output = new FileOutputStream(destination.getFileDescriptor()); byte[] buf = new byte[1024]; int bytesRead; while ((bytesRead = input.read(buf)) > 0) { output.write(buf, 0, bytesRead); } callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES}); input.close(); output.close(); } catch (Exception e) { callback.onWriteFailed(e.getMessage()); e.printStackTrace(); } } @Override public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) { if (cancellationSignal.isCanceled()) { callback.onLayoutCancelled(); return; } PrintDocumentInfo info = new PrintDocumentInfo.Builder(latestGeneratedPdf.getName()) .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT) .build(); callback.onLayoutFinished(info, true); } }; printManager.print(jobName, adapter, null); }
4. 配置FileProvider(适配安卓7.0+)
如果你的应用目标版本>=24,需要在res/xml目录下新建file_paths.xml:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="pdf_files" path="pdfdemo/" /> <!-- 如果你用的是应用内部存储,替换为下面这行 --> <!-- <files-path name="pdf_files" path="pdfdemo/" /> --> </paths>
再在AndroidManifest.xml的application标签内添加FileProvider声明:
<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>
注意事项
- 如果你生成PDF后立刻调用打印,需要确保PDF已经写入完成、
document.close()和输出流关闭后再执行打印逻辑,避免读取到不完整的文件。 - 如果你的PDF存储在应用私有目录,无需申请存储权限,只需对应修改FileProvider的路径配置即可。
内容的提问来源于stack exchange,提问作者Venkat
相关产品推荐
相关产品推荐

