8

I am trying to understand Android's current relationship to Apache http-client. I need to use a standard Java library which relies on org.apache.httpcomponents:httpclient:4.5.2 and it appears to be impossible on Android.

We can see that in Android M, support was removed for httpclient. And in Android P, the library was removed from the boot class path and is unavailable to apps without a manifest entry. I can also see that there is an official Apache Android port of httpclient which is a suitable direct replacement for 4.3.5.1 if you need a slightly more modern version of the library. And that there is even a third party port of 4.4.1.1 for apps with a modern target sdk.

My app's min sdk is 17, and target sdk is 28. So my first question is, would it actually be possible to kill any reference to the Android version of apache httpclient with a min sdk stuck at 17, and if not how can I replace that version with 4.5.2 which is inside the library.

My specific error is java.lang.NoSuchFieldError: org.apache.http.conn.ssl.AllowAllHostnameVerifier.INSTANCE, and even though I have a target SDK of 28, Android is still finding and using a legacy AllowAllHostnameVerifier.java class with no INSTANCE field:

enter image description here

Daniel Wilson
  • 18,838
  • 12
  • 85
  • 135
  • try this : https://stackoverflow.com/questions/50782806/android-google-maps-java-lang-noclassdeffounderror-failed-resolution-of-lorg-a – mridul Feb 12 '19 at 15:14
  • Thanks @mridul but the legacy http client is the opposite of what I need :) – Daniel Wilson Feb 12 '19 at 15:19
  • @DanielWilson have you try use this in your manifest application tag: – Paraskevas Ntsounos Feb 18 '19 at 11:53
  • Thanks anyway but judging from this and the previous comment maybe I am not being clear, the legacy version of apache http client is no good, it does not feature some of the variables and calls made by this new library which my app needs to use. – Daniel Wilson Feb 18 '19 at 12:10
  • How about jst put the source of Apache http-client 4.5.x into your project. Local resources with same name have higher priority. Ugly, not recommended, maybe dangerous, but should work. – Clxy Feb 25 '19 at 03:58
  • This was the first thing I tried because it's how it should work :) I think it is true in the case of an app vs a library dependency but this is a platform vs a library dependency. From what I can tell Android's version of Apache http-client always takes precedence. Hence the existence of SpongyCastle. Thanks though. – Daniel Wilson Feb 25 '19 at 07:53

1 Answers1

3

You can not directly replace classes included in the Android framework. The only solution is to use a different namespace. This is why Spongy Castle uses org.spongycastle.* instead of org.bouncycastle.*, and the project you linked uses cz.msebera.android.httpclient.* instead of org.apache.http.*.

Unfortunately, this means that you have to change every reference to http-client in your library.

Since the release of Android Jetpack, the SDK includes Jetifier, a tool to translate references in libraries bytecode at buildtime. There is a standalone version, and it can use custom mapping config.

In you case this would imply:

  • Create a custom config translating org.apache.http to cz.msebera.android.httpclient
  • Convert your standard Java library
  • Use the transformed library and the third party port of http-client

Another possible solution to convert the library would be to use Jar Jar.

bwt
  • 17,292
  • 1
  • 42
  • 60
  • Thanks @bwt yeah I stumbled across SpongyCastle during my Googles. All of this sounds above my pay grade but I am glad I didn't miss something obvious. I think using a lib that relies on apache-http client in an Android app is much more trouble than it's worth so should be avoided if possible. – Daniel Wilson Feb 25 '19 at 07:55