Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using org.apache.http.legacy in Android 9

Tags:

java

android

I have an old android app that uses the apache legacy Http library (org.apache.http.legacy). After the changes on Android 6, I was able to keep the app working including the legacy library.

useLibrary 'org.apache.http.legacy'.

Now in Android 9 devices I get the below exceptions at runtime.

Caused by: java.lang.IncompatibleClassChangeError: Class 'org.apache.http.conn.ssl.SSLSocketFactory' does not implement interface 'org.apache.http.conn.scheme.SchemeSocketFactory' in call to 'java.net.Socket org.apache.http.conn.scheme.SchemeSocketFactory.createSocket(org.apache.http.params.HttpParams)' (declaration of 'org.apache.http.impl.conn.DefaultClientConnectionOperator' appears in /data/app/com.theprojectfactory.wmp-RdZODaT5h-l1diSw3oNCvA==/base.apk)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:304)
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)

Reading the Android 9 changes docs, there is a mention to add <uses-library android:name="org.apache.http.legacy" android:required="false"/> in the AndroidManifes.xml file, however that does not seem to work for me either as I get the below exception instead when launching the app.

java.lang.VerifyError: Superclass org.apache.http.params.BasicHttpParams of org.apache.http.params.SyncBasicHttpParams is declared final (declaration of 'org.apache.http.params.SyncBasicHttpParams' appears in /data/app/com.theprojectfactory.wmp-R2P9RNgoJ82ZupwxVa7iNA==/base.apk)
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:453)
    at com.activeandroid.ModelInfo.scanForModelClasses(ModelInfo.java:187)
    at com.activeandroid.ModelInfo.scanForModel(ModelInfo.java:152)
    at com.activeandroid.ModelInfo.<init>(ModelInfo.java:63)
    at com.activeandroid.Cache.initialize(Cache.java:66)
    at com.activeandroid.ActiveAndroid.initialize(ActiveAndroid.java:44)
    at com.activeandroid.ActiveAndroid.initialize(ActiveAndroid.java:34)
    at com.activeandroid.content.ContentProvider.onCreate(ContentProvider.java:39)
    at android.content.ContentProvider.attachInfo(ContentProvider.java:1917)
    at android.content.ContentProvider.attachInfo(ContentProvider.java:1892)
    at android.app.ActivityThread.installProvider(ActivityThread.java:6391)
    at android.app.ActivityThread.installContentProviders(ActivityThread.java:5938)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5853)
    at android.app.ActivityThread.access$1100(ActivityThread.java:199)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1650)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Any pointers on how to keep using the org.apache.http.legacy on Android 9 api will be much appreciated.

like image 672
velval Avatar asked Jan 29 '19 05:01

velval


2 Answers

You have to add attribute of android:usesCleartextTraffic="true" on application tag in AndroidManifes.xml file.

And also add this.

<uses-library android:name="org.apache.http.legacy" android:required="false"/>
like image 76
Kaushal Panchal Avatar answered Nov 17 '22 05:11

Kaushal Panchal


So after further troubleshooting found out that issue was due to a third party library (activeandroid). Library was using reflection to check all classes available in the classpath and for some reason the legacy apache HTTP classes conflicted when calling java.lang.Class.classForName. Skipped the reflection code and app worked as expected. On versions below Android 9 this is not an issue though.

So correct way is as per documentation using: <uses-library android:name="org.apache.http.legacy" android:required="false"/>. If you come across random exceptions check you are not using reflection to try to traverse the legacy HTTP classes.

like image 24
velval Avatar answered Nov 17 '22 06:11

velval