如何在Kotlin中直接打印指定路径PDF(无确认对话框)
实现无弹窗直接打印PDF(首次选打印机)
完全可以实现你要的功能,核心思路是保存首次选择的打印机ID,后续打印直接调用该打印机,跳过所有确认弹窗。下面是具体实现步骤:
1. 持久化存储打印机ID
用SharedPreferences保存用户首次选择的打印机ID,确保重启应用后仍能复用:
private fun savePrinterId(printerId: String) { getSharedPreferences("PrintPrefs", MODE_PRIVATE) .edit() .putString("selected_printer_id", printerId) .apply() } private fun getSavedPrinterId(): String? { return getSharedPreferences("PrintPrefs", MODE_PRIVATE) .getString("selected_printer_id", null) }
2. 创建PDF打印适配器
实现PrintDocumentAdapter,负责向系统打印框架提供PDF文件的数据流:
private fun createPdfPrintAdapter(file: File): PrintDocumentAdapter { return object : PrintDocumentAdapter() { override fun onLayout( oldAttributes: PrintAttributes?, newAttributes: PrintAttributes?, cancellationSignal: CancellationSignal?, callback: LayoutResultCallback?, extras: Bundle? ) { if (cancellationSignal?.isCanceled == true) { callback?.onLayoutCancelled() return } val printInfo = PrintDocumentInfo.Builder(file.name) .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT) .setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN) .build() callback?.onLayoutFinished(printInfo, oldAttributes != newAttributes) } override fun onWrite( pages: Array<out PageRange>?, destination: ParcelFileDescriptor?, cancellationSignal: CancellationSignal?, callback: WriteResultCallback? ) { if (cancellationSignal?.isCanceled == true) { callback?.onWriteCancelled() return } try { val input = FileInputStream(file) val output = FileOutputStream(destination?.fileDescriptor) input.copyTo(output) callback?.onWriteFinished(arrayOf(PageRange.ALL_PAGES)) } catch (e: Exception) { callback?.onWriteFailed(e.localizedMessage) } } } }
3. 整合自动打印逻辑
在generatePDF函数的Toast提示后,添加打印判断逻辑:
// 原generatePDF函数末尾 Toast之后添加: val printManager = getSystemService(Context.PRINT_SERVICE) as PrintManager val printAdapter = createPdfPrintAdapter(file) val printJobName = "打印徽章PDF" val savedPrinterId = getSavedPrinterId() if (savedPrinterId != null) { // 直接使用保存的打印机打印,无任何弹窗 printManager.print( printJobName, printAdapter, PrintAttributes.Builder().build(), savedPrinterId ) } else { // 首次打印,弹出打印机选择界面 val printIntent = printManager.createPrintJobIntent(printJobName, printAdapter) startActivityForResult(printIntent, 1001) }
4. 处理打印机选择结果
重写onActivityResult(AndroidX可改用registerForActivityResult),保存用户选中的打印机ID并触发首次打印:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == 1001 && resultCode == RESULT_OK) { val printerId = data?.getStringExtra(PrintManager.EXTRA_PRINTER_ID) printerId?.let { savePrinterId(it) // 首次选择后立即打印 val printManager = getSystemService(Context.PRINT_SERVICE) as PrintManager val printAdapter = createPdfPrintAdapter(File("/storage/emulated/0/Download/Badges/badge.pdf")) printManager.print("打印徽章PDF", printAdapter, PrintAttributes.Builder().build(), it) } } }
关键注意事项
- 权限:Android 10及以下需申请
READ_EXTERNAL_STORAGE权限;Android 11+访问公共Download目录无需额外权限。 - 兼容性:部分小众打印机可能不支持无弹窗直接打印,建议测试主流品牌设备。
- 状态监听:可通过
PrintJob对象监听打印成功/失败状态,做后续提示或重试逻辑。
内容的提问来源于stack exchange,提问作者kartik
相关产品推荐
相关产品推荐

