Why does this give a NetworkOnMainThreadException? - java

I'm trying to get the details of a product from a MySQL database but when I compile the code I get a NetworkOnMainThreadException error even if I use the class GetProductDetails as AsyncTask when I call it to execute . I don't really understand why this happens since I was following a tutorial to do it and I don't see any error.
This is the code that i'm using:
public class ListClubs extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clubs);
new GetProductDetails().execute();
(...some code...)
}
class GetProductDetails extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ListClubs.this);
pDialog.setMessage("Loading product details. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
* Getting product details in background thread
* */
protected String doInBackground(String... params) {
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// Check for success tag
int success;
try {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("pid", Integer.toString(1)));
// getting product details by making HTTP request
// Note that product details url will use GET request
JSONObject json = jsonParser.makeHttpRequest(url_product_detials, "GET", params);
// check your log for json response
Log.d("Single Product Details", json.toString());
// json success tag
success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// successfully received product details
JSONArray productObj = json.getJSONArray(TAG_PRODUCT); // JSON Array
// get first product object from JSON Array
JSONObject product = productObj.getJSONObject(0);
}else{
// product with pid not found
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return null;
}
protected void onPostExecute(String file_url) {
// dismiss the dialog once got all details
pDialog.dismiss();
}
}
And this is the log:
FATAL EXCEPTION: main
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
at com.goout.JSONParser.makeHttpRequest(JSONParser.java:62)
at com.goout.ListClubs$GetProductDetails$1.run(ListClubs.java:464)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5227)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
at dalvik.system.NativeStart.main(Native Method)
Thanks!

