I have an activity that makes an asynchronous connection, like this:
new Thread(new Runnable() {
public void run() {
try{
//Make Connection
}catch(Exception e){
runOnUiThread(new Runnable() { public void run() {
Dialogs.showErrorDialog(MyActivity.this); //I display an error dialog using this context
} });
}
}
}).start();
Imagine that the connection is really slow, and I leaved the activity that launched this thread. If the connection finally goes well, everything is fine, but if the connection fails, it crashes when launching the dialog, as the context does no longer exist. The error is:
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy#4068a558 is not valid; is your activity running?
How to avoid this error? I would like to detect if my activity is still alive to either
1) show a dialog with this context (if I'm still on the screen)
2) show a Toast with ApplicationContext (if I'm outside the screen)
EDITED:
The dialog code is this:
static public void showErrorDialog(Context context){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setTitle(R.string.error_title);
builder.setMessage(R.string.error_content);
builder.setPositiveButton(R.string.button_ok,null);
builder.show();
}
How to avoid this error?
I suggest you to use this:
runOnUiThread(new Runnable() {
public void run() {
if (!(((Activity) context).isFinishing())) { // you need to pass Context.
Dialogs.showErrorDialog(context);
}
}
});
Let me know if it works.
Note: If it won't works, i recommend to you use AsyncTask instead of runOnUiThread().
can't change UI in thread; you use RunOnUiThread, but the UiThread still in the thread.
You can use AsyncTask to do it.
class ConnectionTask extends AsyncTask<Void, Void, Boolean> {
protected Boolean doInBackground(Void... params) {
//Make Connection
boolean flag = connecting(); //flag is connect state: success or fail
return flag;
}
protected void onPostExecute(Boolean result) {
if (!result) {
Dialogs.showErrorDialog(MyActivity.this);
}
}
}
then, use as follows:
ConnectionTask task = new ConnectionTask();
task.execute();
Related
I am working on a program that searches the users phone for some date, which takes about 2-3 seconds. While it's computing I want to display a loading screen, so the user knows something indeed is happening. However, when I try to display a loading screen before the computations, nothing is displayed on the screen.
This is what I have:
ProgressDialog loading= new ProgressDialog(this);
loading.setTitle("Loading");
loading.setMessage("Please wait...");
loading.show();
//search stuff
loading.dismiss();
In addition to this, I have tried putting the ProgressDialog in a thread like the following,
new Thread(new Runnable(){
public void run(){
ProgressDialog loading= new ProgressDialog(this);//error here for "this"
loading.setTitle("Loading");
loading.setMessage("Please wait...");
loading.show();
}
});
//search stuff
but it fails due to the "this" keyword, I believe because its referring to an Activity and not a regular class, but I could be wrong...
How can I get the ProgressDialog to display properly?
Try to handle it in this way
mProgressDialog = ProgressDialog.show(this, "Please wait","Long operation starts...", true);
new Thread() {
#Override
public void run() {
//Do long operation stuff here search stuff
try {
// code runs in a thread
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressDialog.dismiss();
}
});
} catch (final Exception ex) {
}
}
}.start();
Use async task for heavy task. Put your progress dialog code in onPreExecute method progress dialog dismiss code in onPostExecute method and all your heavy task in doInBackground method.
try passing down the context on a new class with your progress bar (this goes on your main activity)
NAME_OF_YOUR_CLASS context = new NAME_OF_YOUR_CLASS(getApplicationContext());
and on your class call the method like this..(this goes on class)
public Networking(Context c) {
this.context= c;
}
dont forget to make context a field (private final Context context;)
hope this helps
also idk if this will work but try to extend AsyncTask and use methods to run your progress bar there.
I am trying to cancel a log run AsyncTask if a certain period of time exceeds (if AsyncTask is not automatically finised)
Below is the code where I setup my task to start with timeout
final ProfileDesc pdsc = new ProfileDesc();
pdsc.execute();
Thread th_pdsc = new Thread(){
public void run()
{
try{
pdsc.get(120000, TimeUnit.MILLISECONDS);
}
catch(Exception e){
pdsc.cancel(true);
((Activity)context).runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Download Time out. Please Try again later.", Toast.LENGTH_LONG).show();
}
});
}
}
};
th_pdsc.start();
below is the code for my AsynTask
private class ProfileDesc extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
dialogue = new ProgressDialog(MainActivity.this);
dialogue.setTitle("Processing");
dialogue.setMessage("Getting Header Information");
dialogue.setIndeterminate(true);
dialogue.setCancelable(false);
dialogue.show();
}
protected void onPostExecute(Void params) {
super.onPostExecute(params);
dialogue.dismiss();
}
protected Void doInBackground(Void... arg0) {
//long run work
return null;
}
}
After two minutes it's still running. How can I set up the time out? Note: I have followed this link of Stack Overflow for this code.
What you had
ProfileDesc pdsc = new ProfileDesc();
pdsc.execute();
was enough. There is no need for a Thread. doInBackground is invoked on the background thread. So you can do you Network operations in doInbackgorund.
Secondly calling get makes AsyncTask no more Asynchronous as it blocks the ui thread
get(long timeout, TimeUnit unit) Waits if necessary for at most the
given time for the computation to complete, and then retrieves its
result
I guess you have misunderstood the use of Asynctask. Read the docs
http://developer.android.com/reference/android/os/AsyncTask.html
You may want to check this
Stop AsyncTask doInBackground method
Here new thread is not needed.Just remove "dialogue.setIndeterminate(true)". It means the "loading amount" is not measured.I think it's creating the problem.
Is there a (thread safe) method I can call from Java on Android which
will give me a handle to the foreground activity from a background task?
I would like to be able to do so in order to safely post toasts on top
of the top window.
Thanks.
You wouldn't necessarily have to get a handle to the foreground UI activity to show a toast message. You can do this from a background thread like this:
runOnUiThread(new Runnable() {
public void run() {
// make toast, show toast
}
});
Create your own class that extends AsyncTask and pass the Activity as one of the parameters:
public class MyAsyncTask extends AsyncTask<String, String, String>{
Activity mActivity;
public MyAsyncTask (Activity mActivity){
this.mActivity = mActivity;
}
#Override
protected String doInBackground(String... urls) {
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
Doing that should allow you to access the Activity (assuming it's still the foreground throughout; which may not necessarily be the case).
If there's a chance that it's not the foreground Activity, you may want to just use the:
runOnUiThread(new Runnable() {
public void run() {
// Do UI stuff here
}
});
However, that isn't necessarily thread-safe
I'm new to Android development. I've be working on Swing and SWT for several years. Both Swing and SWT has a stratage to execute code in UI thread sync and async. The typical usage is doing some time-consume staff in one thread then display the result in UI thread async.
So my question is, is there similiar stratage in Android? Here is my code. Parameter runnable is some time-consume code. This method will display a waiting dialog during the execution then EXPECT to show a Toast after it is finished. But the Toast need to be show in UI thread. So how to do that?
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
// TODO: How to display a Toast message here? execute some code in UI Thread.
}
});
}
And is there some words about Android UI system? Such as is it Thread-Safe, how thread works together and so on. Many Thanks!
There are several ways for doing that,
AsyncTask -
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers. Example for using AsyncTask
Service -
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use. Example for Using Service.
IntentService -
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work. Example for using IntentService.
You can use AsyncTask like this.
To call AsyncTask
new getAsynctask().execute("");
and here is the class for geting result.
class getAsynctask extends AsyncTask<String, Long, Integer> {
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(Pass.this, null, "Please wait...");
}
protected Integer doInBackground(String... params) {
try {
// do your coding
return null;
} catch (Exception e) {
return null;
}
}
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
try {
if (loading != null && loading.isShowing())
loading.dismiss();
} catch (Throwable t) {
Log.v("this is praki", "loading.dismiss() problem", t);
}
}
}
Whenever you are working with Separate thread which is not your UI thread the best way is to use Handler. Whenever you want to intimate user from your Thread, suppose a progress then send a message to Handler to so. Inside Handler you can handle message and write a code snippet to Change anything on UI. This is the preferred way for Android. see these link1 , link2 & link3
You use this AsynTask as a inner class of your activity. In do in background do the time consuming task you want to do and then in on postexecute you can show the text message.
call this from your main activity
initTask = new InitTask();
initTask.execute(this);
protected class InitTask extends AsyncTask<Context, Integer, String> {
#Override
protected String doInBackground(Context... params) {
// Do the time comsuming task here
return "COMPLETE!";
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this
// method
#Override
protected void onProgressUpdate(Integer... values) {
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled() {
super.onCancelled();
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Show the toast message here
}
}
Use a handler:
static final int SHOW_TOAST = 0;
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
handler.sendMessage(handler.obtainMessage(SHOW_TOAST));
}
});
}
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_TOAST:
//Toast here
break;
}
}
};
The Painless threading article from the android developer resources provides different alternatives depending on the specific SDK version.
Tips or ideas on how ProgressDialog can communicate with asyncTask.
For example when I click the button, the program will validate the input to internet, This is should not be interupted. so I use ProgressDialog.
After progressDialog.dismiss(), I need to refresh the view by calling the asyncTask.
I have tried some ways but it's failed, for example
* I execute asynTask after progressdialog.dismiss().
* put execution asynctask inside dialogbox after progressdialog thread.
in other word, is there any way to tell asynctask that progressdialog has been dismissed. Or is there communication such as message between threads ?
here is the example of my code:
btnPost.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
stockProgressDialog = ProgressDialog.show(PostActivity.this,
"Please wait...", "Check the post");
new Thread() {
public void run() {
try{
/* Connect to Internet API */
stockProgressDialog.dismiss();
} catch (Exception e) { }
// Dismiss the Dialog
}
}.start();
new LookUpTask().execute();
}
});
Yes, there is a way to tell asyncTask that progressDialog has been dismissed. you can use one onDismissListener
#Override
public Dialog onCreateDialog(int id){
if(id==DIALOG_PROGRESS_DIALOG){
stockProgressDialog = new ProgressDialog(Main.this);
stockProgressDialog.setTitle("Please wait...");
stockProgressDialog.setMessage("Check the post");
stockProgressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
textView.setText("Waiting the 5 secs...");
myAsyncTask.execute("start it");
//Or myAsyncTask.cancel(true); if you want to interrupt your asyncTask
}
});
return stockProgressDialog;
} else return super.onCreateDialog(id);
}
You can cancel an AsyncTask by calling AsyncTask.cancel(..) and then start up a new AsyncTask. You are not supposed to run the AsyncTask as a parallel activity - it is supposed to be able to run and finish without outside intervention.
Extend async and look into returning a result from doInBackground. onProgress update can dismiss your Progress dialog under control of the async task. Handle the result from doInBackground in onPostExecute.
//create the task
theBackground = new Background();
theBackground.execute("");
--------
private class Background extends AsyncTask<String, String, String>{
protected String doInBackground(String...str ) {
publishProgress("##0");
//do a bunch of stuff
publishProgress(#001);
return("true");
}
protected void onProgressUpdate(String... str ) {
//do stuff based on the progress string and eventually
myProgressDialog.dismiss();
}
protected void onPostExecute(String result) {
}
}
I'm not sure why you're using a thread in one case, but an AsyncTask in another when you could just use two AsyncTasks... Actually, unless I'm missing something, in your case the most straightforward way is to combine the two bits of work into one AsyncTask and simply create and destroy the dialog in the AsyncTask callbacks. In pseudo-code:
onPreExecute
show dialog
doInBackground
do internet stuff
onPostExecute
update views
close dialog
Is there a reason why you're trying to update the views in its own AsyncTask? If you're updating views, you probably need to do the work in the UI thread anyway...