Saturday, 28 April 2012

android.os.NetworkOnMainThreadException

Refer to my old exercise "Read Text file from internet, using Java code": it a simple exercise to read something from internet. It can be download here in project form.

It work as expected, to display the text file from internet, for android:minSdkVersion="9" or older. But fail with android:minSdkVersion="10" or higher. It's a strange and interesting issue for me.

OK for android:minSdkVersion='9' or older



Fail for android:minSdkVersion='10' or higher


After investigated into the logcat, I found that it's Caused by: android.os.NetworkOnMainThreadException!

android.os.NetworkOnMainThreadException is a 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 (actually it fail in my exercise with API level 10). Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged.

The solution is to move the internet accessing code to a background thread, AsyncTask in my exercise.

package com.exercise.AndroidInternetTxt;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidInternetTxt extends Activity {

TextView textMsg, textPrompt;
final String textSource = "http://sites.google.com/site/androidersite/text.txt";


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textPrompt = (TextView)findViewById(R.id.textprompt);
textMsg = (TextView)findViewById(R.id.textmsg);

textPrompt.setText("Wait...");

new MyTask().execute();

/*
URL textUrl;

try {
textUrl = new URL(textSource);

BufferedReader bufferReader
= new BufferedReader(new InputStreamReader(textUrl.openStream()));

String StringBuffer;
String stringText = "";
while ((StringBuffer = bufferReader.readLine()) != null) {
stringText += StringBuffer;
}
bufferReader.close();

textMsg.setText(stringText);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
textMsg.setText(e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
textMsg.setText(e.toString());
}

textPrompt.setText("Finished!");
*/
}

private class MyTask extends AsyncTask<Void, Void, Void>{

String textResult;

@Override
protected Void doInBackground(Void... params) {

URL textUrl;

try {
textUrl = new URL(textSource);

BufferedReader bufferReader
= new BufferedReader(new InputStreamReader(textUrl.openStream()));

String StringBuffer;
String stringText = "";
while ((StringBuffer = bufferReader.readLine()) != null) {
stringText += StringBuffer;
}
bufferReader.close();

textResult = stringText;
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
textResult = e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
textResult = e.toString();
}

return null;

}

@Override
protected void onPostExecute(Void result) {

textMsg.setText(textResult);
textPrompt.setText("Finished!");

super.onPostExecute(result);
}

}
}


Download the files.

Another un-recommended approach: StrictMode.setThreadPolicy and StrictMode.ThreadPolicy.Builder

No comments:

Post a Comment