Reputation: 203
Basically I'm getting a strange issue with my Android application, it's supposed to grab a JSON Array and print out some values, the class looks like this:
ShowComedianActivity.class
package com.example.connecttest;
public class ShowComedianActivity extends Activity{
TextView name;
TextView add;
TextView email;
TextView tel;
String id;
// Progress Dialog
private ProgressDialog pDialog;
//JSON Parser class
JSONParser jsonParser = new JSONParser();
// Single Comedian url
private static final String url_comedian_details = "http://86.9.71.17/connect/get_comedian_details.php";
// JSON Node names
private static final String TAG_SUCCESS = "success";
private static final String TAG_COMEDIAN = "comedian";
private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";
private static final String TAG_ADDRESS = "address";
private static final String TAG_EMAIL = "email";
private static final String TAG_TEL = "tel";
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.show_comedian);
// Getting Comedian Details from intent
Intent i = getIntent();
// Getting id from intent
id = i.getStringExtra(TAG_ID);
new GetComedianDetails().execute();
}
class GetComedianDetails extends AsyncTask<String, String, String>{
protected void onPreExecute(){
super.onPreExecute();
pDialog = new ProgressDialog(ShowComedianActivity.this);
pDialog.setMessage("Fetching Comedian details. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
@Override
protected String doInBackground(String... params) {
runOnUiThread(new Runnable(){
public void run(){
int success;
try{
//Building parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id",id));
// Getting comedian details via HTTP request
// Uses a GET request
JSONObject json = jsonParser.makeHttpRequest(url_comedian_details, "GET", params);
// Check Log for json response
Log.d("Single Comedian details", json.toString());
//JSON Success tag
success = json.getInt(TAG_SUCCESS);
if(success == 1){
// Succesfully received product details
JSONArray comedianObj = json.getJSONArray(TAG_COMEDIAN); //JSON Array
// get first comedian object from JSON Array
JSONObject comedian = comedianObj.getJSONObject(0);
// comedian with id found
name = (TextView) findViewById(R.id.name);
add = (TextView) findViewById(R.id.add);
email = (TextView) findViewById(R.id.email);
tel = (TextView) findViewById(R.id.tel);
// Set text to details
name.setText(comedian.getString(TAG_NAME));
add.setText(comedian.getString(TAG_ADDRESS));
email.setText(comedian.getString(TAG_EMAIL));
tel.setText(comedian.getString(TAG_TEL));
}
} catch (JSONException e){
e.printStackTrace();
}
}
});
return null;
}
}
}
And my JSON Parser class looks like:
package com.example.connecttest;
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
// function get json from url
// by making HTTP POST or GET method
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
// Making HTTP request
try {
// check for request method
if(method == "POST"){
// request method is POST
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}else if(method == "GET"){
// request method is GET
DefaultHttpClient httpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
Now when I run a debug it's querying the correct address with ?id=1 on the end of the URL, and when I navigate to that url I get the following JSON Array:
{"success":1,"comedian":[{"id":"1","name":"Michael Coombes","address":"5 Trevethenick Road","email":"[email protected]","tel":"xxxxxxxxxxxx"}]}
However my app just crashes, the log-cat report looks like this:
03-22 02:05:02.140: E/Trace(3776): error opening trace file: No such file or directory (2)
03-22 02:05:04.590: E/AndroidRuntime(3776): FATAL EXCEPTION: main
03-22 02:05:04.590: E/AndroidRuntime(3776): android.os.NetworkOnMainThreadException
03-22 02:05:04.590: E/AndroidRuntime(3776): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
03-22 02:05:04.590: E/AndroidRuntime(3776): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
03-22 02:05:04.590: E/AndroidRuntime(3776): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
03-22 02:05:04.590: E/AndroidRuntime(3776): at libcore.io.IoBridge.connect(IoBridge.java:112)
03-22 02:05:04.590: E/AndroidRuntime(3776): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
03-22 02:05:04.590: E/AndroidRuntime(3776): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
03-22 02:05:04.590: E/AndroidRuntime(3776): at java.net.Socket.connect(Socket.java:842)
03-22 02:05:04.590: E/AndroidRuntime(3776): at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
03-22 02:05:04.590: E/AndroidRuntime(3776): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:144)
03-22 02:05:04.590: E/AndroidRuntime(3776): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
03-22 02:05:04.590: E/AndroidRuntime(3776): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
03-22 02:05:04.590: E/AndroidRuntime(3776): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
03-22 02:05:04.590: E/AndroidRuntime(3776): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
03-22 02:05:04.590: E/AndroidRuntime(3776): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
03-22 02:05:04.590: E/AndroidRuntime(3776): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
03-22 02:05:04.590: E/AndroidRuntime(3776): at com.example.connecttest.JSONParser.makeHttpRequest(JSONParser.java:62)
03-22 02:05:04.590: E/AndroidRuntime(3776): at com.example.connecttest.ShowComedianActivity$GetComedianDetails$1.run(ShowComedianActivity.java:89)
03-22 02:05:04.590: E/AndroidRuntime(3776): at android.os.Handler.handleCallback(Handler.java:615)
03-22 02:05:04.590: E/AndroidRuntime(3776): at android.os.Handler.dispatchMessage(Handler.java:92)
03-22 02:05:04.590: E/AndroidRuntime(3776): at android.os.Looper.loop(Looper.java:137)
03-22 02:05:04.590: E/AndroidRuntime(3776): at android.app.ActivityThread.main(ActivityThread.java:4745)
03-22 02:05:04.590: E/AndroidRuntime(3776): at java.lang.reflect.Method.invokeNative(Native Method)
03-22 02:05:04.590: E/AndroidRuntime(3776): at java.lang.reflect.Method.invoke(Method.java:511)
03-22 02:05:04.590: E/AndroidRuntime(3776): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
03-22 02:05:04.590: E/AndroidRuntime(3776): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
03-22 02:05:04.590: E/AndroidRuntime(3776): at dalvik.system.NativeStart.main(Native Method)
From this I'm guessing the error is in the jsonParser.makeHttpRequest however I can't for the life of me figure out what's going wrong and was hoping someone brighter than I could illuminate me.
Upvotes: 0
Views: 525
Reputation: 13269
First, remember to actually read the stack trace, the answer is in the first line. When running your App in strict mode (I think the newer versions of Android do by default), Android will throw NetworkOnMainThreadException
if you try to do any network calls on the UI thread, because you DO NOT want to block the UI thread.
E/AndroidRuntime(3776): android.os.NetworkOnMainThreadException
E/AndroidRuntime(3776): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
Looking down the trace here's you code that is causing the issue:
E/AndroidRuntime(3776): at com.example.connecttest.JSONParser.makeHttpRequest(JSONParser.java:62)
E/AndroidRuntime(3776): at com.example.connecttest.ShowComedianActivity$GetComedianDetails$1.run(ShowComedianActivity.java:89)
Here's the actual line:
JSONObject json = jsonParser.makeHttpRequest(url_comedian_details, "GET", params);
Upon inspection, you are actually running your network call in doInBackground
, which runs off the main thread, which is where you want to do network calls (since you can block that thread all you want). However, you are running your network call inside runOnUiThread
, so you are then turning back around and running your network call on the UI thread, and then Android throws NetworkOnMainThreadException
.
I suggest you remove the runOnUiThread
piece, as that is a bad practice, and pass in your request parameters to your AsyncTask
.
More info on the error - How to fix android.os.NetworkOnMainThreadException?.
Upvotes: 1
Reputation: 18863
You are getting android.os.NetworkOnMainThreadException because you are "attempts to perform a networking operation on its main thread." AsyncTask is a Thread ,so remove:
runOnUiThread(new Runnable(){
public void run(){
and the closing brackets.
Upvotes: 2