I want to set timeout for Dialog (progress dialog) in android , to make the dialog disappears after a period of time (if there is No response for some action !)
The same approach as in this post is verified to work (with long instead of float):
public void timerDelayRemoveDialog(long time, final Dialog d){
new Handler().postDelayed(new Runnable() {
public void run() {
d.dismiss();
}
}, time);
}
You could always make a class called ProgressDialogWithTimeout and override the functionality of the show method to return a ProgressDialog and set a timer to do what you wish when that timer goes off. Example:
private static Timer mTimer = new Timer();
private static ProgressDialog dialog;
public ProgressDialogWithTimeout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public ProgressDialogWithTimeout(Context context, int theme) {
super(context, theme);
// TODO Auto-generated constructor stub
}
public static ProgressDialog show (Context context, CharSequence title, CharSequence message)
{
MyTask task = new MyTask();
// Run task after 10 seconds
mTimer.schedule(task, 0, 10000);
dialog = ProgressDialog.show(context, title, message);
return dialog;
}
static class MyTask extends TimerTask {
public void run() {
// Do what you wish here with the dialog
if (dialog != null)
{
dialog.cancel();
}
}
}
Then you would call this in your code as so:
ProgressDialog progressDialog = ProgressDialogWithTimeout.show(this, "", "Loading...");
Related
I am currently implementing my own custom progress dialog, where I call show and hide once a result comes in/error occurs. However, I want to implement a custom method that says if the progress dialog has not hidden after 10 seconds no matter what, hide it and put up an alert.
This is my custom progress dialog with my method that works but not entirely.
public class CustomProgressDialog extends ProgressDialog {
private AnimationDrawable animation;
private CountDownTimer cTimer = null;
private Context mContext;
public CustomProgressDialog(Context context) {
super(context);
mContext = context;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_progress_dialog);
ImageView la = (ImageView) findViewById(R.id.animation);
la.setBackgroundResource(R.drawable.custom_progress_dialog_animation);
animation = (AnimationDrawable) la.getBackground();
}
#Override
public void show() {
super.show();
animation.start();
startTimer();
}
#Override
public void dismiss() {
super.dismiss();
animation.stop();
if(cTimer != null) {
cTimer.cancel();
}
}
//timer added just in case progress dialog does not stop on its own
private void startTimer() {
cTimer = new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
dismiss();
AlertDialogManager alert = new AlertDialogManager();
alert.showAlertDialog(mContext, mContext.getString(R.string.loadingErr), mContext.getString(R.string.loadingErrTxt), 3);
}
}.start();
}
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
animation.stop();
cTimer.cancel();
}
}
This is how I implement it in the activity/fragment:
private void showProgressDialog() {
customProgressDialog = new CustomProgressDialog(this);
customProgressDialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
customProgressDialog.show();
//so it cannot be closed by user first one lets back button cancel it
//customProgressDialog.setCanceledOnTouchOutside(false);
customProgressDialog.setCancelable(false);
}
private void hideProgressDialog() {
if(customProgressDialog != null) {
//customProgressDialog.hide();
}
}
UPDATE: This is a second option I tried it still does not stop the alert from popping up which makes me think the timer is still going even on cancel.
This is the activity:
private void autoProgressShutdown() {
Runnable progressRunnable = new Runnable() {
#Override
public void run() {
customProgressDialog.cancel();
callAlert();
}
};
Handler pdCanceller = new Handler();
pdCanceller.postDelayed(progressRunnable, 10000);
}
private void callAlert() {
AlertDialogManager alert = new AlertDialogManager();
alert.showAlertDialog(this, getString(R.string.loadingErr), getString(R.string.loadingErrTxt), 3);
}
private void showProgressDialog() {
customProgressDialog = new CustomProgressDialog(this);
customProgressDialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
customProgressDialog.show();
//so it cannot be closed by user first one lets back button cancel it
//customProgressDialog.setCanceledOnTouchOutside(false);
customProgressDialog.setCancelable(false);
autoProgressShutdown();
}
private void hideProgressDialog() {
customProgressDialog.cancel();
if(customProgressDialog != null) {
customProgressDialog.hide();
}
}
In the custom dialog edited the file to remove all the timer stuff and added this:
#Override
public void setOnCancelListener(OnCancelListener listener) {
super.setOnCancelListener(listener);
dismiss();
}
Possible Issues:
-not sure if memory leak issues since I am not destroying it
Definite Issues:
-if the Progress dialog is hidden the alert still pops up after 10 seconds which means either cancel did not get called
-Also, if I switch screens not sure if the cancel is enough to destroy the timer
You can use Handler#postDelayed to make something happen later on a given thread, and you can use Handler#removeCallbacksAndMessages to cancel pending tasks. If you call it with null, it just cancels anything pending on the handler if you've got some stuff that you need to prevent in the posted task.
Here's your dialog, but properly self-terminating:
class SuicideDialog extends Dialog{
private Handler mAutoTerminationHandler;
#Override
public void onShow(){
mAutoTerminationHandler = new Handler();
}
#Override
public void show(){
super.show();
mAutoTerminationHandler.postDelayed(new Runnable(){
dismiss();
}, 666L);
}
#Override
public void dismiss(){
mAutoTerminationHandler.removeCallbacksAndMessages(null);
super.dismiss();
}
}
Or, you can put the lifecycle listening into its own class:
class ShownTaskListener implements OnShowListener, OnDismissListener {
private Handler mHandler;
#Override
public ShownTaskListener(Handler handler, Runnable showTask){
mHandler = handler;
mShowTask = showTask;
}
// from OnShowListener
#Override
public void onShow(){
mHandler.postDelayed(mShowTask, 666L);
}
// from OnDismissListener
#Override
public void onDismiss(){
// get rid of all pending actions in the Handler
mHandler.removeCallbacksAndMessages(null);
}
}
And then, you can use it to self-dismiss any Dialog by attaching this listener with Dialog#setOnShowListener and Dialog#setOnDismissListener.
I would like to create a dialog with a progress bar inside.
But I see the Toas message, but I don't see the dialog and tre progress bar ..why?
thx a lot for evryone.
//prepare for a progress bar dialog
progressBar = new ProgressDialog(this);
progressBar.setCancelable(true);
progressBar.setMessage("Creazione Database\nIngredienti...");
progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressBar.setProgress(0);
progressBar.show();
new BackgroundAsyncTask(appContext, progressBar).execute();
...
...
...
and i have created a generic class:
public class BackgroundAsyncTask extends AsyncTask<Void, Integer, Void> {
int myProgressCount;
Context context;
ProgressDialog progressBar;
public BackgroundAsyncTask(Context appContext, ProgressDialog progressBar) {
// TODO Auto-generated constructor stub
this.context = appContext;
this.progressBar = progressBar;
}
#Override
protected void onPreExecute() {
Toast.makeText(context, "onPreExecute Start Progress Bar", Toast.LENGTH_LONG).show();
progressBar.setProgress(0);
myProgressCount = 0;
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
while (myProgressCount < 100) {
myProgressCount++;
/**
* Runs on the UI thread after publishProgress(Progress...) is
* invoked. The specified values are the values passed to
* publishProgress(Progress...).
*
* Parameters values The values indicating progress.
*/
publishProgress(myProgressCount);
SystemClock.sleep(100);
}
return null;
}
/**
* This method can be invoked from doInBackground(Params...) to publish
* updates on the UI thread while the background computation is still
* running. Each call to this method will trigger the execution of
* onProgressUpdate(Progress...) on the UI thread.
*
* onProgressUpdate(Progress...) will not be called if the task has been
* canceled.
*
* Parameters values The progress values to update the UI with.
*/
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Void result) {
Toast.makeText(context, "onPostExecute End Progress Bar",Toast.LENGTH_LONG).show();
progressBar.dismiss();
}
}
The progress range is 0..10000. - as the docs says. Use numbers that fit that range.
I highly recommend use dialog fragment instead dialog
public class ProgressDialogFragment extends DialogFragment {
public static LoadingDialogFragment newInstance() {
ProgressDialogFragment frag = new ProgressDialogFragment ();
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final ProgressDialog dialog = new ProgressDialog(getActivity());
dialog.setMessage(getString(R.string.loading_text));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
// Disable the back button
OnKeyListener keyListener = new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode,
KeyEvent event) {
if( keyCode == KeyEvent.KEYCODE_BACK){
return true;
}
return false;
}
};
dialog.setOnKeyListener(keyListener);
return dialog;
}
}
More info here https://gist.github.com/dhawalhshah/1355547
how can I put a Timer in an android dialog? I have all the dialog methods built, but I can't seem to figure out how to update the text in the dialog view every time the timer fires. my update method is already getting called once per second by another class.
here's my code so far:
public class PlaybackTimerEndingDialog extends DialogFragment implements TimerCallbacks.updateTimer {
private AlertDialog.Builder mBuilder;
private long mTime;
private Context mContext;
private View mTimerEndingView;
public PlaybackTimerEndingDialog(long startTime, Context context){
this.mTime = startTime;
this.mContext = context;
}
private void updateView(String message_text){
LayoutInflater inflater = this.getActivity().getLayoutInflater();
this.mTimerEndingView = inflater.inflate(R.layout.playback_timer_ending, null);
TextView messageView = (TextView) this.mTimerEndingView.findViewById(R.id.timer_ending_message);
messageView.setText(message_text);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
this.updateView("The sleep timer will expie in "+ this.formatTime(this.mTime));
this.mBuilder = new AlertDialog.Builder(this.mContext)
// this.mBuilder.setMessage("The sleep timer will expie in "+ this.formatTime(this.mTime))
.setPositiveButton("Add more time", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
TimerCallbacks.createTimer listener = (TimerCallbacks.createTimer) PlaybackTimerEndingDialog.this.mContext;
listener.createTimerDialog();
}
})
.setNegativeButton("Cancel timer", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
TimerCallbacks.createTimer listener = (TimerCallbacks.createTimer) PlaybackTimerEndingDialog.this.mContext;
listener.stopTimer();
}
});
this.mBuilder.setView(this.mTimerEndingView);
// Create the AlertDialog object and return it
return this.mBuilder.create();
}
#Override
public void finished() {
// TODO Auto-generated method stub
}
#Override
public void update(long time) {
// TODO Auto-generated method stub
// this.getDialog().set
this.updateView("The sleep timer will expie in "+ this.formatTime(time));
this.mTime = time;
Log.d("current time", Long.toString(time));
// this.mBuilder.setMessage("The sleep timer will expie in "+ this.formatTime(time));
}
private String formatTime(long time) {
int seconds = (int) (time / 1000) % 60 ;
int minutes = (int) ((time / (1000*60)) % 60);
String mnStr = (minutes<10 ? "0" : "")+minutes;
String secStr = (seconds<10 ? "0" : "")+seconds;
return "-"+mnStr +":"+ secStr;
}
}
any help with this would be greatly appreciated.
Put that in some function where you want to start a timer.
final Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
updateView("fired");
}
}, 1000);
Update: it's the update method that inflate new layout every time, while the dialog is using first inflated layout.
i have implemented code form the below link to check the idle time of the application
How to intent to another page on android/pop up a message from idle time?
Instead using thread i used asyntask...Now my problem once it reaches the idle time..i want to show dialog to the user application is end relogin from the login activity..
How can i call dialog from the asynctask onpostExcute
public class session extends AsyncTask<Void,Void,Void> {
private static final String TAG=session.class.getName();
private long lastUsed;
private long period;
private boolean stop;
Context context;
final Dialog dialog = new Dialog(context);
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
//here i do the process.......
}
#Override
protected void onPostExecute(Void x){
//stuff to be done after task executes(done on UI thread)
// For Dialog Button**********************************
dialog.setContentView(R.layout.dialog);
dialog.setTitle("Result");
final TextView dialogtxt = (TextView) dialog
.findViewById(R.id.textView1);
final Button closeButton = (Button) dialog
.findViewById(R.id.button1);
closeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
dialogtxt.setText("session time out");
dialog.show();
// ****************************************************
}
#Override
protected void onPreExecute(){
//stuff to be done after task executes(done on UI thread)
}
}
You can do it by calling the dialog from either one of the methods except the doInBackground method.
You may call it in the onPreExecute and show the dialog there and after your background task is done you can cancel it from the onPostExecite method. If you want even more control you can also do it using onProgressUpdate. Just dispatch the progress from your background task by calling publishProgress and overwrite the onProgressUpdate method and do whatever you want there.
This is an example taken right out of the docs.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
The Asynctask need to get the Context.
If your Asynctask is embeded into the activity, just call the java Activity.this as a context.
You can also put a context as a field in the Asynctask and then give it as an arg to Asynctask.
You can call the Dialog.show in the onPostExecute, it's on UI Thread.
This sample AsyncTask is embeded into an activity
public class AsyncDialogBuilder extends AsyncTask {
private Context context = DriverOnTripActivity.this;
private final AlertDialog.Builder dialog = new AlertDialog.Builder(context);
private Integer remoteAllWaitinOnCount;
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
}
#Override
protected Integer doInBackground(Integer... integers) {
remoteAllWaitinOnCount = User.getRemoteAllWaitinOnCount(latestClosestKojo.getRemoteId());
if (remoteAllWaitinOnCount > 0) {
try {
makeDialog();
} catch (Exception e) {
e.printStackTrace();
}
return 100;
} else {
return 99;
}
}
private void makeDialog() {
dialog.setTitle(latestClosestKojo.getName()
+ " - "
+ remoteAllWaitinOnCount
+ " Kojoalas");
dialog.setPositiveButton("S'arreter", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
isDialogPrompted = false;
dialogInterface.dismiss();
goToOnBoardingActivity();
}
});
dialog.setNegativeButton("Ignorer", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
isDialogPrompted = false;
dialogInterface.dismiss();
}
});
}
#Override
protected void onPostExecute(Integer integers) {
if (integers >= 100 && dialog != null) {
dialog.show();
isDialogPrompted = true;
}
}
}
I have a main activity that launches a child activity using the following code:
Intent intent = new Intent();
intent.setClassName(MyChildActivity.class.getPackage().getName(), MyChildActivity.class.getName());
((Activity)context).startActivity(intent);
I am trying to perform a time-consuming task in the child activity and would like to display a ProgressDialog while I do so. My code looks like this:
private ProgressDialog _progressDialog;
private OnClickListener btn_onClick = new OnClickListener() {
public void onClick(View v) {
_progressDialog = ProgressDialog.show(
v.getContext(),
"Please wait",
"Performing task..."
);
TaskThread t = new ExportThread(v.getContext());
t.start();
}
};
private class TaskThread extends Thread{
private Context _context;
public TaskThread(Context context) {
_context = context;
}
private Handler _handler = new Handler() {
#Override
public void handleMessage(Message msg) {
_progressDialog.dismiss();
}
};
#Override
public void run() {
performTask(_context);
_handler.sendEmptyMessage(0);
}
}
For some reason, the ProgressDialog is not displaying. If I use that same code in the main activity, it works - but not in the child activity. In addition, the following code also fails to display the ProgressDialog (but the Toast does display):
private ProgressDialog _progressDialog;
private OnClickListener _btn_onClick = new OnClickListener() {
public void onClick(View v) {
_progressDialog = ProgressDialog.show(
v.getContext(),
"Please wait",
"Performing task..."
);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
_progressDialog.dismiss();
Toast.makeText(v.getContext(), "Done with progress dialog.", Toast.LENGTH_SHORT).show();
}
};
Any ideas out there? Are we not allowed to display a ProgressDialog from a child activity?
Thank you.
why use thread instead of async task?
Async task implements the method onProgressUpdate and publishProgress which makes it easy to display and update UI/progress dialogs.
Here is some example code: http://android-projects.de/2010/12/08/threading-in-android-apps-wir-entwickeln-einen-zahler/