How to use the legacy Apache HTTP client on Android Marshmallow?
Asked Answered
F

12

76

Background

On Android Marshmallow, Google has completely removed the support of Apache HTTP client (link here) because it doesn't have good performance compared to the alternatives.

This might also be the cause for so many apps crashing on Android Marshmallow.

The problem

Google allows you to still use this API, just not as a built in one, by adding this line to the gradle file:

useLibrary 'org.apache.http.legacy'

So, this is what I did:

dependencies {
    classpath 'com.android.tools.build:gradle:1.3.0'
}

And:

android {
    compileSdkVersion 'android-MNC'
    buildToolsVersion "23.0.0 rc3"
    useLibrary 'org.apache.http.legacy'

    defaultConfig {
        applicationId "com.example.user.androidmtest"
        minSdkVersion 'MNC'
        targetSdkVersion 'MNC'
        versionCode 1
        versionName "1.0"
    }

When I tried it, it compiled fine (no errors being shown, and I could run the proof-of-concept app, as it doesn't have any special code), but when I tried using some of the classes that I know that are part of the old API (like "HttpClient" class), I see that it doesn't allow me to do so.

I know it's not recommended to use this solution, but we must have the app ready to work there at least temporarily, till we work 100% on all of the things that should change for Android Marshmallow, and we don't want surprises in the form of crashes.

Here's a screenshot:

enter image description here

The question

Why does it occur? Did I use it correctly?


EDIT: reported about this issue here:

https://code.google.com/p/android/issues/detail?id=181474

Francescafrancesco answered 27/7, 2015 at 12:22 Comment(15)
by it compiled fine you mean gradle synced fine or are you getting a ClassNotFoundException at runtime?Adultery
Can you post some screenshot of android studioatCycad
@Adultery I mean that up to the time I've written classes that are supposed to be supported, it could be compiled&run fine (because there is nothing to use it). There can't be any ClassNotFoundException, because I don't use them yet. Only when I try to use classes that are supposed to be there, I can't. It doesn't allow me to do so and it doesn't offer me the needed imports.Francescafrancesco
@user4847410 Screenshot of what exactly ? Trying to put the import by force will result in it not being recognized. and using a class that exists there does it too. Anyway, I've updated the question to show the current situation, which is quite minimal...Francescafrancesco
Check if you're using the latest beta gradle. dependencies { classpath 'com.android.tools.build:gradle:1.3.0' } That seems like something is missing after the version (i.e. '-beta' or something). Using the latest beta solved it for meHillhouse
@Hillhouse Are you sure it's not final? The recent update says it's available: tools.android.com/recent/… "Include Andoid Gradle 1.3.0 in the offline Gradle plugin repository" . Doesn't it mean it's final?Francescafrancesco
@androiddeveloper Hmm. It says Release candidate 4, so I'm guessing it's not a GA load yet. But what I used to get this to work was com.android.tools.build:gradle:1.3.0-beta2. Please post an update if you figure out what was wrong, we're resorting to lots of ugly hacks all the timeHillhouse
@Hillhouse Tried the "1.3.0-beta2" . Still same results.Francescafrancesco
@androiddeveloper Oh. Bummer. Strange thing happened just now, when I changed the SDK to 'M' and build tools to the latest, Gradle version declaration reverted back to stable..Hillhouse
Ok, here's what I have (complete setup) - pastebin.com/Hx456HFh It's working now for me, hope it helps someoneHillhouse
@Hillhouse using your code, it says the plugin is too old, so I changed it to 1.3.0 . Anyway, it doesn't work, because as soon as I write "HttpClient s;" in code, it doesn't allow me to import it.Francescafrancesco
@androiddeveloper coPLaS answer worked for me so it should be marked as correct answerEph
Sorry. I am new to mobile development. I am using HTTPClient in my app. Does it mean that even if I keep my targetsdkversion 22 and run the app on Android marshmallow, it will crash ?Sherrod
@Sherrod You can try on the emulator... My guess is that it will crash.Francescafrancesco
To clarify what useLibrary is doing: Apache HttpClient is hidden in android-23 but is not actually removed. Otherwise lots of apps targeting earlier platforms would crash on M. Adding useLibrary serves to add these legacy classes to the boot classpath, essentially unhiding these classes at compile time (and at runtime). WenChao's comment below demonstrates that the classes are added to the boot classpath.Pinniped
S
93

Android Studio was complaining that org.apache.http classes like

org.apache.http.NameValuePair
org.apache.http.client.utils.URLEncodedUtils

were missing.

So I added org.apache.http.legacy.jar which is in Android/Sdk/platforms/android-23/optional folder to to app/libs

I also added this line to my app.gradle file

compile files('libs/org.apache.http.legacy.jar')

But if you're using more libraries, you can use this way

compile fileTree(dir: 'libs', include: ['*.jar'])

This resolved all my errors that were caused because google removed support of Apache HTTP client.

Supplication answered 18/8, 2015 at 7:50 Comment(16)
Worked for me. I had to add the Jar as a library to my app module though, to get rid of the Android Studio errors about HttpClient and so forth.Reversion
I get Proguard issues when I include org.apache.http.legacy.jar: IOExcpetion: Can't write [path to classes.jar] (Can't read [path to libs/org.apache.http.legacy.jar(;;;;;;!META-INF/MANIFEST.MF)] (Duplicate zip entry [org.apache.http.legacy.jar:org/apache/commons/codec/binary/Hex.class])) Anyone else using Proguard? Any ideas?Collings
This should be marked as Right Answer. It worked for me.Eph
@Collings probably you get proguard issues because other libs e.g. commons-codec in some of your modules.Controversy
what if I set android:targetSdkLevel to 22 or lower? Will my app crash on Android M?Luxuriance
I also use httpcore-4.3.1.jar and httpmime-4.3.2.jar , so adding the legacy jar file causes other issues (like: Error:(5, 43) error: package org.apache.http.entity.mime.content does not exist ) , and if I don't remove them, I get errors that say that the classes already exist (same package name and class name). BTW, I think this already use the jar file : compile fileTree(dir: 'libs', include: ['*.jar'])Francescafrancesco
@androiddeveloper I am also having same issue of multiple dex as i am using both jars you mentioned above. So did you find any solution for this?Artist
@NakAndroidDev Sadly no, and the team manager said we will move to okHttp to avoid those issues once and for all. I wonder how good it is.Francescafrancesco
@Supplication what about eclipse, where can I find this lib?Kaufman
@NakAndroidDev Did you solve it ? I've now tried to do it again, and now I got: Error:Execution failed for task ':app:packageAllSyncmeappDebugClassesForMultiDex'. > java.util.zip.ZipException: duplicate entry: org/apache/http/ConnectionClosedException.classFrancescafrancesco
yes; but it's not proper fix yet. I think its bug with Android Studio. What i did is added useLibrary 'org.apache.http.legacy' in my gradle file and then tried to build run the app. it worked as it should. But when I open my class file and write its code then it's showing me error that can not resolve all these packages and classes. but on compile time and execution its not showing any error,Artist
It is very sad that Google has chosen to use a hack requiring people to add a binary to their project rather than publishing http-legacy to an artefact repo. I thought we had left that anti-pattern behind 10 years ago.Aklog
Thanks Works ! I think that Google will need repair this problem.Soraya
Thanks. But When I'm using this now, all the basic classes and methods like HttpPost, HttpClient, NameValuePair, BasicNameValuePair are deprecated. Now WhatIridectomy
You are Genius, Sir.Hyla
It still hasn't worked for me even after this. Any possible diagnosis please @SupplicationCoeternity
A
11

Perfect solution here by running a simple file path check. by running

   android {
    compileSdkVersion 'android-MNC'
    buildToolsVersion "23.0.0 rc3"
    useLibrary 'org.apache.http.legacy'

    defaultConfig {
        applicationId "com.example.user.androidmtest"
        minSdkVersion 'MNC'
        targetSdkVersion 'MNC'
        versionCode 1
        versionName "1.0"

    }

        getBootClasspath().each{File file ->
           println file.absolutePath
        }
    }
}

