The question is simple. Actually When I try to toast message, It is not getting displayed. Could you please guide me to resolve this.
protected String doInBackground(Void... params) {
if (result.equals("200")) {
Toast.makeText(CallArduino,appliance + " Success ",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(CallArduino, "Failed", Toast.LENGTH_SHORT).show();
}
return "success";
}
Toast can't be shown in background thread you should call it within the UI thread, in onPostExecute() for example
You are trying to do a UI operation on a background thread, which is forbidden.
Any UI operation (including displaying a toast) must be done in the UI thread.
You could for instance display your toast in the onPostExecute method:
protected String doInBackground(Void... params) {
// do your background stuff
}
protected void onPostExecute (Result result) {
if (result.equals("200")) {
Toast.makeText(CallArduino,appliance + " Success ",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(CallArduino, "Failed", Toast.LENGTH_SHORT).show();
}
}
Related
I created a default login activity when creating a new project in Android.
By default creates a progressBar that works well to login and displayed correctly. All this makes it through AsyncTask.
Now I used Retrofit 2 to make way Async login.
When I pushed the button login launched a method that content:
....
....
showProgress(true);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, retrofit2.Response<User> response) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
User userdatos = response.body();
if(userdatos != null){
// redirect to Main Activity page
showProgress(false);
Intent i = new Intent(LoginActivity.this, MainActivity.class);
startActivity(i);
}
else{
showProgress(false);
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
}
#Override
public void onFailure(Call<User> call, Throwable t) {
call.cancel();
showProgress(false);
Toast.makeText(LoginActivity.this, "Please check your network connection and internet permission", Toast.LENGTH_LONG).show();
}
});
I forced a Thread.sleep (3000) to check.
No progress bar appears, and the debug shows:
Skipped 180 frames! The application May be doing too much work on ITS main thread.
How can this be solved?
I will have many Async calls where I would always display a progress bar to wait for the response is complete.
Thank you
Let me share with you mine code implementation for default Login activity created by Android Studio and my Retrofit implementation. Default login activity, consist AsyncTask which called UserLoginTask, inside it, I did all my login logic stuff. I am using .execute instead of .enqueue because it synchronous and we don't need new thread inside AsyncTask
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
private final String mEmail;
private final String mPassword;
UserLoginTask(String email, String password) {
mEmail = email;
mPassword = password;
}
#Override
protected Boolean doInBackground(Void... params) {
Retrofit restAdapter = new Retrofit.Builder()
.baseUrl(Constants.ROOT_API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
IConstructSecureAPI service = restAdapter.create(IConstructSecureAPI.class);
Call<JsonElement> result = service.getToken(mEmail, mPassword, "password");
try {
//using sync request and get response
JsonElement element = result.execute().body();
if(element!=null) {
//do whatever you want with your response
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
#Override
protected void onPostExecute(final Boolean success) {
mAuthTask = null;
showProgress(false);
if (success) {
if(clientType != 2){
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
clientType = 0;
}
else {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivityForResult(intent, 1);
}
// finish();
} else {
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
}
#Override
protected void onCancelled() {
mAuthTask = null;
showProgress(false);
}
}
Shameless Promotion
I've created RxLoading library for that, it can do this and much more,
you can just do something like this:
networkCall().compose(RxLoading.<>create(loadingLayout)).subscribe(...);
it consists out of 2 classes, a custom view (loadingLayout) and RxLoading which is a transformer that glue it all together, you can choose to work with both or either of them.
you need to be using retrofit2 with RxJava though.
RxLoading also supports empty and error states (with built-in retry mechanism, so make sure to check this options as well)
you can find out more on the GitHub page.
Hi In my Application I'm sending one request to server to validate the user,after sending the request I'm storing that value in database and making the status as 1, after some time I'm changing the status to 2 in database.Now my android app should wait till the status becomes 2. For this I'm showing the user in mobile progress bar.But my problem is as soon as I send the request progress bar stops displaying in the mobile.
Here is what I have tried.
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.show();
progressDialog.setTitle("Please Wait");
progressDialog.setMax(100);
e1 = edittext.getText().toString();
//Toast.makeText(MainActivity.this, "" + e1, Toast.LENGTH_SHORT).show();
AsyncHttpClient client = new AsyncHttpClient();
final RequestParams params = new RequestParams();
params.put("sendingJSON", composeJSON());
client.post("http://192.168.43.137/gpstracker/check_user.php", params, new AsyncHttpResponseHandler() {
public void onSuccess(String response) {
Gson gson = new GsonBuilder().create();
try {
progressDialog.dismiss();
JSONArray arr = new JSONArray(response);
for (int i = 0; i < arr.length(); i++) {
JSONObject obj = (JSONObject) arr.get(i);
String general = obj.get("success").toString();
Toast.makeText(getApplicationContext(), ""+general, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void onFailure(int statusCode, Throwable error, String content) {
if (statusCode == 404) {
Toast.makeText(getApplicationContext(), "Requested resource not found", Toast.LENGTH_LONG).show();
} else if (statusCode == 500) {
Toast.makeText(getApplicationContext(), "Something went wrong at server end", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet]",Toast.LENGTH_LONG).show();
}
}
});
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int whichButton) {
// what ever you want to do with No option.
}
}
);
alert.show();
}
A good solution in this cases is to work with events. Using events you can notify everywhere that something is happening. In your case, you can send an event when "the status changes to 2 in the database" and dismiss the progress dialog. There is a powerful and easy-to-use library to work with events called eventbus:
https://github.com/greenrobot/EventBus
I hope this helps to clarify!
I would recomend you to use an AsynkTask to do it. You can create the progress dialog in the onPreExecute() method, do what you are trying to do (post action or database update) in doInBackground() and once you have everything you want, in the onPostExecute() you can dismiss the dialog and send the result/data, if you need to, to your activity.
public class yourAsyncTask extends AsynkTask<Params, Params, Params>
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Charging...");
pDialog.setCancelable(true);
pDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
errorMesaje = "Process cancelled";
cancel(true);
}
});
pDialog.show();
}
#Override
protected Void doInBackground(Params... params) {
//Do your things here...
#Override
protected void onPostExecute(Void void) {
super.onPostExecute(void);
//Use an interface to call your activity and pass the data, you will have to change the attribute of the method in order to do it.
// Dismiss your dialog when your requests have finished
pDialog.dismiss();
}
I donĀ“t understand what are you trying to do exactly, if you just want to be sure that the post action is completed before the progress bar goes off, this solution will be fine. You can also call in the doInBackground() to your database and update it.
Hope it's clear enough!
I have a class LoginTask which is a subclass of AsyncTask. I used that to execute login functionality. Simply my LoginTask looks like this
class LoginTask extends AsyncTask<JsonObject,Void,String>{
#Override
protected void onPreExecute() {
//Codes to show progressDialog
}
#Override
protected String doInBackground(JsonObject... params) {
Ion.with(MainActivity.this)
.load("--URL TO POST JSON DATA--")
.setJsonObjectBody(params[0])
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> result) {
if (result != null) {
if (result.getHeaders().code() == 200) {
Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_SHORT).show();
} else if (result.getHeaders().code() == 401) {
Toast.makeText(MainActivity.this, "Invalid Username or password", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Something wrong check connection !!!", Toast.LENGTH_SHORT).show();
}
}
}
});
return "some message";
}
#Override
protected void onPostExecute(String string) {
super.onPostExecute(string);
if(progressDialog.isShowing()){
progressDialog.dismiss();
//TODO Something
}
}
}
What I want and What was happened :
I want to call onPostExecute Only after getting the result from FutureCallback method But when I debug the app It is directly returning the value and onPostExecute Method called Immediately before FutureCallback method.
I have written code to Execute LoginTask at Login Button pressed Event, I want to show the ProgressDialog each time when Button is pressed, But the problem is ProgressDialog is shown only at the first time, It didn't appear when I pressed the Button second time.
I want to set some message to a variable and return that to onPostExecute method so that I can handle specific tasks based on the value of String parameter, But FutureCallback is called only after executing the whole Task.
Any Kind of Suggestions will be appreciated.
Here you are calling another thread inside asynctask. So whats happening is when the new thread is getting called. Asynctask is not waiting for your ion's thread to complete and so it is going to onPostExecute.
I think you don't need a asynctask here because Ion is already making the request asyncronously. Whatever you are doing inside onPostExecute(), you can put that inside onComplete() of the ion's call.
Do like this,
[Codes to show progressDialog]
Ion.with(MainActivity.this)
.load("--URL TO POST JSON DATA--")
.setJsonObjectBody(params[0])
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>()
{
#Override
public void onCompleted(Exception e, Response<JsonObject> result) {
if(progressDialog.isShowing()){
progressDialog.dismiss();
//TODO Something
}
if (result != null) {
if (result.getHeaders().code() == 200) {
Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_SHORT).show();
} else if (result.getHeaders().code() == 401) {
Toast.makeText(MainActivity.this, "Invalid Username or password", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Something wrong check connection !!!", Toast.LENGTH_SHORT).show();
}
}
}
});
onCompleted() method you are passing in setCallback() method is a callback method that is an asynchronous call so this callback will be invoked when response is returned from server and its takes time that is why your onPostExecute method is called before futureTask.
Ion lib already uses async calls so you do not need to use AsyncTask. You just need to do following:
Ion.with(MainActivity.this)
.load("--URL TO POST JSON DATA--")
.setJsonObjectBody(params[0])
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> result) {
if (result != null) {
if (result.getHeaders().code() == 200) {
Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_SHORT).show();
} else if (result.getHeaders().code() == 401) {
Toast.makeText(MainActivity.this, "Invalid Username or password", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Something wrong check connection !!!", Toast.LENGTH_SHORT).show();
}
}
}
});
I am a newbie for android development. Recently, i faced a problem when i want to use toast and alert dialog.
Toast.makeText(getActivity(), " error", Toast.LENGTH_LONG).show();
I have tried getActivity().getApplicationContext() instead of only getActivity
both code have no syntax error but show nothing when i run
More code:
public class RegisterFragment extends Fragment {
...
.... onCreate...
.... GetData();...
..
In GetData()
inputStream = response.getEntity().getContent();
String error = convertInputStreamToString(inputStream);
JSONObject data = new JSONObject(error);
String test123 = data.getJSONObject("error").getString("code");
RegisterFragment register = new RegisterFragment();
register.makeToast(test123);
...
..
}
In makeToast function:
public void makeToast(String error){
Log.v("error",error);
Toast.makeText(getActivity(), "missing input",Toast.LENGTH_LONG).show();
}
}
The toast can only be shown on a UI Thread. Since you are making a network call the response must be running on a background thread. change your method to
public void makeToast(String error) {
Log.v("error", error);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getActivity(), "missing input", Toast.LENGTH_LONG).show();
}
});
}
Can you please try below ? Actually I have faced same issue 1 month ago, I have solved by below code:
new CountDownTimer(2000,2000) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
makeToast("Your Error Message");
}
}.start();
Hope it will help you.
RegisterFragment register = new RegisterFragment();
register.makeToast(test123);
This is your problem. You have just created an instance of RegisterFragment, but it is not attached to an Activity at this point. Therefore, the getActivity() call within makeToast() will return null.
I currently have an asyncTask which on preexecute begins a loading bar, in background send something to a server, and on post execute dismisses the dialog and enables a button. However, my post execute is not executing due to doInBackground returning null. I'm trying to figure out what I can do do get the postExecute to run. any ideas? thanks
code:
class DatabaseAsync extends AsyncTask<Void,Void,Void>{
#Override
protected void onPreExecute(){
dialog = ProgressDialog.show(MainFeedActivity.this, null, "Posting...");
}
#Override
protected Void doInBackground(Void... arg0) {
Log.d(TAG, "send to databse");
SendToDatabase();
Log.d(TAG, "sent to database - DONE");
//dialog.dismiss();
//sendButton.setEnabled(true);
return null;
}
protected void onPostExecute(){
Log.d(TAG, "p execute");
dialog.dismiss();
sendButton.setEnabled(true);
Log.d(TAG, "done executing");
}
}
It is completely Ok to return null from doInBackground() in your case. Just make sure onPostExecute() looks like this:
#Override
protected void onPostExecute(Void result) {
Log.d(TAG, "p execute");
dialog.dismiss();
sendButton.setEnabled(true);
Log.d(TAG, "done executing");
}
change your DatabaseAsync class like this:
class DatabaseAsync extends AsyncTask<String, Void, String>{
protected void onPreExecute(){
dialog = ProgressDialog.show(MainFeedActivity.this, null, "Posting...");
}
protected String doInBackground(String... arg0) {
Log.d("TAG", "send to databse");
Log.d("", "sent to database - DONE");
//dialog.dismiss();
//sendButton.setEnabled(true);
return null;
}
protected void onPostExecute(String result){
Log.d("TAG", "p execute");
dialog.dismiss();
Log.d("TAG", "done executing");
}
read this link after the code works http://www.vogella.de/articles/AndroidPerformance/article.html