Error with NetworkOnMainThread exception [duplicate] - android

This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 9 years ago.
I want to make post to the remote db from my device, but i've got NetworkOnMainThread except, how can I solve this task ? Also I need simple example how to post data to remote db.
ib_wyslij.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
sendAccelerationData(zam);
}
});
private void sendAccelerationData(Zamowienie zam)
{
//Add data to be send.
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("Zam_suma", Float.toString(zam.getSuma())));
this.sendData(nameValuePairs);
}
private void sendData(ArrayList<NameValuePair> data){
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("www.kupa.pl/1.php");
httppost.setEntity((HttpEntity) new UrlEncodedFormEntity(data));
HttpResponse response = httpclient.execute(httppost);
Log.i("postData", response.getStatusLine().toString());
//Could do something better with response.
}
catch(Exception e)
{
Log.e("log_tag", "Error: "+e.toString());
}
}

As the exception is telling you - what is wrong is you are doing network activity on the main thread. Put it into the background asynchronously. For this case an AsyncTask will work perfectly.
private void sendAccelerationData(final Zamowienie zam) {
new AsyncTask<Void,Void,Void>() {
public void doInBackground(...) {
//Add data to be send.
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("Zam_suma", Float.toString(zam.getSuma())));
MyActivityClass.this.sendData(nameValuePairs);
}
}
}

You cannot make network operations in your main UI, because that would block your program execution with a very disgusting experience for your users. For this, you have to separate network operations inside a Thread, or even better, an AsyncTask if you're just starting with the thread world.
This is the structure you would use:
final class MyNetworkOperation extends AsyncTask<URL, Integer, Void> {
#Override
protected void onPreExecute(final Void param) {
...
}
#Override
protected Void doInBackground(final URL... args) {
...
return null;
}
#Override
protected void onPostExecute(final Void param) {
...
}
}
Even the method names are very self explanatory. When you define your AsyncTask, and call .execute(url_object) on it, the first called method will be .onPreExecute(), there you may initialize variables and prepare everything for the network operation you want to do. The hard part of your network operation should be done inside doInBackground(). There you connect, do the data transfer and disconnect from the host. Finally, onPostExecute() is called: Once you're done, you can process here your results (transfer it to the main Activity, show a Dialog, etc.).
For more on AsyncTasks (and know what does those parameters mean) I strongly recommend reading the reference.
A very good example might be found here.

Add this in your onCreate()
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
ADD this to Manifest
<uses-permission android:name="android.permission.INTERNET"/>
Better use thread or asynctask for network tasks...

Related

ProgressDialog in AsyncTask onPreExecute, but it appears after doInBackground

This is part of my application. (You can run code below as an isolated application) On that website (url), using php language, parse some numbers from other website, and make an array and encode it to JSON array, and show.
But, with the code below (without dismiss function!) ProgressDialog appears after doInBackground.
When I add dismiss function to onPostExecute like below, it never appears. But When I set log for checking dialog window, it says that there was an dialog.
I heard that doInBackground freezes UI, but it freezes before dialog is shown.
Other similar questions have found solution, erasing .get() from mAsyncTask().execute().get(), but I don't have any get() in my code.
Boolean variable loadfinish is for waiting finishing asynctask, to show results from that website after asynctask. If I delete
while(loadFinish == false)
there, it automacally appears and disappears very well, but I can't show result immediately...
Add) I found that it takes several seconds to dialog appear after doInBackground... why?!
Add2) I've tried to move dialog codes before and after new mAsyncTask().execute(), but it doesn't work too...
public class MainActivity extends Activity {
boolean loadFinish;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button start = (Button) findViewById(R.id.start);
//just a button for starting asynctask
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loadFinish = false;
new mAsyncTask().execute();
// get and make json array to java array
while (loadFinish == false)
;
}
});
// add array to Custom_List_Data, and set custom row_adapter to listView.
// if I delete while(loadFinish == false), array with initial data is added.
}
private class mAsyncTask extends AsyncTask<String, String, String> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("asdf");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(String... params) {
String url = "http://songdosiyak.url.ph/MouiRate/etoos/3/main/";
String response_str = "";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
try {
response_str = client.execute(request, responseHandler);
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
loadFinish = true;
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
dialog.dismiss();
}
}
}
Sorry for my poor English language skill and thank you for reading!
As Gabe mentioned you don't need the loop, all you need is some more understanding what the async methods should do.
You introduced the result, because you want to display the result. All you have to do is to return your response_str in doInBackground. It will be then available to you as a param to onPostExecute where you can easily display it, or do whatever you need to do with it.
So to summarize:
Remove the loop
Return value response_str or whatever from doInBackground
Display value in onPostExecute
And remove loadFinish variable as its not needed at all
Hope that helps.
Because you're using an AsyncTask totally wrong. You're busy looping waiting for it to finish. NEVER do that- if you're doing that there's no point in using an AsyncTask. At any rate, the reason it won't appear is that the UI doesn't update until the UI thread returns to the event loop inside the Android Framework and runs the drawing code, which happens after onClick returns. So you won't draw until your busy loop exits, which happens after doInBackground finishes.
The solution is to remove the loop waiting for the AsyncTask to finish in your onClick. If you have logic that needs to run after it, put it in onPostExecute.
It may be worth looking into using an async library.
Using a library to help handle async callbacks can be super helpful for this as you can start the spinner, call your api, then stop the spinner in either the onSuccess function, or your success callback method in your class.
This is the one I usually use:
LoopJ's Async HTTP Callback Library
This will handle GET and POST requests with a lot of cool features such as custom timeouts, JSON format, onSuccess() and onFailure() methods, etc. There's a lot of working examples of this library too. I've used it in all my apps and haven't had any problems yet!
Hopefully this helps.

