I've already discovered that you can't override the Home button on an Android phone. It exits the application, it ALWAYS exits the application, and it DOESN'T bother with any sort of namby-pamby confirmation. I suppose I understand Google's reasoning -- but I do think it's a bit short-sighted...
Anyway, (before I learned about the Home button), I set up my app so the user can exit the application through the Options Menu -- using onCreateOptionsMenu() and an XML file, I set up a simple pop-up menu that's displayed when the Menu button is pressed. One of its choices is Exit, and it works fine.
However, it occurred to me that it might be good practice to add a confirmation dialog to the exit process (even if it could also be considered superfluous). So, I created an AlertDialog with the title "Do you want to Exit?" and Yes and No buttons...
The click listeners for the buttons are simple and just set exitConfirm (a boolean) true or false. The code that handles the Exit menu choice then cleans up after my application and executes finish() or not depending on the state of exitConfirm...
Unfortunately, it completely doesn't work... All of the code in onOptionsItemSelected() for the exit case executes and THEN the Dialog is displayed!! I suppose I should've seen that coming. And I suppose if I keep pounding on it, I'll come up with a way accomplish this, but I thought I would ask the community for suggestions - so, does anybody have a suggestion for a way to smoothly exit an Android application in a manner that includes the step of getting confirmation from the user??
Thanks,
R.
First of all - this is a terrible practice. Asking for confirmation may be a nice option on a desktop application, but you're writing a mobile application. It's different. Actually, I need to write that in bold:
You are not writing a desktop application.
I recommend: No splash screen. No exit option. Definitely no exit confirmation. Here is an excellent question about it.
For your question: Use setPositiveButton and setNegativeButton to handle buttons.
Short answer:
You should read: When to Include an Exit Button in Android Apps.
Long answer:
You can try something like this:
protected Dialog onCreateDialog(int id) {
Dialog dialog = null;
switch (id) {
case MENU_QUIT:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.main_screen_quit_text))
.setCancelable(false)
.setPositiveButton(
getString(R.string.main_screen_quit_yes),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
moveTaskToBack(true);
}
})
.setNegativeButton(getString(R.string.main_screen_quit_no),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
return alert;
default:
dialog = null;
}
return dialog;
}
Apparently, it's generally considered not to be cool to have an exit button (or menu item, or whatever) in your Android app. Apparently, this is because your application doesn't really exit. It's only minimized out of the way, and presumably, the OS will take care of it eventually.
However, if what you're doing requires some level of clean-up when you're done doing it, this is what I think I know about that:
Pay careful attention to the various Android "Life Cycle Methods", especially what kicks them off. Life cycle methods include onCreate(), onStart(), onResume(), onPause(), and onStop(). There's also onDestroy() -- the complement to onCreate() -- but I don't currently use it.
These methods are called in response to various events (like pressing the Home button), but what was important in my case was that minimizing the application calls onPause() and maximizing it calls onResume(). Hence, I needed to call my set up and tear down methods from those locations, and NOT, for instance, from onCreate() and onDestroy().
There is a function called finish() that I used to use all over my code. Now it's only in the method that's called to handle loss of communication with my external device. I believe the results of calling finish() are exactly the results of pressing the Home button -- so, it's just a way to "press" the Home button in software.
The long-winded conclusion to all this is the Home button absolutely WILL hide your application from the user's view. You cannot trap this key press -- no matter how badly you want to add some sort of, "Are you sure??" functionality. However, the app's been minimized, not closed, and this can either be good or bad. If you've written your start up and shut down code properly (and added it to the proper life cycle methods), you won't blow things up, and your user will be able to easily return to your app once they've learned to long press the Home button to see a list of minimized apps.
With any luck, I suppose, they'll blame their frustration on Google, and not on you...
Related
I'm doing a videogame. I wanted the application to have 3 screens. The presentation screen, the play screen, and the end screen.
I know that an activity can be started with an intent, but my problem is that in doing so, the last activity would be stacked, allowing the user to come back to the previous activity (or screen).
Is there a way to avoid this ?
use the finish() method inside the activity you want to close.
Although others have covered that you can simply call the finish() method to close down an activity if you do not want your user to be able to return to it, there is another issue I wish to cover quickly.
The Android Design Principles, or more specifically the Navigation Principles tell us that we should not be messing around with the default behaviour of the back button too much. A direct quote from the guide;
Consistent navigation is an essential component of the overall user
experience. Few things frustrate users more than basic navigation that
behaves in inconsistent and unexpected ways.
So, instead of preventing your users from being able to return to the entry screen, consider instead a prompt that notifies your user that they will be leaving the game. That way the back button continues to work as they would expect, and your users will not be suddenly dropped from gameplay. You can override the back button like so;
#Override
public void onBackPressed() {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Leaving the Game");
alert.setMessage("Do you want to leave the game? You might lose your progress.");
alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
YourActivity.this.finish();
}
});
alert.setNegativeButton("Cancel", null );
alert.show();
}
Also, as a note, if you choose to simply close the previous Activity using finish(), the back button will then drop the user out of the app entirely because there is no Activity to go back to.
I want to disable back button from closing the app.
How can i disable back button?
You can override the onBackPressed() method and determine what happens in that method. Like this:
#Override
public void onBackPressed() {
// do nothing because you don't want them to leave when it's pressed
}
Just add that method to your activity class and you're good to go.
However, this is bad app design. What you would most likely want to do is make a dialog pop up that asks them if they are sure they want to leave. You would add the dialog code inside that method so that when the back button is pressed, the dialog pops up.
Generally, that's not a good idea. Users hate to feel "trapped" in your app.
Many users are able to start apps "on top of" other apps. When they hit "back" they may expect your app to stop, and the app they were in previously to appear. This is different from "home" where they expect all apps to go to the background.
Users familiar and comfortable with this functionality will not like it if you change "back" - although you may give them options like "press back again to exit" as some apps do. It depends on your particular situation.
So if you are in need of it, here is a good reference:
Android - How To Override the "Back" button so it doesn't Finish() my Activity?
I have an app that consists of two activities: the "main" activity (M) and the "settings" activity (S). S can only be launched from M. The purpose of S is to modify settings which affect M. S has a "done" button that finishes the activity and goes back to M (through M's onActivityResult method, with an Intent that contains the new settings for M to apply).
My problem is: if I go back from S to M using the hardware "back" button (instead of S's "done" button) the system brings M to the top without any knowledge of the modified settings. Can this behaviour be modified? Ideally I would like to alter the behaviour of the hardware "back" button when S is on top, so that it cause S to finish (that way M would get the new settings).
If that's not possible, and more generally: what would you do you to have the settings applied on a "back" button pressing?
You can simply override onBackPressed()
#Override
public void onBackPressed()
{
// check if settings have been changed
super.onBackPressed();
}
Since this is a "closing action" do the super call after you have done your other work.
Following up on comments left on blackbelt's answer (now deleted comments) you may want to consider, if you haven't already, asking the user if they are sure they want to exit without saving in case they went into settings and decided not to change anything. What if they press the back button because they decided not to save the changes? You may already have something in place for this like a cancel button.
you have to override the onBackPressed from Activity and manage the same logic from the done button
You can also introduce a new java class to your package with static fields holding your settings.
Write to them as user changes settings & read from them as soon as in Activity's OnResume() method or later as needed.
You can achieve what you want by overriding onbackpressed method
#Override
public void onBackPressed() {
Intent intent = new Intent();
//get your settings from your views
intent.putExtra("setting1","on");
intent.putExtra("setting2","off");
setResult(RESULT_OK);
finish();
}
The answers above will do what you want, however:
Have you looked into using the built in android SharedPreferences? That way changes to the settings (made in S) will be stored to the device and then you can tell activity M to look at the settings and update appropriately in the onResume method. Plus the settings will be saved forever and it doesn't matter what happens to S.
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 want to know if when the user presses "Yes" on an alert dialog and this one is dismissed, that event executes the onResume method of the activity in which the user is in.
Because I have a "Clean" button that asks the user if he's really sure of cleaning all the fields of the form (the activity) in order to redraw the activity with the empty fields.. The form is created dynamically, so I don't know a priori the elements in the GUI to set them empty...
Sorry for my bad english!!
Thanks and Greetings!
Not sure if this is the approach that should be taken, but you should be able to do what I think you are requesting. If for some reason this is what you would want to achieve.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Do you want to clean?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.dismiss();
((ActivityName) appContext).onResume();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.dismiss();
}
});
builder.create().show();
}
You will really want to be calling your clean function instead of anything like a lifecycle call on a success while doing nothing on a failure.
Another potential way to approach this would be to bring the current activity back to the front using flags.
Intent intent = new Intent(this, CurrentlyRunningActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
Which would also provide a way to call upon your main activity without directly referencing the onResume() call, as pointed out is not the appropriate approach; however, I did want to directly respond to the question as it was asked.
To see if a method is called you can put a breakpoint at the method, onResume(), to see what happens. If you aren't familiar with the Acitvity Lifecycle then doing this will help you familiarize yourself with it and reading the provided documentation.
Now, I don't think you should redraw your whole layout just to clear some Views. It would be more efficient, in my opinion, to just reset all fields by using setText() or another method for whatever you need when the user clicks "ok " or whatever. You can use invalidate() if you need to redraw certain Views
I also recommend watching
Google I/O-Turbo Charge Your UI
Activity LifeCycle <-- very important to understand
AFAIK This is not possible since in order to have displayed the dialog box the activity would have already passed the onResume state. Check out the following page for more on the life cycle on an Android app (it really helped me understand better):
App lifecycle
If you're not sure when the onResume is called, add a log into the onResume method.