You will get something like below

/Users/"yourname"/Development/android-sdk-macosx/platforms/android-MNC/android.jar /Users/"yourname"/Development/android-sdk-macosx/platforms/android-MNC/optional/org.apache.http.legacy.jar

So there you go, the jar is there.For some reason it didn't get added to the project. but you can always add it manually I guess.

Atalante answered 5/8, 2015 at 6:16 Comment(6)
I don't understand. What is this code you've written? You mean I should search for this jar, and add it to the project. Please explain.Francescafrancesco
Yeah, you are right. I wrote that code in build.gradle under android clause. Exactly what I'm saying, the jar didn't get picked up automatically . Perhaps you need to add it manuallyAtalante
What does the code do? Is it really needed? Also, have you checked it? Does it work fine?Francescafrancesco
No,it just prints the file path. doesn't do anything fancy, you can remove it safely. That jar contains everything from the old apache jar(HttpClient,Log, etc.) I suppose it will work just fine.Atalante
ok, thank you. hope that I won't need it when the time comes. Will check it again if/when needed. For now, You get +1 for the effort.Francescafrancesco
I've now got back to this issue. Now I get this error when trying to use the jar: Error:Execution failed for task ':app:packageAllSyncmeappDebugClassesForMultiDex'. > java.util.zip.ZipException: duplicate entry: org/apache/http/ConnectionClosedException.class .Did you also have this issue?Francescafrancesco
H
10

useLibrary 'org.apache.http.legacy' did not work for me until I upgraded the Gradle tools version in my main build.gradle file of my Android Studio project, as follows:

