You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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警告只是日志依赖缺失,不会导致崩溃,可后续再处理。

解决步骤

  1. 排除系统自带的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版本请替换为你实际使用的版本。

  2. 消除SLF4J警告(可选)
    如果想去掉SLF4J的警告,添加适配Android的SLF4J实现依赖:

    implementation 'org.slf4j:slf4j-android:1.7.36'
    
  3. 代码小优化
    你的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:30:57