App crashes every time i make an http request

This is my code
every time i touch the imageview my app waits about 5 secs and then chrashes
I have the INTERNET permission
On the server side i have a php page that reads the GET and insert it in a database
public class Home extends Activity {
ImageView lightbut;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
ImageView lightbut = (ImageView) findViewById(R.id.light);
lightbut.setClickable(true);
lightbut.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d("== My activity ===","OnClick is called");
// Creating HTTP client
HttpClient httpClient = new DefaultHttpClient();
// Creating HTTP Post
HttpGet httpPost = new HttpGet("http://192.168.0.102/HR/index.php?command=ligthsoff");
try {
HttpResponse response = httpClient.execute(httpPost);
} catch (ClientProtocolException e) {
// writing exception to log
e.printStackTrace();
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
}
});
}
A logcat would be very helpful but its probably from doing network stuff on the UI. You should move all of your network code to a background Thread such as an AsyncTask. This will easily allow you to do the network stuff in the background then update the UI if needed in functions that run on the UI.
AsyncTask Docs
Here is an answer that shows the basic structure. Basically, you call the AsyncTask from the UI such as in your onClick() then you do network operations in doInBackground() which is called when the task first starts then you can update the UI in any of its other methods.
Using the example I referenced, you would just put all of your network stuff, which looks like everything in your onClick(), inside the doInBackground() method of the example in the link. Then in your onClick() you would do something like
lightbut.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TalkToServer task = new TalkToServer(); // could pass params to constructor here but might not be needed in this situation
task.execute(); // could pass in params for `doInBackground()` such as url, etc... but again maybe not needed for this situation
}

Run New Thread on Timer Android

