【问题标题】:Importing a newer Apache HttpClient jar in Android在 Android 中导入更新的 Apache HttpClient jar
【发布时间】:2014-06-04 23:21:18
【问题描述】:

我正在尝试从我的 Android 客户端发送 HTTP/HTTPS 发布请求。

问题

为什么我的代码会失败?

到目前为止

我创建了一个 apache 类/HttpClient 调用。一切正常:

HttpClient httpClient = new DefaultHttpClient();

我已阅读此方法已被弃用,因此我已切换到新的推荐方法:

HttpClient httpClient = HttpClientBuilder.create().build();

Eclipse 没有这个类,所以我不得不下载 Apache HttpClient 4.3.3。我通过将其复制到 libs 文件夹并将它们添加到我的构建路径(导入的 httpclient、httpclient-cache、httpcore、httpmime、fluent-hc、commons-logging、commons-codec)将其导入到我的项目中。

错误信息

06-05 02:15:26.946: W/dalvikvm(29587): Link of class 'Lorg/apache/http/impl/conn/PoolingHttpClientConnectionManager;' failed
06-05 02:15:26.946: E/dalvikvm(29587): Could not find class 'org.apache.http.impl.conn.PoolingHttpClientConnectionManager', referenced from method org.apache.http.impl.client.HttpClientBuilder.build

最近的代码

static private String insertJson(String json,String url){
    HttpClient httpClient = HttpClientBuilder.create().build();

    String responseString = "";
    try {
        HttpPost request = new HttpPost(url);
        StringEntity params =new StringEntity(json, "UTF-8");
        request.addHeader("content-type", "application/json");
        request.setEntity(params);
        HttpResponse response = httpClient.execute(request);
        HttpEntity entity = response.getEntity();
        responseString = EntityUtils.toString(entity, "UTF-8");

    }catch (Exception ex) {
        ex.printStackTrace();
        // handle exception here
    } finally {
        httpClient.getConnectionManager().shutdown();
    }
    return responseString;
}

【问题讨论】:

  • 它可能在更新的库版本中被弃用。但是 Android 使用的是旧版本。我不认为它在 Android 中已被弃用。
  • @matlash 弃用和完全删除是有区别的。
  • @EJP 但“新建议方法”(HttpClientBuilder)在 Android 中甚至不存在。它是 httpclient 4.3 中的新功能,而 android 有 4.0beta2。 DefaultHttpClient 在该版本中尚未弃用,在 Android 中也未弃用。
  • 加载apk时logcat中没有任何先前的警告吗?某些类可能无法加载,因为 previous 类失败。

标签: java android apache-httpclient-4.x apache-httpcomponents


【解决方案1】:

问题是 Android 已经包含了旧版本的 Apache HttpClient(it's unclear exactly which,但大约是 4.0beta2)。

当您将新版本的 jars 添加为应用程序的库时,加载 APK 时会忽略重复的类。由于 HttpClient 中的一些 类依赖于对这些其他类进行的修改,因此 dalvik 会尽其所能(例如删除引用等),但除非有条件地使用它们,否则这是可能导致崩溃。

例如,您可以在 logcat 中看到类似这样的消息:

06-05 00:46:39.083: I/dalvikvm(6286): Could not find method org.apache.http.client.protocol.RequestDefaultHeaders.<init>, referenced from method org.apache.http.impl.client.HttpClientBuilder.build
06-05 00:46:39.083: W/dalvikvm(6286): VFY: unable to resolve direct method 22794: Lorg/apache/http/client/protocol/RequestDefaultHeaders;.<init> (Ljava/util/Collection;)V
06-05 00:46:40.434: D/dalvikvm(6286): DexOpt: couldn't find static field Lorg/apache/http/impl/client/DefaultHttpRequestRetryHandler;.INSTANCE
06-05 00:46:40.434: W/dalvikvm(6286): VFY: unable to resolve static field 8420 (INSTANCE) in Lorg/apache/http/impl/client/DefaultHttpRequestRetryHandler;

此特定消息是因为DefaultHttpRequestRetryHandler has a new INSTANCE static field in 4.3,其中it does not have in Android。还有很多。

回到您原来的问题,使用较新的 httpclient 的唯一方法是重命名 all 类,这样就不会发生这些名称冲突。这就是httpclientandroidlib 所做的。

更进一步:DefaultHttpClient has indeed been deprecated 在 4.3 中,但它在 Android 中被弃用(除非你认为 trend towards using HttpUrlConnection 是一种隐蔽的弃用形式——在这种情况下是更新的 HttpClient也不是首选的选择)。为什么你想要/需要改变它?

【讨论】:

【解决方案2】:

一年的答案,正确的答案是使用apache库的官方android端口,它使用不同的命名空间,从而避免冲突:https://hc.apache.org/httpcomponents-client-4.5.x/android-port.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多