如何检测Android中未完成的打印任务并监听状态变化?
Android打印任务状态监控(失败/阻塞检测)
Android系统没有提供直接的PrintJob状态变化回调监听器,你可以通过定时轮询+系统广播监听的组合方案来实现打印任务完成/失败/阻塞的实时通知,具体实现如下:
一、核心思路
- 提交打印任务时保存
PrintJob实例或其ID,用于后续状态查询 - 通过定时轮询主动检查任务状态,覆盖所有场景
- 监听系统打印状态广播,被动接收状态变化通知,减少轮询频率
二、关键状态说明
PrintJobInfo的状态值可以覆盖你提到的场景:
STATE_COMPLETED:任务成功完成STATE_FAILED:任务直接失败STATE_BLOCKED:任务被阻塞(对应打印机缺墨、纸张不足、断开连接等情况)STATE_CANCELED:任务被取消
三、具体实现
1. 提交打印任务并保存任务ID
提交打印时,获取并保存PrintJob的ID,用于后续定位任务:
// Kotlin示例 val printManager = getSystemService(Context.PRINT_SERVICE) as PrintManager val printJob = printManager.print("我的文档", customPrintAdapter, null) // 保存任务ID,可存在SharedPreferences、ViewModel等地方 val targetJobId = printJob.id
2. 定时轮询检查状态
使用协程或Handler定期查询任务状态,适合需要精准监控的场景:
// 在ViewModel或Activity中启动轮询(Kotlin协程) viewModelScope.launch { val printManager = getSystemService(Context.PRINT_SERVICE) as PrintManager while (isActive) { delay(2000) // 每2秒检查一次,可按需调整 val printJob = printManager.getPrintJob(targetJobId) printJob?.let { job -> when (job.info.state) { PrintJobInfo.STATE_COMPLETED -> { // 处理任务完成逻辑,比如通知用户 cancel() // 停止轮询 } PrintJobInfo.STATE_FAILED, PrintJobInfo.STATE_BLOCKED, PrintJobInfo.STATE_CANCELED -> { // 处理失败/阻塞/取消逻辑,比如提示用户检查打印机 cancel() // 停止轮询 } // 其他状态(如STATE_QUEUED、STATE_PRINTING)继续轮询 } } ?: run { // 任务已不存在,停止轮询 cancel() } } }
3. 监听系统广播接收状态变化
通过监听系统广播android.intent.action.PRINT_JOB_STATE_CHANGED,被动获取状态更新,降低轮询频率:
步骤1:注册广播接收器(Manifest方式)
<receiver android:name=".PrintJobStateReceiver"> <intent-filter> <action android:name="android.intent.action.PRINT_JOB_STATE_CHANGED" /> </intent-filter> </receiver>
步骤2:实现广播接收器
class PrintJobStateReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action != "android.intent.action.PRINT_JOB_STATE_CHANGED") return val printManager = context?.getSystemService(Context.PRINT_SERVICE) as PrintManager val targetJobId = // 从保存的位置获取目标任务ID val printJob = printManager.getPrintJob(targetJobId) printJob?.let { job -> when (job.info.state) { PrintJobInfo.STATE_COMPLETED -> { // 通知任务完成 } PrintJobInfo.STATE_FAILED, PrintJobInfo.STATE_BLOCKED -> { // 通知任务因缺墨/断开连接等原因失败/阻塞 } } } } }
四、注意事项
- 广播会接收系统所有打印任务的状态变化,务必通过任务ID精准匹配自己的任务,避免误处理
- 轮询间隔不要设置过短,避免不必要的资源消耗
STATE_BLOCKED是检测打印机硬件问题(缺墨、断连)的关键状态,需重点处理
内容的提问来源于stack exchange,提问作者Rohan Pande