I've been working on an android app which regularly checks a mysql database using JSON and everything works fine with my code.
Im having trouble running this as a timer as it only runs once and then stops.
The only code i managed to get working runs the http request on the UI thread which freezes up.
Any help would be most appreciated.
Thank in advance,
#Override
protected void onCreate(Bundle savedInstanceState) {
...
checkUpdate.start();
...
}
private Thread checkUpdate = new Thread() {
public void run() {
try {
// my code here to get web request to return json string
}
String response = httpclient.execute(httppost, responseHandler);
mHandler.post(showUpdate);
}
...
}
private Runnable showUpdate = new Runnable(){
public void run(){
try{
// my code here handles json string as i need it
Toast.makeText(MainActivity.this,"New Job Received...", Toast.LENGTH_LONG).show();
showja();
}
}
}
private void showja(){
Intent i = new Intent(this, JobAward.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
As #Raghunandan suggested, the standard way to perform work in the background on Android, and then modify the UI when that work is done, is using AsyncTask.
First define a new subclass of AsyncTask:
private class JsonRequestTask extends AsyncTask<HttpUriRequest, Void, String> {
protected String doInBackground(HttpUriRequest... requests) {
// this code assumes you only make one request at a time, but
// you can easily extend the code to make multiple requests per
// doInBackground() invocation:
HttpUriRequest request = requests[0];
// my code here to get web request to return json string
String response = httpclient.execute(request, responseHandler);
return response;
}
protected void onPostExecute(String jsonResponse) {
// my code here handles json string as i need it
Toast.makeText(MainActivity.this, "New Job Received...", Toast.LENGTH_LONG).show();
showja();
}
}
and then you would use the task like this, instead of your Thread:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
JsonRequestTask task = new JsonRequestTask();
task.execute(httppost);
...
}
You may run the task again by simply creating a new JsonRequestTask() and calling its execute() method.
A common practice for a simple async task like this is to make it a private inner class within the Activity class that uses it (if only one Activity needs it). You may need to change the scope of some of your activity's variables so that the inner class may use them (e.g. move local variables to member variables).

Android - Open URL in background

There is this website for example http://website.com You can like stuff there, with a link like this for example: http://website.com/3020/hype. You have to go to that link to get the article (3020) liked. You can only like stuff when loged in.
I have this:
HttpClient client = new DefaultHttpClient();
String getURL = "http://website.com/3020/hype/";
HttpGet get = new HttpGet(getURL);
HttpResponse responseGet = client.execute(get, cookieStuff);
Where cookieStuff is the cookie string I got from loggin in.
This works, but it takes ages. Is there another option?
Yes there is a nother option.. Internet connections and Database Connection should made in a AyncTask or Handler.. This will improve the time taken for connection (the connections will make in Background)..
here is a example for an async task:
private class YourTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... s) {
//Here you have to make the loading / parsing tasks
//Don't call any UI actions here. For example a Toast.show() this will couse Exceptions
// UI stuff you have to make in onPostExecute method
}
#Override
protected void onPreExecute() {
// This method will called during doInBackground is in process
// Here you can for example show a ProgressDialog
}
#Override
protected void onPostExecute(Long result) {
// onPostExecute is called when doInBackground finished
// Here you can for example fill your Listview with the content loaded in doInBackground method
}
}
To execute an AsyncTask:
new YourTask().execute("");

Android I can't get xml from url

I'm trying to get an xml from a url, but I have a bug in HttpResponse.
The URL is for example as follows:
http://maps.googleapis.com/maps/api/directions/xml?origin=43.364876,-5.8654205&destination=43.545686,-5.664482&sensor=true
And my code is:
public String getXML (String url){
String result = null;
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpPost = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);
} catch (Exception ex) {
Toast errorToast =
Toast.makeText(getApplicationContext(),
"Error reading xml", Toast.LENGTH_LONG);
errorToast.show();
}
return result;
}
I've already set the internet permission in the manifest.
The error is in the line:
HttpResponse httpResponse = httpClient.execute(httpPost);
and shows an error:
android.os.NetworkOnMainThreadException
Thank you
You should create a new thread as fetching the data could take a long time, thus blocking the UI thread. This is reason why you get android.os.NetworkOnMainThreadException.
Try this,
new Thread(new Runnable() {
#Override
public void run() {
// Your code here.
}
}).start();
Alternative to this solution is using AsyncTask, which is provided in android. It has doInBackground method which runs on a background thread.
Instead of calling getXML(); directly, you write this snippet in your main method:
{
...
String[] params = new String[]{url};
AsyncPostData apd = new AsyncPostData ();
apd.execute(params);
...
}
Define your Async Task like below:
private class AsyncPostData extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
getXML (params[0])
return null;
}
}
I think we have a same query here
cant get xml file from an URL in android
I'll just repost this from a different question asked earlier today:
You're trying to run a network request on the main UI thread. Android does not allow you to do that since 3.0 (I believe). Doing so causes your UI to lock up until the request is completed, rendering your app useless during the execution of the request.
You'll either have to run your request in a new Thread or an ASyncTask, to take the load of the UI thread. You can find more info on how to use multiple threads here.
Android Devices with 4+ OS versions not allows to call webservices from main activity.
your have HTTP request on activity, so you have got "android.os.NetworkOnMainThreadException"
I recommend you go for the AsyncTask solution. It is an easy and straightforward way of running requests or any other background tasks and calling web services using devices having latest OS virsion you must need to use AsyncTask.
It's also easy to implement e.g. onProgressUpdate if you need to show a progress bar of some sort while running your requests.
private class YourTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
//call your methods from here
//publish yor progress here..
publishProgress((int) ((i / (float) count) * 100));
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
//action after execution success or not
}
}

Categories

Resources