Android项目使用Cups4j获取打印机信息报错,求问题排查
问题描述
我在Android(Java)项目中导入了Cups4j,参考官方导入文档编写了代码,尝试通过CupsClient获取打印机列表,但运行时抛出致命异常。
我的代码
private class PrintTask extends AsyncTask<Void, Void, PrintRequestResult> { @Override protected PrintRequestResult doInBackground(Void... params) { try { CupsClient cupsClient = new CupsClient("myIP", 631); List<CupsPrinter> printers = cupsClient.getPrinters(); for (CupsPrinter printer : printers) { System.out.println("Printer Name: " + printer.getName()); } } catch (IOException e) { Log.e("PrintError", "Error while reading file or communicating with the printer : ", e); e.printStackTrace(); } catch (Exception e) { Log.e("PrintError", "Error : ", e); e.printStackTrace(); } return null; } @Override protected void onPostExecute(PrintRequestResult result) { if (result != null && result.isSuccessfulResult()) { Log.d("PrintSuccess", "Print job submitted successfully!"); } else { Log.e("PrintError", "Print job failed: " + (result != null ? result.getResultMessage() : "Unknown error")); } } }
运行时错误日志
W/System.err: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". W/System.err: SLF4J: Defaulting to no-operation (NOP) logger implementation W/System.err: SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1 Process: com.example.wifidir, PID: 31309 java.lang.RuntimeException: An error occurred while executing doInBackground() at android.os.AsyncTask$4.done(AsyncTask.java:415) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383) at java.util.concurrent.FutureTask.setException(FutureTask.java:252) at java.util.concurrent.FutureTask.run(FutureTask.java:271) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:923) Caused by: java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; in class Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; or its superclasses (declaration of 'org.apache.http.conn.ssl.AllowAllHostnameVerifier' appears in /system/framework/framework.jar!classes5.dex) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.<clinit>(SSLConnectionSocketFactory.java:151) at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:977) at org.cups4j.operations.IppHttp.<clinit>(IppHttp.java:33) at org.cups4j.operations.IppHttp.createHttpClient(IppHttp.java:39) at org.cups4j.operations.IppOperation.sendRequest(IppOperation.java:157) at org.cups4j.operations.IppOperation.sendRequest(IppOperation.java:130) at org.cups4j.operations.IppOperation.request(IppOperation.java:64) at org.cups4j.operations.cups.CupsGetPrintersOperation.getPrinters(CupsGetPrintersOperation.java:59) at org.cups4j.CupsClient.getPrinters(CupsClient.java:138) at com.example.wifidir.MainActivity$PrintTask.doInBackground(MainActivity.java:55) at com.example.wifidir.MainActivity$PrintTask.doInBackground(MainActivity.java:50) at android.os.AsyncTask$3.call(AsyncTask.java:394) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:923)
我不确定问题出在代码还是依赖配置上,请问我的代码有问题吗?
问题分析与解决方案
你的代码逻辑本身没问题,致命错误的根源是Apache HttpClient版本冲突:
- Android系统自带了旧版本的Apache HttpClient库,而Cups4j依赖的新版本HttpClient中,
AllowAllHostnameVerifier类的INSTANCE静态字段在系统旧版本里不存在,导致加载类时抛出NoSuchFieldError。 - 开头的SLF4J警告只是日志依赖缺失,不会导致崩溃,可后续再处理。
解决步骤
排除系统自带的HttpClient依赖
在Module级别的build.gradle中添加配置,强制使用兼容Android的HttpClient版本:android { useLibrary 'org.apache.http.legacy' packagingOptions { exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE' } } dependencies { // 导入Cups4j时排除冲突的HttpClient模块 implementation('org.cups4j:cups4j:0.7.6') { exclude group: 'org.apache.httpcomponents', module: 'httpclient' } // 引入适配Android的HttpClient版本 implementation 'org.apache.httpcomponents:httpclient-android:4.3.5.1' }注意:Cups4j版本请替换为你实际使用的版本。
消除SLF4J警告(可选)
如果想去掉SLF4J的警告,添加适配Android的SLF4J实现依赖:implementation 'org.slf4j:slf4j-android:1.7.36'代码小优化
你的doInBackground始终返回null,导致onPostExecute永远走错误分支,可修改为返回明确的结果:@Override protected PrintRequestResult doInBackground(Void... params) { try { CupsClient cupsClient = new CupsClient("myIP", 631); List<CupsPrinter> printers = cupsClient.getPrinters(); for (CupsPrinter printer : printers) { Log.d("PrinterInfo", "Printer Name: " + printer.getName()); } return new PrintRequestResult(true, "成功获取打印机列表"); } catch (IOException e) { Log.e("PrintError", "与打印机通信时发生IO错误: ", e); } catch (Exception e) { Log.e("PrintError", "发生意外错误: ", e); } return new PrintRequestResult(false, "获取打印机列表失败"); }
内容的提问来源于stack exchange,提问作者Jungwon
相关产品推荐
相关产品推荐

