Apache http 客户端 android 库的 Android 问题 [英] Android Issues with Apache http client android library

本文介绍了Apache http 客户端 android 库的 Android 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我正在使用的库:https://github.com/clickntap/Vimeo

我正在尝试将该库用于 Android 应用.我的测试设备是 Kitkat (4.4.4).

这是我的 gradle 配置:

compileSdkVersion 25构建工具版本25.0.3"useLibrary 'org.apache.http.legacy'默认配置{applicationId "my.app.package"minSdk 版本 16目标SDK版本25版本代码 1版本名称1.0.0-alpha"}

这是我添加库的方式:

编译'com.clickntap:vimeo:1.10'

但是我在 Vimeo.addVideo() 上收到以下错误:

java.lang.NoClassDefFoundError: org.apache.http.impl.client.HttpClientBuilder

和警告:

警告:调试时忽略依赖 org.apache.httpcomponents:httpclient:4.3.6,因为它可能与 Android 提供的内部版本冲突.警告:调试时忽略依赖关系 org.json:json:20140107,因为它可能与 Android 提供的内部版本冲突.

所以我搜索了一下,发现我可以做这样的事情:

编译'org.apache.httpcomponents:httpclient-android:4.3.5.1'编译('com.clickntap:vimeo:1.10'){排除组:'org.apache.httpcomponents'排除组:'org.json'}

但现在我在 Vimeo.addVideo() 上仍然收到此错误并且找不到任何解决方案:

java.lang.NoSuchMethodError: org.apache.http.entity.FileEntity.

请帮忙:(

谢谢,

附言这是第一个场景的堆栈跟踪:

Caused by: java.lang.NoClassDefFoundError: org.apache.http.impl.client.HttpClientBuilder在 com.clickntap.vimeo.Vimeo.apiRequest(Vimeo.java:218)在 com.clickntap.vimeo.Vimeo.beginUploadVideo(Vimeo.java:122)在 com.clickntap.vimeo.Vimeo.addVideo(Vimeo.java:138)在 my.app.package.VimeoActivity$6.subscribe(VimeoActivity.java:163)//我的活动在 io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:39)在 io.reactivex.Single.subscribe(Single.java:2702)在 io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)在 io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:451)在 io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)在 io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)在 java.util.concurrent.FutureTask.run(FutureTask.java:237)在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)在 java.lang.Thread.run(Thread.java:841)

这里是第二个场景,其中包含 httpclient-android:

Caused by: java.lang.NoSuchMethodError: org.apache.http.entity.FileEntity.在 com.clickntap.vimeo.Vimeo.apiRequest(Vimeo.java:247)在 com.clickntap.vimeo.Vimeo.uploadVideo(Vimeo.java:126)在 com.clickntap.vimeo.Vimeo.addVideo(Vimeo.java:140)在 my.app.package.VimeoActivity$6.subscribe(VimeoActivity.java:163)//我的活动在 io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:39)在 io.reactivex.Single.subscribe(Single.java:2702)在 io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)在 io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:451)在 io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)在 io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)在 java.util.concurrent.FutureTask.run(FutureTask.java:237)在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)在 java.lang.Thread.run(Thread.java:841)

解决方案

Android version<6 内嵌了一个 fork of Apache HTTP Client 4.0.beta 快照 (https://hc.apache.org/httpcomponents-client-4.3.x/android-port.html).>

第一个场景失败,因为 HttpClientBuilder 是在 httpclient:4.3 上引入的.

第二种情况失败,因为您同时使用了加载旧版 httpclient 库的 useLibrary 'org.apache.http.legacy'compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'.Vimeo 客户端使用遗留库中不存在的 FileEntity 构造函数,该构造函数存在于类路径中,并且优先于 FileEntity 类的 httpclient-android 版本.

我建议使用第二个场景中的依赖项,但删除 useLibrary 'org.apache.http.legacy'.

如果您使用的是在 4.3.5.1 之前或之后引入的 API,则此解决方案适用于 httpcomponents:httpclient 的任何依赖项,假设 httpclient-android 库的公共 API与同版本的httpcomponents:httpclient 库相同.

更新

如果您的代码或任何依赖项明确使用已在 httpclient-android 库中替换的 API,以便不与 Android SDK 的旧版 httpclient 冲突,则此解决方案将不起作用.org.apache.httpcomponents:httpclient 提供了构建器(例如 HttpClientBuilder、EntityBuilder、MultipartEntityBuilder),它们抽象了正在使用的实际类,这应该是首选.不幸的是,访问内部"类/API 和使用构建器都是可能的(可能是为了保持兼容性),但我认为库应该允许一种干净的方式.

在上面的例子中,Vimeo 库直接使用 FileEntity 构造函数,该构造函数将库与特定类耦合,如果使用了 EntityBuilder,这可以解耦.所以我能看到的唯一方法是修改库源代码,使其与httpclient-android库和Android兼容.

This is the library that I'm using: https://github.com/clickntap/Vimeo

I'm trying to use the library for an Android app. My test device is Kitkat (4.4.4).

Here's my gradle config:

compileSdkVersion 25
buildToolsVersion "25.0.3"
useLibrary  'org.apache.http.legacy'

defaultConfig {
    applicationId "my.app.package"
    minSdkVersion 16
    targetSdkVersion 25
    versionCode 1
    versionName "1.0.0-alpha"
}

Here's how I added the library:

compile 'com.clickntap:vimeo:1.10'

But I receive the following error on Vimeo.addVideo():

java.lang.NoClassDefFoundError: org.apache.http.impl.client.HttpClientBuilder

and warnings:

WARNING: Dependency org.apache.httpcomponents:httpclient:4.3.6 is ignored for debug as it may be conflicting with the internal version provided by Android.
WARNING: Dependency org.json:json:20140107 is ignored for debug as it may be conflicting with the internal version provided by Android.

So I searched a little and found that I could do something like this:

compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'
compile('com.clickntap:vimeo:1.10') {
    exclude group: 'org.apache.httpcomponents'
    exclude group: 'org.json'
}

But now I'm receiving this error still on Vimeo.addVideo() and can't find any solution:

java.lang.NoSuchMethodError: org.apache.http.entity.FileEntity.<init>

Please help :(

Thanks,

P.S. Here's the stack trace for the 1st scenario:

Caused by: java.lang.NoClassDefFoundError: org.apache.http.impl.client.HttpClientBuilder
                at com.clickntap.vimeo.Vimeo.apiRequest(Vimeo.java:218)
                at com.clickntap.vimeo.Vimeo.beginUploadVideo(Vimeo.java:122)
                at com.clickntap.vimeo.Vimeo.addVideo(Vimeo.java:138)
                at my.app.package.VimeoActivity$6.subscribe(VimeoActivity.java:163) // my activity
                at io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:39)
                at io.reactivex.Single.subscribe(Single.java:2702)
                at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
                at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:451)
                at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
                at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52) 
                at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 
                at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
                at java.lang.Thread.run(Thread.java:841) 

