Android App Licensing crashes on Android Pie
Asked Answered
F

3

6

The error says URLEncodedUtils is not found. Is there a workaround.

Caused by java.lang.ClassNotFoundException
    Didn't find class "org.apache.http.client.utils.URLEncodedUtils" on path: DexPathList[[zip file "/data/app/com.app.p-MY70To6m946K0_uiYLCsSg==/base.apk"],nativeLibraryDirectories=[/data/app/com.app.p-MY70To6m946K0_uiYLCsSg==/lib/arm64, /data/app/com.app.p-MY70To6m946K0_uiYLCsSg==/base.apk!/lib/arm64-v8a, /system/lib64]]
Felten answered 25/8, 2018 at 19:15 Comment(2)
Could you please post your Gradle (App)Mandymandych
Possible duplicate of java.lang.NoSuchMethodError org.apache.http.client.utils.URLEncodedUtils.encPathPavel
F
3

Google doesn't support legacy apache library so in the original class APKEpansionPolicy this method uses URLEncodedUtils and NameValuePair

private Map<String, String> decodeExtras(String extras) {
        Map<String, String> results = new HashMap<String, String>();
        try {
            URI rawExtras = new URI("?" + extras);
            List<NameValuePair> extraList = URLEncodedUtils.parse(rawExtras, "UTF-8");
            for (NameValuePair item : extraList) {
                String name = item.getName();
                int i = 0;
                while (results.containsKey(name)) {
                    name = item.getName() + ++i;
                }
                results.put(name, item.getValue());
            }
        } catch (URISyntaxException e) {
            Log.w(TAG, "Invalid syntax error while decoding extras data from server.");
        }
        return results;
    }

Replace this method in this and any other class with this piece of code that is splitting the query and using Map instead of NameValuePair.

private Map<String, String> decodeExtras(String extras) {
    Map<String, String> results = new HashMap<String, String>();
    try {
        URI rawExtras = new URI("?" + extras);
        Map<String, String> extraList = splitQuery(new URL(rawExtras.toString()));
        for (Map.Entry<String, String> entry : extraList.entrySet())
        {
            String name = entry.getKey();
            int i = 0;
            while (results.containsKey(name)) {
                name = entry.getKey() + ++i;
            }
            results.put(name, entry.getValue());
        }
    } catch (URISyntaxException e) {
        Log.w(TAG, "Invalid syntax error while decoding extras data from server.");
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return results;
}

public static Map<String, String> splitQuery(URL url) throws UnsupportedEncodingException {
    Map<String, String> query_pairs = new LinkedHashMap<String, String>();
    String query = url.getQuery();
    String[] pairs = query.split("&");
    for (String pair : pairs) {
        int idx = pair.indexOf("=");
        query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
    }
    return query_pairs;
}
Felten answered 10/9, 2018 at 16:47 Comment(0)
R
8

The Apache libraries have been removed. If you were previously using

useLibrary 'org.apache.http.legacy 

in your build.gradle, it no longer works in Android Pie.

Instead, you have to add

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

to your AndroidManifest.

See here for official release notes

Rushton answered 5/12, 2018 at 1:5 Comment(1)
My app needed both, I guess because I have a high targetSdkVersion and a low minSdkVersion.Monocotyledon
F
3

Google doesn't support legacy apache library so in the original class APKEpansionPolicy this method uses URLEncodedUtils and NameValuePair

private Map<String, String> decodeExtras(String extras) {
        Map<String, String> results = new HashMap<String, String>();
        try {
            URI rawExtras = new URI("?" + extras);
            List<NameValuePair> extraList = URLEncodedUtils.parse(rawExtras, "UTF-8");
            for (NameValuePair item : extraList) {
                String name = item.getName();
                int i = 0;
                while (results.containsKey(name)) {
                    name = item.getName() + ++i;
                }
                results.put(name, item.getValue());
            }
        } catch (URISyntaxException e) {
            Log.w(TAG, "Invalid syntax error while decoding extras data from server.");
        }
        return results;
    }

Replace this method in this and any other class with this piece of code that is splitting the query and using Map instead of NameValuePair.

private Map<String, String> decodeExtras(String extras) {
    Map<String, String> results = new HashMap<String, String>();
    try {
        URI rawExtras = new URI("?" + extras);
        Map<String, String> extraList = splitQuery(new URL(rawExtras.toString()));
        for (Map.Entry<String, String> entry : extraList.entrySet())
        {
            String name = entry.getKey();
            int i = 0;
            while (results.containsKey(name)) {
                name = entry.getKey() + ++i;
            }
            results.put(name, entry.getValue());
        }
    } catch (URISyntaxException e) {
        Log.w(TAG, "Invalid syntax error while decoding extras data from server.");
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return results;
}

public static Map<String, String> splitQuery(URL url) throws UnsupportedEncodingException {
    Map<String, String> query_pairs = new LinkedHashMap<String, String>();
    String query = url.getQuery();
    String[] pairs = query.split("&");
    for (String pair : pairs) {
        int idx = pair.indexOf("=");
        query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
    }
    return query_pairs;
}
Felten answered 10/9, 2018 at 16:47 Comment(0)
P
1

I wonder if this is still available on Pie, but besides the suggestions at the other possibly duplicate question, there's also a Gradle configuration for that: useLibrary 'org.apache.http.legacy', in order to use the legacy classes (while still available). otherwise, and in general, migrating to okhttp3 might be still the best option.

Pavel answered 25/8, 2018 at 20:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.