Android PrintService打印作业文档质量极低,寻求技术帮助
Android PrintService 获取文档数据质量极低问题
我在使用Android PrintService时遇到技术问题:打印作业的文档数据质量极低,通过FileDescriptor获取的InputStream读取到的是低质量文件。已在网络上搜索相关解决方案但未找到有效信息,该问题已困扰我四天,恳请各位提供帮助。
public class CustomPrintService extends PrintService { private static final String TAG = "Praneet"; private PrinterInfo mThermalPrinter; @Override public void onCreate() { super.onCreate(); Log.e(TAG, "Custom Print Service created."); mThermalPrinter = new PrinterInfo.Builder(generatePrinterId("BT-582"), "Kebio Prints", PrinterInfo.STATUS_IDLE).build(); } @Override protected PrinterDiscoverySession onCreatePrinterDiscoverySession() { return new CustomPrinterDiscoverySession(); } @Override protected void onRequestCancelPrintJob(PrintJob printJob) { Log.e(TAG, "Canceling print job: " + printJob.getId()); if (printJob.isStarted()) { printJob.cancel(); } } @Override protected void onPrintJobQueued(PrintJob printJob) { if (printJob.isQueued()) { Log.e(TAG, "Processing queued print job: " + printJob.getId()); processPrintJob(printJob); } } @Override public void onDestroy() { super.onDestroy(); Log.e(TAG, "Custom Print Service destroyed."); } private void processPrintJob(PrintJob printJob) { PrintDocument document = printJob.getDocument(); if (document != null) { try (ParcelFileDescriptor descriptor = document.getData(); InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) { // Define the output PDF file path File outputFile = new File(getExternalFilesDir(null), "printed_document.pdf"); try (OutputStream outputStream = new FileOutputStream(outputFile)) { // Copy content from input stream to output stream (PDF generation) byte[] buffer = new byte[5*1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } Log.d("Praneet", "PDF generated at: " + outputFile.getAbsolutePath()); printJob.complete(); // Mark job as completed } catch (Exception e) { Log.e("Praneet", "Error writing PDF: " + e.getMessage()); printJob.fail("Failed to generate PDF"); } } catch (Exception e) { Log.e("Praneet", "Error reading print document: " + e.getMessage()); printJob.fail("Failed to process document"); } } else { Log.e("Praneet", "No document available"); printJob.fail("No document to print"); } } // Custom printer discovery session private class CustomPrinterDiscoverySession extends PrinterDiscoverySession { private final List<PrinterInfo> discoveredPrinters = new ArrayList<>(); @Override public void onStartPrinterDiscovery(List<PrinterId> priorityList) { Log.e(TAG, "Starting printer discovery..."); // Simulate discovering a single printer PrintAttributes.MediaSize customSize = new PrintAttributes.MediaSize(mThermalPrinter.getId().getLocalId(), "58mm thermal Paper", 58, 100); PrinterCapabilitiesInfo capabilities = new PrinterCapabilitiesInfo.Builder(mThermalPrinter.getId()) .addMediaSize(customSize, true) .addResolution(new PrintAttributes.Resolution(mThermalPrinter.getId().getLocalId(), "Default", 1000, 1000), true) .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME, PrintAttributes.COLOR_MODE_MONOCHROME) .build(); PrinterInfo printerInfo = new PrinterInfo.Builder(mThermalPrinter.getId(), "Kebio Prints", PrinterInfo.STATUS_IDLE) .setCapabilities(capabilities) .build(); discoveredPrinters.add(printerInfo); addPrinters(discoveredPrinters); Log.e(TAG, "Printer discovered: " + printerInfo.getName()); } @Override public void onStopPrinterDiscovery() { Log.e(TAG, "Stopping printer discovery..."); } @Override public void onValidatePrinters(List<PrinterId> printerIds) { Log.e(TAG, "Validating printers..."); } @Override public void onStartPrinterStateTracking(PrinterId printerId) { Log.e(TAG, "Starting printer state tracking for: " + printerId.getLocalId()); } @Override public void onStopPrinterStateTracking(PrinterId printerId) { Log.e(TAG, "Stopping printer state tracking for: " + printerId.getLocalId()); } @Override public void onDestroy() { Log.e(TAG, "Destroying discovery session..."); } } }
问题根源
Android PrintService会根据打印机能力参数对原始文档做适配处理,代码里的两个关键错误导致了文档降质:
- 媒体尺寸单位错误:
PrintAttributes.MediaSize的尺寸参数默认单位是千分之一英寸,你直接传入58(mm),实际58mm约等于2283千分之一英寸,错误的尺寸会让系统严重压缩文档。 - 分辨率参数不匹配:声明的1000x1000分辨率和多数58mm热敏打印机的实际203DPI不符,系统会因参数不兼容自动降质。
修复方案
1. 修正媒体尺寸
将58mm热敏纸的尺寸换算为正确的千分之一英寸单位:
// 58mm宽度≈2283千分之一英寸,高度设为10000支持连续打印 PrintAttributes.MediaSize customSize = new PrintAttributes.MediaSize( new PrintAttributes.MediaSizeName("THERMAL_58MM", "58mm Thermal Paper"), 2283, 10000);
2. 设置真实分辨率
使用热敏打印机常见的203DPI分辨率:
.addResolution(new PrintAttributes.Resolution("RES_203DPI", "203 DPI", 203, 203), true)
3. 验证文档属性
在processPrintJob中添加日志,确认文档的实际属性是否符合预期:
PrintAttributes docAttrs = printJob.getAttributes(); Log.d(TAG, "Doc resolution: " + docAttrs.getResolution()); Log.d(TAG, "Doc media size: " + docAttrs.getMediaSize());
如果日志显示的尺寸/分辨率和设置的不符,说明系统仍在调整文档,需要进一步检查打印机能力声明。
4. 优化流复制逻辑
可以使用Apache Commons IO的IOUtils.copy简化流复制,避免手动缓冲可能的问题:
// 需要添加依赖:implementation 'commons-io:commons-io:2.15.1' IOUtils.copy(inputStream, outputStream);
额外测试建议
- 直接打印到实际打印机,跳过PDF保存步骤,确认是否是PDF转换导致的质量损失。
- 过滤系统日志中的
PrintService标签,查看是否有文档缩放、质量调整的相关提示。
内容的提问来源于stack exchange,提问作者praneetk2
相关产品推荐
相关产品推荐