And here's for the 2nd scenario, where the httpclient-android is included:

Caused by: java.lang.NoSuchMethodError: org.apache.http.entity.FileEntity.<init>
                at com.clickntap.vimeo.Vimeo.apiRequest(Vimeo.java:247)
                at com.clickntap.vimeo.Vimeo.uploadVideo(Vimeo.java:126)
                at com.clickntap.vimeo.Vimeo.addVideo(Vimeo.java:140)
                at my.app.package.VimeoActivity$6.subscribe(VimeoActivity.java:163) // my activity
                at io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:39)
                at io.reactivex.Single.subscribe(Single.java:2702)
                at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
                at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:451)
                at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
                at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52) 
                at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 
                at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
                at java.lang.Thread.run(Thread.java:841) 

解决方案

Android version<6 embedded a fork of Apache HTTP Client 4.0.beta snapshot (https://hc.apache.org/httpcomponents-client-4.3.x/android-port.html).

The 1st scenario fails because HttpClientBuilder was introduced on httpclient:4.3.

The 2nd scenario fails because you are using both useLibrary 'org.apache.http.legacy' that loads the legacy httpclient library and compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'. Vimeo client uses a FileEntity constructor that did not exist in the legacy library, which exists in the classpath and takes priority over the httpclient-android version of the FileEntity class.

I would suggest to use the dependencies as in the 2nd scenario, but remove useLibrary 'org.apache.http.legacy'.

This solution will work with any dependency on httpcomponents:httpclient if you are using APIs that were introduced before or on 4.3.5.1 and not later, assuming that the public API of the httpclient-android library is identical to the httpcomponents:httpclient library of the same version.

Update

This solution will not work if your code or any of your dependencies use explicitly an API that has been replaced in the httpclient-android library in order to not conflict with the legacy httpclient version of the Android SDK. org.apache.httpcomponents:httpclient provides builders (e.g. HttpClientBuilder, EntityBuilder, MultipartEntityBuilder) which abstract the actual classes being used, that should be preferred. Unfortunately, both accessing "internal" classes/APIs and using Builders is possible (probably to maintain compatibility), but I believe that a single clean way should be permitted by the library.

In the above example, Vimeo library directly uses FileEntity constructor, which couples the library with a specific class, while this could be decoupled, if the EntityBuilder was used. So the only way I can see, is to modify the library source code, to make it compatible with httpclient-android library and Android in general.

这篇关于Apache http 客户端 android 库的 Android 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