Search code examples
androidjsonexception

JSONException since Android Api 28 (String result = "")


Upgraded to Android Api 28. Now im getting an curios JSONException. Actually its not clear how I can solve the problem. I know why this is happen, but I don't know how to fix it at this time.

This part should produce the error "String result = "";" and on line 74 on this part "JSONObject json = new JSONObject(result);" JSON crashed

GetJsonResults

import java.io.InputStreamReader;

public class GetJsonResults extends AsyncTask<String, Void, String> {
    private final static String LOG_TAG = GetJsonResults.class.getSimpleName();

    private static String GET(String url) {
        InputStream inputStream;
        String result = "";
        try {

            // create HttpClient
            HttpClient httpclient = new DefaultHttpClient();

            // make GET request to the given URL
            HttpResponse httpResponse = httpclient.execute(new HttpGet(url));

            // receive response as inputStream
            inputStream = httpResponse.getEntity().getContent();

            // convert inputstream to string
            if (inputStream != null)
                result = convertInputStreamToString(inputStream);
            else
                result = "Did not work!";

        } catch (Exception e) {
            Log.d("InputStream", e.getLocalizedMessage());
        }

        return result;
    }

    private static String convertInputStreamToString(InputStream inputStream) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        String result = "";
        while ((line = bufferedReader.readLine()) != null)
            result += line;

        inputStream.close();
        return result;

    }

    @Override
    protected String doInBackground(String... urls) {

        return GET(urls[0]);
    }

    // onPostExecute displays the results of the AsyncTask.
    @Override
    protected void onPostExecute(String result) {
        //Toast.makeText(getBaseContext(), "Daten erfolgreich empfangen!", Toast.LENGTH_LONG).show();
        try {
            JSONObject json = new JSONObject(result);
2019-07-11 16:59:02.919 10072-10072/com.radio.xxxxxxSRAPPID D/SplashActivity: Get JSON Results
2019-07-11 16:59:04.312 10072-10072/com.radio.xxxxxxSRAPPID D/GetJsonResults: There was an JSONException
2019-07-11 16:59:04.312 10072-10072/com.radio.xxxxxxSRAPPID W/System.err: org.json.JSONException: Value http of type java.lang.String cannot be converted to JSONObject
2019-07-11 16:59:04.312 10072-10072/com.radio.xxxxxxSRAPPID W/System.err:     at org.json.JSON.typeMismatch(JSON.java:112)
2019-07-11 16:59:04.312 10072-10072/com.radio.xxxxxxSRAPPID W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:163)
2019-07-11 16:59:04.312 10072-10072/com.radio.xxxxxxSRAPPID W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:176)
2019-07-11 16:59:04.312 10072-10072/com.radio.xxxxxxSRAPPID W/System.err:     at com.radio.xxxxxx.task.GetJsonResults.onPostExecute(GetJsonResults.java:74)
2019-07-11 16:59:04.312 10072-10072/com.radio.xxxxxxSRAPPID W/System.err:     at com.radio.xxxxxx.task.GetJsonResults.onPostExecute(GetJsonResults.java:21)

Solution

  • This is happening because http calls are disabled by default in API 28, you can use the below work around to enable http calls in API 28,

    In your AndroidManifest.xml, put

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ... >
        <application android:networkSecurityConfig="@xml/network_security_config">
    
    
    
    
        </application>
    </manifest>
    

    Create network_security_config.xml file in resource directory and paste below source in it,

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <base-config cleartextTrafficPermitted="true">
            <trust-anchors>
                <certificates src="system" />
            </trust-anchors>
        </base-config>
    </network-security-config>
    

    OR use only android:usesCleartextTraffic="true" in app class

    This will allow http calls in your app, for more info please check, https://stackoverflow.com/a/51902630/4360419

    also documentation here,

    https://developer.android.com/about/versions/pie/android-9.0-changes-28