This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Quitting an application - is that frowned upon?
I want to offer the user an option to exit the application as I need to delete some sensitive data, which is stored in the SharedPreferences as long as the application needs it.
As soon as the user wants to exit, the password in the SharedPreferences should be wiped and of course all activities of the application should be closed (it makes no sense to run them without the known password - they would crash).
How can I do that?
System.exit(0) and finish() only exit the current activity - useless. I know there is a taskmanager app. How is that one doing it? It's able to kill the whole application...
When you use the finish() method, it does not close the process completely , it is STILL working in background.
Please use this code in Main Activity (Please don't use in every activities or sub Activities):
#Override
public void onBackPressed() {
android.os.Process.killProcess(android.os.Process.myPid());
// This above line close correctly
}
You are correct: calling finish() will only exit the current activity, not the entire application. however, there is a workaround for this:
Every time you start an Activity, start it using startActivityForResult(...). When you want to close the entire app, you can do something like this:
setResult(RESULT_CLOSE_ALL);
finish();
Then define every activity's onActivityResult(...) callback so when an activity returns with the RESULT_CLOSE_ALL value, it also calls finish():
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(resultCode)
{
case RESULT_CLOSE_ALL:
setResult(RESULT_CLOSE_ALL);
finish();
}
super.onActivityResult(requestCode, resultCode, data);
}
This will cause a cascade effect closing all activities.
Also, I support CommonsWare in his suggestion: store the password in a variable so that it will be destroyed when the application is closed.
When the user wishes to exit all open activities, they should press a button which loads the first Activity that runs when your app starts, in my case "LoginActivity".
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
The above code clears all the activities except for LoginActivity. LoginActivity is the first activity that is brought up when the user runs the program. Then put this code inside the LoginActivity's onCreate, to signal when it should self destruct when the 'Exit' message is passed.
if (getIntent().getBooleanExtra("EXIT", false)) {
finish();
}
The answer you get to this question from the Android platform is: "Don't make an exit button. Finish activities the user no longer wants, and the Activity manager will clean them up as it sees fit."
which is stored in the
SharesPreferences as long as the
application needs it.
Why?
As soon as the user wants to exit, the
password in the SharedPreferences
should be wiped and of course all
activities of the application should
be closed (it makes no sense to run
them without the known password - they
would crash).
Even better: don't put the password in SharedPreferences. Hold onto it in a static data member. The data will naturally go away when all activities in the app are exited (e.g., BACK button) or otherwise destroyed (e.g., kicked out of RAM to make room for other activities sometime after the user pressed HOME).
If you want some sort of proactive "flush password", just set the static data member to null, and have your activities check that member and take appropriate action when it is null.
Using onBackPressed() method:
#Override
public void onBackPressed() {
android.os.Process.killProcess(android.os.Process.myPid());
}
or use the finish() method, I have something like
//Password Error, I call function
Quit();
protected void Quit() {
super.finish();
}
With super.finish() you close the super class's activity.
My understanding of the Android application framework is that this is specifically not permitted. An application is closed automatically when it contains no more current activities. Trying to create a "kill" button is apparently contrary to the intended design of the application system.
To get the sort of effect you want, you could initiate your various activities with startActivityForResult(), and have the exit button send back a result which tells the parent activity to finish(). That activity could then send the same result as part of its onDestroy(), which would cascade back to the main activity and result in no running activities, which should cause the app to close.
Related
I have 2 activities, a 4 digit pin style login Activity (MainActivity) and a content Activity.
This app stores private information and such that should not be able to be seen when resuming an activity, therefore i want the app to completely restart on the login activity each time it's launched, rather than picking up where it left off.
I've tried messing around within the content activity's onStop() and onResume methods, but these seem to be highly unreliable as sometimes when i have the onRestart setup to relaunch the login activity, it won't launch it at all, and calling for the login screen to be activated in the onStop() will prevent me from being able to finish up tasks in the background, such as saving data.
Is there anything i can add to the manifest file that will tell the app to restart from the login activity no matter what? One of the worst things that can happen when working on an app like this is that the information is accessible to someone other than the owner that wasn't forced to login..
What you need is to focus on two calls in your Content Activity:
onPause(): This is where you kill Content activity and remove it from the stack. You can do this easily:
#Override
public void onPause() {
super.onPause();
//Save your data here
finish(); //Kill Contect Activity.
}
onRestart(): This is where you redirect the user to the Main Activity.
#Override
public void onRestart() {
super.onRestart();
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
finish(); //Kill Contect Activity.
}
This graph might help you in understanding the Activity lifecycle:
What you need is setting the flag android:clearTaskOnLaunch and android:excludeFromRecents for your activities in the Manifest.
I have an Android App, and has several activities. I need to provide the button for each activity or specific activity which should allow to Close the App, without going to back to previous activities or run in background.
I tried
finish();
System.exit(0);
Both combination and individually its not working but closing the current activity and navigate to previous activity.
I looked the code from the following question
Need code for exit from app in android
First, having a Quit button is not reccomended in Android as it's not part of the expected UX.
But if you really need it, then you can call your home activity with an intent containing an extra, for instance :
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.putExtra("FORCE_EXIT", true);
Finally in your home activity, when handling the intent (in the onNewIntent() method), if the "ForceExit" extra is set, then finish the activity.
The stack will have been cleared completely by the FLAG_ACTIVITY_CLEAR_TOP and your app will then stop.
The most recommended approach that works for most cases is to feature only 1 Activity, using fragments for content displaying and logic.
This way you only need to finish() the main Activity since it will control the app lifecycle by design.
You will have many other benefits, such as dependency control and reusability, aswell as built-in functionality like animations using fragment transactions while having the possibility of keeping a fragment backstack, which you can manage accordingly towards your expected user interaction and without affecting the conveniency of finishing your app by calling finish() on your host Activity.
Another thing you can do, is to flag intents like this: intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); before launching a new Activity.
This way you can maintain your back trace clean, hence finishing the application whenever the user press the back button or call finish() from any event. However the use of flags is discouraged and considered bad practise.
This may be a hack to solve your problem. but i have just made an app and tested my code and it is working fine.
You will need to create a new activity called QuitActivity or whatever you want to name it and when you want to finish your app or quit your app you will have to start that activity via using this code
Intent i = new Intent(getApplicationContext(), QuitActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
this.finish();
then this is my code for quit activity that does nothing but closes it self after clearing the backstack so your app will quit.
public class QuitActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.finish();
}
}
hope this helps you.
First Finish your current Activity while moving to next by this code
startActivity(intent);
Classname.this.finish();
Second thing just override onBackPressed
#Override
public void onBackPressed() {
//do nothing
}
Use:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
when starting a new Activity, as described in API Documentation.
type only System.exit(0);
or create static boolean needToExit;
set needToExit = true;
in place where you call
finish();
System.exit(0);
in all other activity overwrite onresume
public void onResume(){
super.onResume();
if (MySettingsClass.needToExit){
finish();
System.exit(0);
return;
}
//your other code;
}
I tried some of the answers here using the flags or System.exit(0), but for me it either didn't work or it resulted in weird behavior. Sometimes it would kill the app, but then immediately restart it. I realized that I should just be doing things more of the standard way using request and result codes.
Basically, in your parent activity, start your child activity with:
startActivityForResult(new Intent(this, ChildActivity.class), CHILD_ACTIVITY_REQUEST_CODE);
where CHILD_ACTIVITY_REQUEST_CODE is just a constant (static final) integer. Then in your child activity, when they press the exit button, finish the activity with:
setResultAndFinish(RESULT_CODE_EXIT);
where RESULT_CODE_EXIT is another constant (static final) integer. Then back in your parent activity, handle the result code and finish the parent activity too:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == CHILD_ACTIVITY_REQUEST_CODE) {
if(resultCode != ChildActivity.RESULT_CODE_EXIT) {
finish();
return;
}
}
}
Right now an activity gets destroyed when the BACK key is pressed. How can I make it just stop ( i.e. keep all the variables, etc. alive ), rather then be destroyed?
Thanks!
Why is it that you need to keep the variables alive? Given the established lifecycle of an Android application, I'm not sure that preventing the activity from being destroyed "just to keep the variables" makes sense.
Even if you stop the application without destroying it, there is always the chance that Android will kill it to free up memory. You will have to account for this in your code anyway, and so preventing the application from destroying doesn't save you from writing code.
Variables can be saved and restored relatively easily and quickly using SharedPreferences in your onPause() and onResume() methods. Unless you are storing a ton of data, preventing the application from destroying might not make much of a difference.
It sounds like you want to keep the variables in memory because you intend to return to this activity. Typically, you don't use the back button to navigate away from activities that you intend to come back to. Instead you would create an Intent and start a new activity. When you do this, Android places the current activity on the Back Stack calling onPause() and onStop(), which seems like exactly the sort of behavior you are looking for.
So if you still really want to prevent your activity from being destroyed (at least until Android decides it's using too much memory and kills it on it's own) you could always use Sagar's code and start a new activity in onBackPressed().
#Override
public void onBackPressed()
{
Intent intent = new Intent(this, Other.class);
startActivity(intent);
}
Just be certain that that is what you really want to do.
Simple one line
#Override
public void onBackPressed() {
mActivity.moveTaskToBack(true);
}
Pressing the BACK key triggers the onBackPressed callback method of Activity class. The default implementation of this callback calls the finish() method.
http://developer.android.com/reference/android/app/Activity.html#onBackPressed()
You can override this method to move the activity to background (mimick the action of pressing the HOME key.
eg:
#Override
public void onBackPressed() {
onKeyDown(KeyEvent.KEYCODE_HOME);
}
You could also instead consider moveTaskToBackground() mentioned here:
Override back button to act like home button
I have managed to work out exactly what you want: switch between 2 activities using Back button and keep them all not to be destroyed!
For example: you have 2 activities A & B. A will be started first, then A calls B. When B is loaded, user press Back button and switches back to activity A from B. From now B should not be destroyed and just goes to background, and when user starts activity B from A again, activity B will be brought to foreground, instead of being re-created again or created new instance! How to implement this:
1. Override onBackPressed() of activity B:
#Override
public void onBackPressed() {
Intent backIntent = new Intent(this, ActivityA.class);
backIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(backIntent);
}
2. On activity A, call activity B:
public void callActivityB() {
Intent toBintent = new Intent(this, ActivityB.class);
toBIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(toBintent);
}
remember to add flag: Intent.FLAG_ACTIVITY_REORDER_TO_FRONT when you call A&B.
This is similar to this question that was asked earlier.
Hope this helps!
N.S.
First of all, sorry for not answering the question, cause, I still have no optimal answer for it.
But, I really like when people start asking "what do you need this for". And, very rarely, the person who asked the question, really deserves this kind of question. I think not this time, but ok, this is not the issue...
Anyway, I will try to point out why some of us are convinced that
going from Activity A to Activity B(creating UI based on some data fetching) AND
going back from B to A(destroying all the created UI and/or fetched data in B) is sometimes a bad concept. Better solution would be to keep the stack as it is, so using something like finish() in Activity B, but keeping the Activity B in Pause state, so later when calling it again from Activity A - it just goes in onResume = nothing recreated in UI, no additional data fetching. The bonus of course is a fast and responsive UI, and the difference is really if you have a more complicated UI layout.
Just specify in the manifest for the activity as
android:persistent="true"
That should prevent your activity getting destroyed. To know more about this please refer to these below links which were answered by me
How to prevent call of onDestroy() after onPause()?
Prevent activity from being destroyed as long as possible
In the above posts I have explained in detail with a use case
I need to finish all the activities running in an Android application when an exit button is clicked. How can I do that?
What I want:
An option menu on screen with an EXIT option.
When I click the Exit menu, the application should close.
How to make a button for the user to immediately finish all Activities
When the user wishes to exit all open activities, have them press a button which loads the first Activity (passing in an intent to clear out all the other activities) that runs when your app starts. Then inside the one remaining activity (LoginActivity), place some code in onCreate to have it choose to self destruct.
Details:
Create a button and call it "exit", make a buttonlistener for that button, and put the following code in there. What it does is load the activity, makes it the only remaining activity by clearing all activities underneath it.
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
The above code clears all the activities under LoginActivity. The LoginActivity must be the first activity your app runs. So now we are left with only LoginActivity activated. Now we have to get LoginActivity to check the putExtra parameter, and if it has the value "EXIT" then destroy itself as well.
Put the following code inside the LoginActivity's onCreate and onResume, to check the "EXIT" parameter and finish when it is seen:
if (getIntent().getBooleanExtra("EXIT", false)) {
finish();
}
Why is this so hard, why isn't there just an exitAllActivites() function?
Android OS Developers make this hard because they don't want you to give the user an Exit button. They want the user never to care if their App is running or not. If they want it, they run it, if they don't want it, they stop using it. There are benefits to this model, because then an app can be destroyed to make room for a phone call and heavy map-usage, and then they re-run your app, they pick up right where they left off, rather than having to restart from scratch.
So if you use this code, try to cooperate with the Android Developers vision for Android and make it so that the App can be destroyed/recreated at any point, and the user always picks up where they left off. Requiring a user to 'exit' is a hassle.
use StartActivityForResult function for starting a new Activity and when user presses EXIT button, send a unique value as a resultcode. Check for this resultcode in onActivityForResult func and if you find the same unique code then finish the activity.
I don't understand the people who say that this should not be done. Closing an activity can be done quite easily using the built in method to do so.
There is no place in the official documentation that says this should not be done.
For those who think it should not be done for any purpose, maybe you can't think of a reason to do so. There are plenty of legitimate reasons to do this. And since it is a method built in to the Android code.. Google has also decided that you might need to depending on your use. Not all of us only create consumer applications for Android.
So to accomplish this task..shutting down all of the activities in your stack
public void quitApp(){
this.finishAffinity();
}
I created a kiosk app that was run as the default launcher. So I needed a way to exit the app to get to settings or other apps on the device. So in an admin Activity, I placed a pin number pad.. after the user inputs the correct pin, the app needed to exit to the original launcher. I used above code.
You should not implement an Exit button in an Android application.
Read http://groups.google.com/group/android-developers/browse_thread/thread/1bf0f7a4a9c62edd/a0a4aedf21ae5f76?pli=1
Cheers
How to close all activities in Android:
Why are the Android OS devs telling me not to create an Exit button?
If you give developers a hammer, they will use it, and everything becomes a nail, so don't give them a hammer. This is why there is no one-liner to exit all activities.
Why is an Exit button so bad?
You may be frustrated wondering why killing all activities in Android is so difficult. It's hard to do because you've got to bite the bullet and understand how you created the stack, and what it looks like. In what order should the Activities be destroyed? What if the user gets a phone call and needs to nuke your app ASAP? You NEED to have a plan for unwinding. It can't rely on the Activity Manager to babysit your app. If you want to kill your app, the OS devs are twisting your arm to create a unwinding plan because they don't want your application to have any errors when the Activity Manager nukes it.
This self destruct mechanism I go on to describe cooperates with the Activity Manager and causes a cascade effect that causes all activities to finish themselves no matter how they are organized.
To add this cascading self destruct to your app, do these three things:
If you are newbie to android and have never done this before, I suggest you create a brand new bare bones android project to test this out and get a feel for how it behaves. Only when you get the "aha" moment of understanding why this works, then can you extract the usefulness of the code below to delight the user.
Put this override method inside each one of your activities:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
//onActivityResult is called when a launched activity exits, giving
//you the requestCode, 1234, that you started it with. The resultCode
//it returned, 900, and any additional Intent data from it. The
//resultCode will be RESULT_CANCELED if the activity explicitly
//returned that, didn't return any result, or crashed during its
//operation.
switch(resultCode)
{
case 900: //Make 900 a final global variable if you want.
//900 means CLOSE_ALL_ACTIVITIES to me. It is
//a signal that the self destruct button has
//been initiated and all activities should end.
setResult(900); //setResult sets the resultCode that will be passed
//to onActivityResult in the activity that called
//this activity. this will immediately tell the
//parent to self destruct even before the next
//command, finish(), is run.
finish(); //Now stop this activity.
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
If you have more than 3 activities, consider having each activity extending a "MyAppActivity" with the above code in there. If you catch yourself copy/pasting the above method into 15 different activities, slap yourself once, and take a class on good Object Oriented Programming. Then read this.
( Details about onActivityResult. ), ( Details about setResult. )
Whenever you have the user start a new activity, you must do it exactly this way:
Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
startActivityForResult(myIntent, 1234);
//The 2nd parameter of startActivityForResult is what is sent to
//resultCode in the onActivityResult method. The code `1234`
//doesn't do anything here because it is a flag that is
//ignored in onActivityResult.
More information about startActivityForResult.
If you don't use startActivityForResult, then the self destruct unravelling won't work.
When you want to exit your application, initiate self destruct like this:
setResult(900); //900 is the self destruct code.
finish();
Then the activity stack unwinding plan cascades through the entire app.
you should do this on yourself. read this good blogpost: http://blog.radioactiveyak.com/2010/05/when-to-include-exit-button-in-android.html
Another solution to finish all activities works for me:
Somewhere in my Controller class, there is a method to initiate the shutdown:
/**
* Ask for application shutdown.
*
* <p>
* After the call, the system shall wipe the entire task and activities and
* then call {#link #onTaskWiped()} to finish the cleaning.
* </p>
*/
public void attemptShutdown() {
// wipe the task and its activities.
Application app = getApplication();
Intent intent = new Intent(app, ShutdownActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
app.startActivity(intent);
}
The ShutdownActivity is just performing data cleanup before finishing itself like it was told before.
/**
* This activity is started by {#link Controller#attemptShutdown()} to wipe the
* entire task and activities. It calls {#link Controller#onTaskWiped()} in
* {#link #onCreate(Bundle)} and finish immediately after.
*/
public class ShutdownActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// this is where you release the application data.
Controller.controller.onTaskWiped();
finish();
}
}
And finally the Manifest part. I have set the transparent style to avoid the small flash when the activity appears but it does not seem to work well.
<activity android:label="Exiting..."
android:name=".ShutdownActivity"
android:excludeFromRecents="true"
android:theme="#style/Theme.Transparent" />
My application starts with a welcome screen Activity, but that screen has an option to skip that screen altogether in future launches.
What's the proper Android way to do this? Initially, I just automatically detected the skipWelcome preference and switched to the 2nd activity from Welcome. But this had the effect of allowing the user to hit the back button to the welcome screen we promised never to show again.
Right now, in the Welcome activity, I read the preference and call finish() on the current activity:
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
boolean skipWelcome = preferences.getBoolean("skipWelcome", false);
if (skipWelcome) {
this.finish();
}
And then I implement onDestroy to move on to the next Activity:
#Override
public void onDestroy() {
super.onDestroy();
startActivity(new Intent(Welcome.this, StartFoo.class));
}
But this makes for some weird visual transitions. I'm starting to think that I need a base Activity that pops open Welcome only if proper, and then goes to StartFoo.
I can't comment on Mayra's answer or I would (not enough rep), but that's the correct approach.
Hidden in the Android documentation is this important phrase for Activity.startActivityForResult(),
"As a special case, if you call
startActivityForResult() with a
requestCode >= 0 during the initial
onCreate(Bundle
savedInstanceState)/onResume() of your
activity, then your window will not be
displayed until a result is returned
back from the started activity. This
is to avoid visible flickering when
redirecting to another activity."
Another important note is that this call does not block and execution continues, so you need to stop execution of the onCreate by returning
if (skipWelcome) {
// Create intent
// Launch intent with startActivityForResult()
return;
}
The final piece is to call finish immediately in the welcome activity's onActivityResult as Mayra says.
There are a few solutions to this.
Did you try just launching the activity and finishing? I vauguely remember that working, but I could be wrong.
More correctly, in if(skipWelcome) you can start the new activity for result, then when onActivityResult is called, immidiately finish the welcome activity.
Or, you can have your launcher activity not have a view (don't set content), and launch either the welcome activity or StartFoo.