Android Issues with Apache http client android library
R

1

0

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) 
Riva answered 21/9, 2017 at 7:55 Comment(3)
Check section 'Apache HTTP Client Removal' in this page developer.android.com/about/versions/marshmallow/… . I guess it'll help this situation.Violetteviolin
do you have a choice in libraries? I wouldn't use that library solely because it doesn't let me swap the underlying httpclient (it's forcing you to use apache... hence your problem)Enwrap
thank you, I ended up creating my own android upload library following the vimeo api specsRiva
H
2

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.

Hibernicism answered 7/10, 2017 at 23:23 Comment(3)
Hi, thanks for your help. I tried that but still got the Caused by: java.lang.NoSuchMethodError: org.apache.http.entity.FileEntity.<init> errorRiva
Hi, thanks for the feedback. Please check the updated answer.Hibernicism
thank you very much for the explanations! I see, I ended up creating my own android upload library following the vimeo api specsRiva

© 2022 - 2024 — McMap. All rights reserved.