In the next code I can not make the toast message inside the doInBackground method jump.
When I delete this line, the writing of the "error" string into the edittext performed fine.
What am I doing wrong?
private class Verify extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
username = etusername.getText().toString();
password = etpass.getText().toString();
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("username", username));
postParameters.add(new BasicNameValuePair("password", password));
String response = null;
String result;
try {
response = CustumHttpClient.executeHttpPost(url_verify_detials, postParameters);
result = response.toString();
result = result.replaceAll("\\s+", "");
if (!result.equals("0")) {
Intent in = new Intent(MainActivity.this, danpage.class);
startActivity(in);
} else {
Toast.makeText(getApplicationContext(), "this is my Toast message!!", Toast.LENGTH_LONG)
.show();
etusername.setText("Error");
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
You can't place any code which does anything to the user interface inside the doInBackground method. If you want to show your toast you will need to return a result to onPostExecute and deal with it there.
How do you return a result to onPostExecute? In your class definition the third parameter inside the <> is the type that you will want to return in the onPostExecute method so you declaration will look like
private class Verify extends AsyncTask<Void, Void, String>
and you onPostExecute will look like
protected void onPostExecute(String result) {
Please see the reference for a good example. http://developer.android.com/reference/android/os/AsyncTask.html
You can use publishProgress and onProgressUpdate to make a Toast:
private static final int ERROR = -1;
...
try {
response = CustumHttpClient.executeHttpPost(url_verify_detials, postParameters);
result = response.toString();
result = result.replaceAll("\\s+", "");
if (!result.equals("0")) {
Intent in = new Intent(MainActivity.this, danpage.class);
startActivity(in);
} else {
//Toast.makeText(getApplicationContext(), "this is my Toast message!!", Toast.LENGTH_LONG)
// .show();
//etusername.setText("Error");
publishProgress(ERROR);
}
} catch (Exception e) {
}
...
#Override protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (values[0]==ERROR){
Toast.makeText(MainActivity.this, "this is my Toast message!!", Toast.LENGTH_LONG)
.show();
etusername.setText("Error");
}
}
You must use runOnUIThread method to execute this code.
You must execute ui methods in that thread.
Yeap ... toast has to be displayed on the UI thread. When you don't return a result from doInBackground you can return a Boolean instead and use it in onPostExecute to show your Toast. onPostExecute is executed on the UI thread. runOnUIThread is also a solution ...
Related
I have a AsyncTask<Task, Void, Boolean> thread in my Android application. And I want to show message through Toast.makeText() when this thread completes its execution. For this I have added Toask.makeText() inside if as well as inside else of doInBackground method. The thread is completing its execution succesfully but the toast's message does not appears. So what can be the problem?
Code:
#Override
protected Boolean doInBackground(Task... arg0) {
try {
Task task = arg0[0];
QueryBuilder qb = new QueryBuilder();
HttpClient httpClient = new DefaultHttpClient();
HttpPost request = new HttpPost(qb.buildContactsSaveURL());
StringEntity params =new StringEntity(qb.createTask(task));
request.addHeader("content-type", "application/json");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
if(response.getStatusLine().getStatusCode()<205)
{
/*this is the message inside if*/
Toast.makeText(context, "inside -IF", Toast.LENGTH_SHORT).show();
return true;
}
else
{
/*this is the message inside else*/
Toast.makeText(context, "inside -ELSE", Toast.LENGTH_SHORT).show();
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
Toast work in Main thread you are trying to show Toast in Background Thread (doInBackground). Move your toast code to onPostExecution callaback and you will be able to see Toasts.
The Task it is doing is in background, it won't show toast as it is in background.
Background tasks don't affect your UI or main thread.
The thread is completing its execution succesfully but the toast's
message does not appears
Because doInBackground method run on non-ui-Thread. and application only show Alert,Toast and update UI elements from UI-Thread only.
To show Toast from doInBackground wrap Toast related code inside runOnUiThread method
OR
return response from doInBackground method and use onPostExecute method to show Toast.
As mentioned by other people, you shouldn't have any UI related changes/activities on the background thread. Do it on the main thread which onPostExecute method does. Here's an example
private class DoSomethingTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
//Do background process here. Make sure there are no UI related changes here
return null;
}
protected void onPostExecute(Void x)
{
//Do UI related changes here
}
}
Using your code:
private class DoSomethingTask extends AsyncTask<Void, Void, Void> {
int statusCode;
#Override
protected Void doInBackground(Task... arg0) {
try {
Task task = arg0[0];
QueryBuilder qb = new QueryBuilder();
HttpClient httpClient = new DefaultHttpClient();
HttpPost request = new HttpPost(qb.buildContactsSaveURL());
StringEntity params =new StringEntity(qb.createTask(task));
request.addHeader("content-type", "application/json");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
statusCode = response.getStatusLine().getStatusCode();
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
protected void onPostExecute(Void x)
{
//Do UI related changes here
if(statusCode < 205)
{
/*this is the message inside if*/
Toast.makeText(context, "inside -IF", Toast.LENGTH_SHORT).show();
return true;
}
else
{
/*this is the message inside else*/
Toast.makeText(context, "inside -ELSE", Toast.LENGTH_SHORT).show();
return false;
}
}
}
Hope this helps!
I got an async task that posts JSON data, the web service i post it to sends it as an email. I have a problem now the email is being sent twice. I already disabled the button and added the progress dialog while the task is on doInBackground. I cant seem find the error why it sends twice. In my logs it only returns the success once.
Here is the code of the async task
public class postEmail extends AsyncTask<String, String, String>{
String response;
#Override
protected void onPostExecute(String s) {
pd.dismiss();
if (response.contains("success")) {
Toast.makeText(getActivity(), "Message successfully sent", Toast.LENGTH_LONG).show();
Log.d("success", "sent success");
clearEditText();
editSubject.requestFocus();
}
else {
Toast.makeText(getActivity(), "Sending Failed. Kindly check your internet connection", Toast.LENGTH_LONG).show();
}
super.onPostExecute(s);
}
#Override
protected void onPreExecute() {
pd = new ProgressDialog(getActivity(), R.style.MyTheme);
pd.setCancelable(false);
pd.setMessage("Sending...");
pd.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
pd.show();
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
jsonParser = new JSONParser();
Log.d("POST EMAIL", "SENDING");
String finalEmail = "qcqpsd.admin#stluke.com.ph";
String finalCcEmail = "nolascolee#gmail.com";
String postUrl = "http://qpsdev.stluke.com.ph/webservice/qpsSendEmail";
List<NameValuePair> post_email = new ArrayList<NameValuePair>();
post_email.add(new BasicNameValuePair("email", finalEmail));
post_email.add(new BasicNameValuePair("subject", finalSubject));
post_email.add(new BasicNameValuePair("message", finalMessage));
post_email.add(new BasicNameValuePair("sender", finalSender));
post_email.add(new BasicNameValuePair("cc", finalCcEmail));
response = jsonParser.getJSONFromPostURL(postUrl, post_email);
Log.d("result", response);
return result = jsonParser.getJSONFromPostURL(postUrl, post_email);
}
}
And here is the code for the button:
btnSend.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
getValue();
if(isConnected)
{
finalizeString();
new postEmail().execute();
}
else{
Toast.makeText(getActivity(), "Please check your connection",Toast.LENGTH_LONG).show();
}
}
});
response = jsonParser.getJSONFromPostURL(postUrl, post_email);
Log.d("result", response);
return result=jsonParser.getJSONFromPostURL(postUrl,post_email);
in here you send the file twice,change the return part and don't call method again mate
i am trying to parse a jsonObject, but i cant get the result out of doInBackground into onPostExecute
Here is my AsyncTask code:
private class GetContacts extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(MyActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
String auth2 = jsonObj.getString("auth");
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
#Override
protected void onPostExecute(Void auth2) {
super.onPostExecute(auth2);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
Toast.makeText(getApplicationContext(), "String retrived:" + auth2, Toast.LENGTH_SHORT).show();
}
}
I know its propably because i have return null there, but when i make return string then i get error.
I know in fact that jsonStr holds json data, i can see it in log:
Response:﹕ > {"user_info":{"auth":0}}
I put this code together from tutorials, thats why i dont completly understand it.
My goal is to see if auth is 0 or 1.
cant get the result out of doInBackground into onPostExecute
To return auth2 String from doInBackground :
1. Change return type of doInBackground method from Void to String:
#Override
protected String doInBackground(Void... arg0) {
}
2. Change AsyncTask last generic type from Void to String :
private class GetContacts extends AsyncTask<Void, Void, String>
3. Return auth2 from doInBackground :
String auth2 = jsonObj.getString("auth");
return auth2;
4. Change onPostExecute parameter type from Void to String :
#Override
protected void onPostExecute(String auth2) {
super.onPostExecute(auth2);
//...
Toast.makeText(getApplicationContext(),
"String retrived:" + auth2, Toast.LENGTH_SHORT).show();
}
read the documentation:
http://developer.android.com/reference/android/os/AsyncTask.html
private class GetContacts extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... arg0) {
...
return "askdjalskdj";
}
#Override
protected void onPostExecute(String auth2) {
Log.i("Output", auth2);
}
}
See the params I have set in the Generic implementation of Asynctask , see the defined return value from doInBackground and the Parameter type of onPostExecute
AsyncTask's generic types The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the
background computation.
Not all types are always used by an
asynchronous task. To mark a type as unused, simply use the type Void:
private class MyTask extends AsyncTask { ... }
I am creating an android app that depends on data that the app gets from the database. To get this data I have the following class (this class gets data from the database in JSON, translates it and returns it):
public class Json {
public String jsonResult;
private Activity activity;
private String url = "http://json.example.org/json.php";
private String db, query;
public Json(Activity activity) {
this.activity = activity;
}
public String accessWebService(String db, String query) {
JsonReadTask task = new JsonReadTask();
this.db = db;
this.query = query;
task.execute(new String[] { url });
try {
task.get();
} catch (InterruptedException e) {
Toast.makeText(activity.getApplicationContext(), "FATAL ERROR: The thread got interrupted",
Toast.LENGTH_LONG).show();
} catch (ExecutionException e) {
Toast.makeText(activity.getApplicationContext(), "FATAL ERROR: The thread wasn't able to execute",
Toast.LENGTH_LONG).show();
}
return jsonResult;
}
// Async Task to access the web
private class JsonReadTask extends AsyncTask<String, Void, String> {
private final ProgressDialog dialog = new ProgressDialog(activity);
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
// add post data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("db", db));
nameValuePairs.add(new BasicNameValuePair("query", query));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
jsonResult = inputStreamToString(response.getEntity().getContent()).toString();
if (jsonResult.isEmpty()) {
Toast.makeText(activity.getApplicationContext(),
"Error, connection is up but didn't receive data. That's strange...", Toast.LENGTH_LONG)
.show();
this.cancel(true);
}
} catch (ClientProtocolException e) {
// Toast.makeText(activity.getApplicationContext(),
// "Error, Client Protocol Exception in JSON task",
// Toast.LENGTH_LONG).show();
Log.i("Json", "Error, Client Protocol Exception in JSON task");
this.cancel(true);
} catch (IOException e) {
// Toast.makeText(activity.getApplicationContext(),
// "Error, Please check your internet connection",
// Toast.LENGTH_LONG).show();
Log.i("Json", "Error, Please check your internet connection");
this.cancel(true);
}
return null;
}
private StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
} catch (IOException e) {
Toast.makeText(activity.getApplicationContext(), "Error..." + e.toString(), Toast.LENGTH_LONG).show();
}
return answer;
}
}// end async task
}
I noticed that my app freezes while accessing the database. After some googling, I found out it was the .get() method in the accessWebService() method caused this. I tried to implement a progressDialog like so (I also deleted the .get() method):
private final ProgressDialog dialog = new ProgressDialog(activity);
protected void onPreExecute() {
super.onPreExecute();
this.dialog.setMessage("Loading...");
this.dialog.setCancelable(false);
this.dialog.show();
}
protected void onPostExecute(String result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
}
but the dialog didn't show up and I got NullPointerException because the app only works when there is data:
result = json.accessWebService(db, query);
(maybe an important thing to mention: I also use this method in for loops)
So now my question is: How can I change my app so that I get a ProgressDialog while accessing the database and without getting NullPointerException? I fear that I have to rearchitect my whole app and if I have to do this, how do I do this? I hope you guys understand my question and have a fix for this because I really need help. Thanks in advance.
P.S. Sorry if my English is not that good, I'm not a native speaker.
... I found out it was the .get() method in the accessWebService() method caused this. I tried to implement a progressDialog...
That is right. get() is a blocking call and simply adding a ProgressDialog won't fix it. You need to remove .get() and that will probably fix the issue of your ProgressDialog not showing.
An AsyncTask must be executed on the main Thread so make sure you are doing that.
Another problem you have is Toast.LENGTH_LONG).show(); runs on the UI and you have it in doInBackground() which cannot happen. You need to send the result to onPostExecute() and you can display your Toast there if need. This could also be done in onProgressUpdate().
This null pointer exception happens because of result value was null. put the condition before
if(result != null ) {
// CODE FOR PARSING
} else {
return;
}
You can start showing progress bar before asyncTask is started and finish showing when asyncTask is finished.
Pass handler to asyncTask and sendMessage onPostExecute method. Then handle message on UI thread and hide progress bar
For example there is handler field in UI (mainActivity). There you should handle hiding progress bar:
public Handler refreshChannelsHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case EPGManager.ERROR_MESSAGE:
//do some stuff
break;
case EPGManager.SUCCESS_MESSAGE:
//do some stuff
break;
}
super.handleMessage(msg);
}
};
Then you can call asyncTask with your handler
epgManager.loadChannels(refreshChannelsHandler);
AsyncTask is inside the method so it looks like this:
public void loadChannels(Handler handler) {
AsyncTask task = new AsyncTask() {
#Override
protected Object doInBackground(Object[] params) {
try {
//do AsyncTask Job
} catch (Exception e) {
return new LoadingResult((Handler) params[0], false);
}
return new LoadingResult((Handler) params[0], false);
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
LoadingResult loadingResult = ((LoadingResult)o);
sendMessageToHandler(loadingResult.handler, loadingResult.isSuccess);
}
};
task.execute(handler);
}
Here is method:
private void sendMessageToHandler(Handler handler, boolean isSuccess) {
handler.sendEmptyMessage(isSuccess ? SUCCESS_MESSAGE : ERROR_MESSAGE);
}
And finally inner class
private class LoadingResult {
private Handler handler;
private boolean isSuccess;
public LoadingResult(Handler handler, boolean isSuccess) {
this.handler = handler;
this.isSuccess = isSuccess;
}
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
Ow, and don't forget constants
public static final int SUCCESS_MESSAGE = 1;
public static final int ERROR_MESSAGE = -1;
Hope it helps :)
I am working on android applications. I need some clarification regarding asynchronous task doinbackground method.
Code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LongOperation2 op = new LongOperation2();
op.execute("");
}
public void test1() {
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("id", id));
try {
res1 = CustomHttpClient.executeHttpPost(
"http://website.com/folder1/firstpage.php",
postParameters);
System.out.println("response in test1" + res1.trim());
}
catch (Exception e) {
e.printStackTrace();
}
}
public void test2() {
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("value", value));
try {
res2 = CustomHttpClient.executeHttpPost(
"http://website.com/folder1/secondpage.php",
postParameters);
System.out.println("response in test2" + res2.trim());
}
catch (Exception e) {
e.printStackTrace();
}
}
private class LongOperation2 extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
test1();
test2();
return "Executed";
}
#Override
protected void onPostExecute(String result) {
dialog1.dismiss();
try {
Test.this.startActivity(new Intent(Page1.this, Page2.class));
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onPreExecute() {
dialog1 = ProgressDialog.show(Test.this, "Please wait...",
"Retrieving data ...", true);
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
In the above code I have two methods test1() and test2(). In both the methods I am passing parameters to webservice. Now my doubt is can I call both the methods at a time in doInBackground() of asynchronous task? Is that ok? Please let me know or give me suggestion regarding this. Thanks in advance.
There is nothing wrong in calling two or more methods. But they will be executed one after another sequentially. There is no multiprocessing inside doBackground method.