Take this stuff out of doInbackground() and see what happens
runOnUiThread(new Runnable() {
public void run() {
The point of an AsyncTask is to run network stuff or any heavy lifting in doInBackground() then use the other methods to update the UI if needed. So you don't want to do the opposite of its purpose to tell its background code(doInbackground()) to run on the UI Thread with runOnUiThread().
Also, really good information on AsyncTask Here

You are marshalling all your code at once from the AsyncTask into the main UI again, that's why right now it's as if the AsyncTask didn't exist, everything is ran from the UI Thread.
Extract your network code to run in the doInBackground method and return a meaningful (To your application) type from it, then override the onPostExecute method with the code that updates the UI with the result of doInBackground. onPostExceute is ALWAYS run from the Ui thread, you don't need to manage the threading yourself if you use it correctly.
More info: http://developer.android.com/reference/android/os/AsyncTask.html

Adding runOnUiThread in your doInBackground method is causing your background thread to queue a runnable to your main thread, so everything inside of that runnable (which includes your networking tasks) is being run on the main thread. In Android (Honeycomb+) this causes your exception to be thrown.
If you find that you have trouble with AsyncTasks, and in-particluar network requests, consider looking into a library to help simplify things - such as droidQuery and Android Volley.

Related

Should JSON be downloaded in background?

After user press the button it fires up weather function. But it doesn't log any JSON data or any error. Should it be done in background? I've used gson libary to download JSON.
Edit: I edited my code but user must enter a city which is pasted to the link. So is it possible to run in background process when the button is tapped?
public class MainActivity extends AppCompatActivity {
public class Download extends AsyncTask<String,Void,String>{
#Override
protected String doInBackground(String... strings) {
try {
URL url = new URL("api.openweathermap.org/data/2.5/weather?q="+strings[0]+"&APPID=****");
URLConnection request = url.openConnection();
request.connect();
JsonParser jp=new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject rootobj = root.getAsJsonObject();
String weather = rootobj.getAsString();
Log.i("weather:",weather);
}
catch (Exception e){
e.printStackTrace();;
}
return null;
}
}
public void weather(View view){
TextView textView=(TextView) findViewById(R.id.editText);
String city=textView.getText().toString();
Download download=new Download();
download.execute(city);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
All io operation should be executed in background , because all this operations are time consuming . which means you will block your main thread if you donot execute these codes in background and may cause Android Not Respond exception. IO operation in ui thread generally lead to bad user experience . so i strongly advice you do this in background.
You should definitely load your data in the background. The Main Thread i.e. the UI Thread is the thread that renders the UI components so no heavy operation should be done there. If heavy operation is done in the UI Thread, it will freeze the UI.
You should look at the AsyncTask class to perform your loading in the background.
Here is some good tutorials:
https://alvinalexander.com/android/asynctask-examples-parameters-callbacks-executing-canceling
https://www.journaldev.com/9708/android-asynctask-example-tutorial
https://www.tutorialspoint.com/android-asynctask-example-and-explanation

Android AsyncTask sending message to a Handler on a dead thread

I am trying to make a program that should work something like a catalog - I have a JSON array that I loop through and parse the JSON objects into a string containing the image link, and two strings for descriptions for each object. Now, when downloading the images from the internet with the link, I run into a problem at the same image every time, image number 93. I checked the link, and it's working, just the same as the others.
This happens:
W/MessageQueue: Handler (android.os.Handler) {f95f6fe} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (android.os.Handler) {f95f6fe} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:543)
at android.os.Handler.enqueueMessage(Handler.java:643)
at android.os.Handler.sendMessageAtTime(Handler.java:612)
at android.os.Handler.sendMessageDelayed(Handler.java:582)
at android.os.Handler.post(Handler.java:338)
at android.os.ResultReceiver$MyResultReceiver.send(ResultReceiver.java:57)
at com.android.internal.os.IResultReceiver$Stub.onTransact(IResultReceiver.java:58)
at android.os.Binder.execTransact(Binder.java:565)
This is how my AsyncTask looks:
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
This is how I call the AsyncTask:
new DownloadImageTask(imgProductPicture).execute(pictureLink);
layoutTest.addView(NewImgView);
In my code I make sure that no more than 5 of these are called at a time, and they all load without issue until reaching the object indexed 92. The object itself is fine, but the app shuts off at this point always. Does anyone have an idea why? I've tried downloading less images at a time (one by one) and it still fails at the same point. I'd appreciate any help.
AsyncTask uses handler of the main thread, to callback onPostExecute(). If the main thread is dead when to callback, system throws the exception. To avoid this, you have to keep the main thread alive until all the work completes.
I solved the problem by creating a new handler/runnable every time I called the DownloadImageTask. Thanks to all who have tried to help.

Populating listview with parse cloud objects on Android Studio(Using adapter)

I have some problem with my code and I just can't find a solution.
Here's my project: I have a Parse database that stores users, and these users can post status. On my parse app I have two classes, users and status. When some user upload the status, I save them and the username.
The problem is, I can't retrieve the values from 'status' on parse and show on a listview:
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Status");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> status, ParseException e) {
if(e == null) {
mStatus = status;
listview tcam = new listview();
tcam.mac(mStatus);
}else{
System.out.println("Deu ruim");
}
}
});
}
mStatus is declared like this: List<ParseObject> mStatus;
, listview is another java class, and mac is a method(and that's where the problem is). I need to pass mStatus as parameter, so I can use on this method(on listview.java):
public void mac(List<ParseObject> mStatus){
StatusAdapter adapter = new StatusAdapter(getListView().getContext(), mStatus);
setListAdapter(adapter);
}
I get an error on the following lines:
(StatusAdapter adapter = new StatusAdapter(getListView().getContext(), mStatus));
and
(tcam.mac(mStatus);)
and the application closes.
I've tested the variable mStatus and it is not empty. You may ask why I'm doing this in 2 classes, and it is because the ...getListView().getContext()... doesn't work without extending ListActivity, and I'm already extending AppCompactActivity.(This is the only solution I found)
StatusAdapter is another class, and I have extended ArrayAdapter<ParseObject>. And yes, I have a xml layout file to draw my listview...
Thanks!
That's my console error:
12-11 16:48:56.545 22535-22535/com.example.rafael.whatsnew W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x4184c7d0)
12-11 16:48:56.555 22535-22535/com.example.rafael.whatsnew E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NullPointerException
at android.app.Activity.setContentView(Activity.java:1893)
at android.app.ListActivity.ensureList(ListActivity.java:312)
at android.app.ListActivity.getListView(ListActivity.java:297)
at com.example.rafael.whatsnew.listview.mac(listview.java:21)
at com.example.rafael.whatsnew.home$4.done(home.java:204)
at com.example.rafael.whatsnew.home$4.done(home.java:198)
at com.parse.ParseTaskUtils$2$1.run(ParseTaskUtils.java:115)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5031)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
at dalvik.system.NativeStart.main(Native Method)