dependencies {
    classpath 'com.android.tools.build:gradle:1.3.0'
}
Hunfredo answered 24/8, 2015 at 19:22 Comment(4)
Thanks a lot! any idea why only this change solve the issue?Deterge
Apparently the useLibrary directive was only added to Gradle fairly recently, so need to use a newer version as I stated above.Hunfredo
I have this in the main gradle file : classpath 'com.android.tools.build:gradle:1.0.0-rc2' So should I remove this and add your line or keep both the lines and it would work without any problemThundercloud
Remove that and add the above.Hunfredo
F
6

The answer above just helps the debug builds to run, and release builds that are utilizing gradle.

Insert this inside the application tag on the manifest file, on all project instances that uses the legacy apache classes:

<uses-library android:name="org.apache.http.legacy" android:required="false" />

This helps for those who are still using Eclipse and ant scripts during compile.

Feathered answered 4/11, 2015 at 1:40 Comment(0)
K
6

After many frustrating hours, the following worked:

1. Locate the apache jar. It should reside somewhere like:

C:\Users\<yourname>\AppData\Local\Android\sdk\platforms\android-23\optional

2. Copy org.apache.http.legacy.jar to your libs folder.

Either right click on libs -> paste , or use your file explorer to navigate to the libs folder of your project and paste.

If you don't have a libs folder, as I did, make a new project and import all relevant files into their respective places.

3. Click ok see this

4. Most important step: Right click on the apache folder and select Add As Library. see this

Hope this helps someone get on with their life.

Kelcey answered 13/5, 2016 at 20:4 Comment(0)
C
2

First you have to check that in your libs folder

Make sure in Libs Folder Check that apache library

Then add into your gradle file like this 

    android {
        compileSdkVersion 23
        buildToolsVersion '23.0.2'

        defaultConfig {
            applicationId "info.tranetech.laundry"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    android {
        useLibrary 'org.apache.http.legacy'
    }
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:appcompat-v7:23.0.1
        compile 'com.android.support:design:23.0.1
        testCompile 'junit:junit:4.12'
        compile files('libs/android-async-http-1.4.4.jar')
        compile 'com.google.android.gms:play-services:8.4.0'
    }

This Is my gradle file

Also check external library

Closemouthed answered 27/7, 2015 at 12:23 Comment(0)
T
2

Legacy Apache library located in

[ANDROID_SDK]\platforms\android-23\optional\org.apache.http.legacy.jar 

So you can copy it inside you project libs or just use

compile files("${android.getSdkDirectory().getAbsolutePath()}" + File.separator + "platforms" + File.separator + "android-23" + File.separator + "optional" + File.separator + "org.apache.http.legacy.jar")

in your /app/build.gradle

Tridentine answered 17/9, 2015 at 9:25 Comment(0)
C
2

I know this is silly reason but at list try it...

I experienced this problem recently, and it is caused by the path length restriction I think it´s 256 characters maximum.

Relocate your Project and the build will succeed.Hope this work for you.

Closemouthed answered 28/11, 2015 at 9:57 Comment(3)
this is not silly... this is the answer that worked in my case... Past 36 hours I spent trying everything on earth, except this.. It sound silly in the beginning so I didn't take it seriously..Dorren
Guys, try this out too... It really worked for me, where everything else failedDorren
it's my pleasure.@DorrenClosemouthed
R
1

Enable this in sdk/platforms/android-23/optional/optional.json

[
  {
    "name": "org.apache.http.legacy",
    "jar": "org.apache.http.legacy.jar",
    "manifest": false
  }
]
Ringo answered 26/2, 2016 at 7:17 Comment(0)
M
1

Remove

useLibrary 'org.apache.http.legacy' 

from the build.gradle and I also added this line to my app.gradle file

compile files('libs/org.apache.http.legacy.jar')

But if you're using more libraries, you can use this way

compile fileTree(dir: 'libs', include: ['*.jar'])

CoPLaS answer fixed my problems.

Milton answered 15/3, 2016 at 2:17 Comment(1)
Then just upvote CoPLaS answer instead of reproducing it here!Launcher
F
0

A simple way to solve this issue is C:\Users\username\AppData\Local\Android\sdk\platforms. Here delete your android-23 and from SDK manager update your API 23 again. It will solve your issue.

Foxhole answered 15/12, 2015 at 10:21 Comment(0)
M
0

How to use the legacy Apache HTTP client on Android Marshmallow?

To continue using Apache HTTP classes for API 23+:

First of all, be sure to add the gradle dependencie into the build.gradle f

buildscript {

    dependencies {
        classpath 'com.android.tools.build:gradle:2.0.0'
    }
}

Then add the reference inside build.gradle of your project:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.0"
    useLibrary 'org.apache.http.legacy'
    ...
}
Monney answered 4/5, 2016 at 23:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.