Android Issues with Apache http client android library

匆匆过客 提交于 2019-12-14 03:05:54

问题


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) 

回答1:


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.



来源:https://stackoverflow.com/questions/46338408/android-issues-with-apache-http-client-android-library

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!