Android: retrieve website html - not working

I have scoured the internet, and developed code that I thought would work to get the html of a website in readable form. However, I am still unable to make this work. Here is my code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DownloadTask task = new DownloadTask();
task.execute("http://www.cnn.com");
}
private class DownloadTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... urls) {
HttpResponse response = null;
HttpGet httpGet = null;
HttpClient mHttpClient = null;
String s = "";
try {
if(mHttpClient == null){
mHttpClient = new DefaultHttpClient();
}
httpGet = new HttpGet(urls[0]);
response = mHttpClient.execute(httpGet);
s = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return s;
}
#Override
protected void onPostExecute(String result){
final TextView textview1 = (TextView) findViewById(R.id.headline);
textview1.setText(result);
}
}
}
When I try this, the app crashes on startup, with the LogCat shown below:
07-26 16:13:42.561: W/dalvikvm(23584): threadid=12: thread exiting with uncaught exception (group=0x416dfda0)
07-26 16:13:42.561: E/AndroidRuntime(23584): FATAL EXCEPTION: AsyncTask #1
07-26 16:13:42.561: E/AndroidRuntime(23584): Process: com.app.firstapp, PID: 23584
07-26 16:13:42.561: E/AndroidRuntime(23584): java.lang.RuntimeException: An error occured while executing doInBackground()
I have no idea why this is happening, does anyone know how I can modify my code to make this work? Thanks in advance.
A library that might be helpful to you is jsoup.
Link: http://jsoup.org
To get a pages HTML in jsoup you just do:
Jsoup.connect("http://google.com").get();
And then from this HTML you can use Jsoup to parse whatever data from the HTML you need.
Link: http://jsoup.org/cookbook/extracting-data/dom-navigation
Edit: I miss read the question. I thought you were having trouble with getting the HTML instead of the fact that there was a problem in the backgrounding.
Make sure that you have included
<uses-permission android:name="android.permission.INTERNET"/>
in your Manifest file.

Android httpClient

I am hitesh my problem is ,i work on httpclient in andriod i gave internet permission to my application and i run my application and click on button the tehy gave unfortunately stopped. please help me there my code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText user=(EditText) findViewById(R.id.username);
final EditText pass=(EditText) findViewById(R.id.password);
Button login=(Button) findViewhere`ById(R.id.login);
login.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
String u=user.getText().toString();
String p=pass.getText().toString();
HttpClient httpClient=new DefaultHttpClient();
HttpPost httppost=new HttpPost("http://202.164.53.122");
BasicNameValuePair usernameBaseNameValuePair=new BasicNameValuePair("id",u);
BasicNameValuePair passBaseNameValuePair=new BasicNameValuePair("pass",p);
List<NameValuePair> nameValuePairList=new ArrayList<NameValuePair>();
nameValuePairList.add(usernameBaseNameValuePair);
nameValuePairList.add(passBaseNameValuePair);
try {
UrlEncodedFormEntity urlEncodedFormEntity=new
UrlEncodedFormEntity(nameValuePairList,HTTP.UTF_8);
httppost.setEntity(urlEncodedFormEntity);
try {
HttpResponse httpResponse=httpClient.execute(httppost);
} catch (ClientProtocolException e) {
} catch (IOException e) {
user.setText(e.getMessage());
}
}catch(UnsupportedEncodingException uee){
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
dont work with network on main thread(or get android.os.NetworkOnMainThreadException). use thread class or AsyncTask class.
AsyncTask
Thread
If you are using this code in android 4.0+ you get exception android.os.NetworkOnMainThreadException. Use AsyncTask to provide any http communication.
Firstly, create a separate class for getting the Request and use Asynctask to perform all your actions. Use a String to pass the URI and then pass the URI in the Asynctask. This method won't block your Main UI Thread.
Refer to this link for how to use Asynctask.
http://developer.android.com/reference/android/os/AsyncTask.html
For network operation you should use different thread rather than using main thread because using network on main thread will cause to application UI unresponsive to avoid this you should AyncTask
For Example of AsyncTask use this Link
First of all, you should use a different thread for sending a request. Or, the best way is to use volley requests with post method. It is faster and more efficient.

Categories