Reputation: 6968
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:
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
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
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
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
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