Android Apache http 客户端问题 android 库

Android Issues with Apache http client android library

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

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

这是我的 gradle 配置:

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"
}

这是我添加库的方式:

compile 'com.clickntap:vimeo:1.10'

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

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

和警告:

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.

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

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'
}

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

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

请帮忙:(

谢谢,

P.S。 这是第一种情况的堆栈跟踪:

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.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.access1(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) 

这是第二种情况,其中包含 httpclient-android

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.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.access1(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 嵌入了 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 构造函数,它存在于 classpath 中,优先于 FileEntity class.[=18 的 httpclient-android 版本=]

我建议像第二种情况一样使用依赖项,但删除 useLibrary 'org.apache.http.legacy'

如果您使用的是在 4.3.5.1 之前或之后引入的 APIs,假设 public API的httpclient-android库与同版本的httpcomponents:httpclient库相同。

更新

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

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