In my app I have several activities one after the other. After my login screen I have Home screen and after that several screens. Now When user select device home button or power off button I want to display login screen when user again comes to my app and then Home screen. Rest all activity I am finishing it from my base class. Now till here I have done, My problem is when I show a dialog in some other activity and at that instance if user click on home or power button, then i am getting WINDOW LEAKED EXCEPTION.
Like I have TempActivity is displaying a dialog and user clicked home button so StoreActivity and TempActivity will finish but Dialog never got chance to be dismissed. So What would be the best way to deal with this situation.
Is there some better way to dismiss the dialog so that I don't get any exception.
Override onDestroy, there, check whether the dialog is present, if so, dismiss it.
dismiss() in onDestroy() doesn't solve this problem. Try to override activity.finish() like:
#Override
public void finish() {
if(mDialog != null) {
mDialog.dismiss();
}
super.finish();
}
Put the Dialog handle in a member object, then when you finish the top activities, dismiss the dialog first.
You could make this more neat by creating abstract Activity class (which all your activities extends), which dismisses possible dialog when calling finish()
Related
Simply my problem is that i have the following scenario:
I have activity A ... and there is a custom dialog appearing on it .. it's quite big but it's not an activity it's just a dialog ..
Clicking on a certain item on that dialog opens new activity B
After clicking on the dialog .. I need to dismiss the dialog and open Activity B
what happens is that Activity A appears for like a second or less then Activity B opens ..
I've tried dismissing the dialog after calling startActivity() .. but still the A activity still shows briefly before opening activity B ..
Any suggestions ?
As alternative to #user543 solution (which also valid) you can hold on with dismissal of the dialog. Launch new activity from dialog and leave dialog alone (or better maintain a flag for later dialog dismiss), activity will appear immediately on top of Activity A and it's dialog. When user will click back button, onStart and onResume of Activity A will be called, so check if that flag and dismiss the dialog there
Dismiss the dialog in onStop(). Because after loading Activity B only onStop() will call in Activity A.
Define some boolean variable like:
boolean isClicked=false;
Whenever u r performing some click functionaly in dialog, then make this variable as 'true'. Then in onStop() check like this:
#Override
protected void onStop() {
super.onStop();
if(isClicked)
{
//dismiss dialog
}
}
I am developing a small app which shows passwords of the user through a Dialog screen.
When home button is pressed, I need to dim the screen (on the multi tasking window) so that any other person cannot see the password.
When user re-opens the app, it asks an application lock. But if the user leaves the password Dialog open and presses the home button, dialog and the password which user last looked at stays visible (on the multi tasking window) for a while (3-4 seconds!!) until a new dialog asks the lock.
So far I tried ever possible dialog.dissmiss() options. Dialog dismisses only when app is opened again (until a new lock dialog appears) even I put dismiss() in onPause, onStop etc.
Any idea appreciated.
I also tried,
android.os.Process.killProcess(android.os.Process.myPid());
this.finish();
System.exit(0);
none of them actually worked.
Suggestion 1: Double-check your implementation. Tying your dialog to the activity lifecycle seems like a good idea (especially to avoid leaked window errors as described here)
The following example works out well for me (with coachMark being derived from Dialog)
#Override
protected void onResume()
{
log.debug("onResume");
super.onResume();
// Show the coachMark depending on saved preference values
coachMark.mayBeShow();
}
#Override
protected void onPause()
{
log.debug("onPause");
// Hide the coachMark if it is showing to avoid leakedWindow errors
coachMark.maybeHide();
super.onPause();
}
onPause definately gets called when you press the home button, so if this approach does not work for you, try not recreating the dialog in the restarting part of the acitivty lifecycle (onRestart(), onStart() and onResume()) and see, if it gets dismissed correctly.
Suggestion 2: Should all of the above fail, you might consider overriding the home button as described here. I highly advise against it though, since this may cause the app to work in an way that the user does not expect it to.
I am stumped on this issue, my onBackPressed() method doesn't work when it has to. My scenario is as soon as activity starts, progress dialog shows up because I called asynctask.execute() in onCreate. When the process takes long time I want to give user a feature that he can dismiss the ongoing process(downloading data from the server) so I tried to dismiss the dialog and finish the activity when back button is pressed, but it's not working.
When I normally press back button after I have got the data, then the control seems to be flowing under onBackPressed().
Below is my code snippet:
public void onBackPressed() {
if(progressDialog != null && progressDialog.isShowing())
{
progressDialog.dismiss();
}
finish();
}
Is there any other way to give user an opportunity to cancel that anytime. Please suggest me how to make the entire process and activity terminated when the user presses back button.
For canceling the progress dialogue please set progress dialog cancel as true.
dialog.setCancelable(true);
I have a timer which runs continously. When I press the BACK button I made a dialog to appear where you can quit from that intent or go back and cointinue the timer what has been stopped by the BACK button. Well if I click on the contimnue, the onResume() method makes the timer continue and it works good. But, if I press the back button when the dialog is on the screen I want the timer to go on just like if I press the Continue on the dialog. But instead, I press the back button and nothing happens, the timer is stopped and it is not good for me since some of my methods only works if the timer is going or it is stopped by the dialog. But if there is no dialog and the timer is stopped numerous potential errors can happen. So how can I stop the user to press the back button when the dialog is on the screen?
I tried something like this:
if ((keycode==back) && a=0 ) {... a=1 , onPuase()} // dialog comes in onPause() just happened
else ((keycode==back) && a=1 ) {... a=0, onResume()} //I want onResume() to happen here
But it is not good. The dialog appears on the first Back button then it disappears on the second Back (nothing happens here). The timer is still stopped here however the third back button starts the timer. So there is an unecessary Back which can cause troubles since the useres wont know that they have to press it again...
A few advices:
Do not call onResume/onPause manually, only system should make it. Else you'll have unexplainable issues on various devices.
You really want to use OnDismissListener ( http://developer.android.com/reference/android/content/DialogInterface.OnDismissListener.html ). As starting from ICS, dialog can be dismissed not only by pressing Back key, but also by tapping somewhere on screen, outside the dialog.
If you want to prevent dismissing the dialog by "back" and "tapping out of dialog" - use setCancellable(false) http://developer.android.com/reference/android/app/Dialog.html#setCancelable(boolean) for the dialog.
Good luck
If you want to be notified when user pressed BACK while your dialog was displayed, use OnDismissListener
implement OnDismissListener in your DialogClass
and override OnDismiss method
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
//you can control back button from here
}
A snippet from the Android Activities document(scroll down to the "foreground lifetime" line) says :
An activity can frequently transition in and out of the foreground—for
example, onPause() is called when the device goes to sleep or when a
dialog appears.
I don't quite understand this. Under what circumstances should this happen? Is onPause() called only if the context of the dialog in question is different from the activity on top of which the dialog is to be displayed?
EDIT: Adding code sample to illustrate my doubt in detail
Going by the above-mentioned quote from document, should my activity's onPause() method get called when the AlertDialog (or just the Dialog) in the following code gets displayed? Should I see the "onPause called" log entry when the dialog is displayed?
But I don't see that happen. And it shouldn't either, if I have understood the Android life cycle correctly! So, what's the document pointing at then?
public class LifeCycleTestActivity extends Activity {
private static final String TAG = "LifeCycleTest";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onClick");
AlertDialog dialog = new AlertDialog.Builder(LifeCycleTestActivity.this).create();
dialog.setMessage("You Clicked on the button");
dialog.setTitle("Dialog!");
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
dialog.setCancelable(true);
dialog.show();
/*
Dialog dialog = new Dialog(LifeCycleTestActivity.this);
dialog.setTitle("Dialog!");
dialog.setCancelable(true);
dialog.show();
*/
}
});
}
#Override
protected void onPause() {
Log.d(TAG, "onPause() called");
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume() called");
}
}
onPause() is called when your activity is no longer at the top of the activity stack. A Dialog by itself is not an Activity, so will not replace the current Activity at the top of the stack, so will not cause anything to pause.
A dialog (lower-case) does not need to be implemented by a Dialog class, however. For example, it is not uncommon to implement one with an Activity whose theme is set to that of a dialog. In this case, displaying the dialog-as-an-Activity will cause the new Activity to be on the top of the stack, pausing what previously was there.
I've been doing quite a lot of code with dialogs, including the AlertDialog that you mention, and I've also tried to check if onPause() is being called on the activity when the dialog pops up, but thus far my conclusion is that the activity simply keeps running and that onPause() is not called.
Not sure if it helps, but at least you now know that there are others who experience what you're experiencing :-)
Its wrong that activity remains no longer at top of activity stack in onPause phase.
Condition an activity to be onPause state -
Activity partially visible e.g. dialog on activity.
The Activity object is retained in memory, it maintains all state and member information, and remains attached to the window manager.
e.g Home button pressed causes activity to go in onPause(). Still at top of stack.
In fig 1. Activity3 will be destroyed and removed from top stack
In fig 2. Now Task A goes to background but Activty X still on top of stack . If you override onPause() method int this state
Figure 1. A representation of how each new activity in a task adds an item to the back stack. When the user presses the Back button, the current activity is destroyed and the previous activity resumes.
Figure 2. Two tasks: Task B receives user interaction in the foreground, while Task A is in the background, waiting to be resumed.
I think I remember reading in an earlier version of the Android Lifecycle that onPause was called when none of the activity is on display. i.e. if a bit of your activity is still visible under a popup, onPause will not be called.
Maybe some other experts can vouch for this behavior?
In my slightly weird experience onResume gets called with dialog.setCanceledOnTouchOutside(true); but onPause never gets called.
That being said, I think the documentation might focus on system dialogs (e.g. low on battery).
#hackbot
onPause() is called when your activity is no longer at the top of the activity >stack. A Dialog by itself is not an Activity, so will not replace the current >Activity at the top of the stack, so will not cause anything to pause.
everything depends on implementation...
what is a Dialog ? is a Window added to Display by WindowManager///
so the window when it shows is on top of everything .... (Z order)
what is activity... is "thing" that also creates its window....
when a dialog is shown or it's window comes visible on top of an existing activity, then it overrides partial the activity window so existing activity will move to partially invisible state and you will get call to onPause() from ActivityThread.
but to be sure we also need to consider here a one think...
the state of window if is a standalone window shown on top or it is a child window and a parent of it is a activity window....
so when we know
the Window.LayoutParams (FLAGS) we use to add
and what IBinder is used for the Window to show
we will khow how the activity will behave when windows are shown each over other .. as each winndow has a callbacks they are used by activity or dialog to manage their states...
involved components:
android.os.IBinder
android.view.Window
android.view.Window.Callback
android.view.WindowManager
android.view.WindowManager.LayoutParams
android.view.Display
btw:
if you want to know the windows on screen [ applicable only for the process you own - as window belongs to process and those are Sandboxed - each processs is a separate JVM strictly saying "ART" ] you can use a replection see :
android.view.WindowManagerImpl
android.view.WindowManagerGlobal
onPause() is called every Time when an Activity goes background and Dialog or other Activity comes foreGround. This is done to give first priority to something with which the user is interacting. e.g: assume you are in homescreen (which in turn is an activity) of an application, the homescreen is said to be in foreground. and when you go to next screen by pressing some button or a dialog appears the next screen/Activity/Dialog comes to foreGround and homecreen goes to backGround, which just means homeScreen's onPause() method got called.