TomSelleck
TomSelleck

Reputation: 6968

Retrieve JSON Object Android

I'm trying to get a JSON String from a URL but I keep getting a "NetworkOnMainThreadException". I thought I moved my network code to another thread but obviously not.

Here is the error:error

JSONParser

package com.example.jsonparsing;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class JSONParser {

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";

    // constructor
    public JSONParser() {

    }

    public String getJSONFromUrl(String url) {

        DefaultHttpClient   httpclient = new DefaultHttpClient(new BasicHttpParams());
        HttpPost httppost = new HttpPost("http://api.androidhive.info/contacts/");
        // Depends on your web service
        httppost.setHeader("Content-type", "application/json");

        InputStream inputStream = null;
        String result = null;
        HttpResponse response = null;
        try {
            response = httpclient.execute(httppost);
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }           
        HttpEntity entity = response.getEntity();

        try {
            inputStream = entity.getContent();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // json is UTF-8 by default i beleive
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null)
            {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result = sb.toString();
    }
}

Main Activity

package com.example.jsonparsing;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class MainActivity extends Activity{

    // url to make request
    private static String url = "http://api.androidhive.info/contacts/";

    // contacts JSONArray
    JSONArray contacts = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Hashmap for ListView
        ArrayList<HashMap<String, String>> contactList = new ArrayList<HashMap<String, String>>();

        RetrieveJSONString retrieveJSON = new RetrieveJSONString();
        retrieveJSON.run();
        String whatever = retrieveJSON.getJSONString();
    }
}

class RetrieveJSONString implements Runnable{

    JSONParser jParser;
    String jsonString;

    public void run() {
         // Creating JSON Parser instance
        JSONParser jParser = new JSONParser();

        // getting JSON string from URL
        String jsonString = jParser.getJSONFromUrl("http://api.androidhive.info/contacts/");

    }

    public String getJSONString(){

        return jsonString;
    }

}

Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.jsonparsing"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="15" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

If anybody can shed some light on the problem I would appreciate it!

Upvotes: 1

Views: 3347

Answers (4)

Sanjeev Badoni
Sanjeev Badoni

Reputation: 95

Call getJSONFromUrl method inside AscyTask .this exception occur when process take long time. Call this AscyTask task by using this line

new AppTask().execute();

public class AppTask extends AsyncTask<String, String, Void> {
   protected void onProgressUpdate(String... progress){}  protected void onPreExecute(){ }

   protected Void doInBackground(final String... args) {
       getJSONFromUrl();
       return null;
   }

   protected void onPostExecute(final Void unused) { }
}

Upvotes: 0

DecodeGnome
DecodeGnome

Reputation: 1809

You are getting that error because you are trying to do HTTP calls on the UI-thread, and you should never do that :) Use an AsyncTask instead. Here is a simple example:

GetJsonAsync getJson = new GetJsonAsync();
getJson.execute();

private class GetJsonAsync extends AsyncTask <String, Void, String> {

        @Override
        protected void onPreExecute() {
            // Do stuff before the operation
        }

        @Override
        protected String doInBackground(String... params){
            getJSONFromUrl();
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            // Do stuff after the operation
        }
    }

Upvotes: 4

Ron
Ron

Reputation: 24235

You should call start() on a Thread and not call the run method directly. You are calling the retrieveJSON.run(); which will be run on the UI thread.

 new Thread(new RetrieveJSONString()).start();

I suggest using a AsyncTask for this purpose instead of a Thread, as you want to update the UI after fetching JSON. In AsyncTask, when the background job is done the onPOstExecute() method gets called, where you can update the UI.

Upvotes: 3

PearsonArtPhoto
PearsonArtPhoto

Reputation: 39718

From the Android SDK docs

The exception that is thrown when an application attempts to perform a networking operation on its main thread.

This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness.

Essentially, you want to do some sort of a threaded application, or else the GUI can get stuck. Look into AsyncTask or just threading for your JSON parsing needs.

Upvotes: 3

Related Questions