We have a live video streaming app with a lot going on. A user presses the home button. I want the app to be removed from memory. When the app is selected again we have a brand new load. There are a lot of processes going on and we don't want to have to manually manage all the connections, streams, etc. This is how our iPhone version of the app works.
I've read this: Is quitting an application frowned upon?
I don't really care about Androids design patterns here either way. However if someone has an elegant, simple way that all my activities will be removed from the stack when the home button is pressed, and then when the app is reloaded it starts with a fresh main activity, that would be great. Also, I can't seem to ever debug when the home key is pressed in onKeyDown. Its simply not registering. (keyCode == KeyEvent.KEYCODE_HOME) is my check. It picks up back buttons, etc.
Any thoughts?
You can call system.exit(0); but I would still suggest to follow the Android guidelines, and clean everything (as should be) on onPause() or similar method.
Could you just override the onPause method and use the finish() function?
int p = android.os.Process.myPid();
android.os.Process.killProcess(p);
you can do than on button click. Define any static method like exit() and define
android.os.Process.killProcess(android.os.Process.myPid()); in exit method
in the main or first activity.
Then call this method on button click.
If you want to clear all of your activities from the stack, you can broadcast an intent from the activity which initiates the quit like this:
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("CLEAR_STACK");
sendBroadcast(broadcastIntent);
And in every one of your activities that you want to be cleared off the stack you can create a BroadcastReceiver with an inner class:
class ActivitiesBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
}
And register your BroadcastReceiver in the onCreate() method:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("CLEAR_STACK");
BroadcastReceiver r;
r = new ActivitiesBroadcastReceiver();
registerReceiver(r, intentFilter);
Related
This question already has answers here:
Finish all activities at a time
(21 answers)
Closed 3 years ago.
I want to kill my app from a exit button on my navigation drawer. the drawer has a exit button that is suppose to just kill the whole app (all activity) and gets the user out of the app .
When i am using finish() in the first activity its working but when i go into the app and call finish() the activity gets killed and returns to previous activity but never really kills the app.
Tried to use System.exit(0) but no luck.
Extra Information Might Help
I have all my activity started with android:launchMode="singleTop" . it means all those activities that are already created will not be created again and just reordered to front on calling.
Do anyone have any suggestion for this , please do help.
Update
I want to make some updates here as my question looks like this SO Question.
As i have already said i am using a android:launchMode="singleTop" . and this answer is not working for my case. I have to call onCreate() to make this happen but it is not my case.
Use below code
public void AppExit()
{
this.finish();
Intent intent= new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
System.exit(0);
}
Call above function to exit from App.
First, you need to decide if you just need to take the user out of the app, or if you also need to finish() all of your activities. It depends on your needs, but my guess is that in most cases most users won't know the difference, and Android is designed to have many apps having activities still running. If this is all you need, then you can just use an Intent to take the user to the home screen.
Intent intent = new Intent(Intent.
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
If you actually want to finish() your activities, then you need a mechanism to inform all currently running activities that the user is exiting the app. You can use something like EventBus to send an event that will be received by all registered subscribers; if you don't want to use a third-party library, you can do the same type of thing with LocalBroadcastManager. To do that, you would register a BroadcastReceiver with an IntentFilter for a custom action and broadcast an Intent with that action when the user wants to exit.
In either case, every activity should receive the signal and call finish() on itself. Note that the subscription (in the EventBus case) or the registration of a receiver (in the LocalBroadcastManager case) must be still active after onStop(), so I would register in onCreate() and unregister in onDestroy().
Use below code in your exit button
Intent intent = new Intent(this, ActivityOne.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
And, in your ActivityOne.class oncreate() method just put below code
if (getIntent().getBooleanExtra("EXIT", false))
{
finish();
}
As a few answers say, call finish(); after you start an intent from an activity. That will make sure the current activity is the only running activity. Also try super.finish(), which will call finish() at parent activity.
You can alternatively use only one activity with many fragments. That way, if you call finish() in the exit button OnClickListener code, you'll exit the app. This will also save a lot of coding since you will be defining the navigation drawer once.
First of all, Android apps are not intended to be killed other that by the system, which attempts to keep them in memory in case the user will return.
But, if you have to do it, try this:
android.os.Process.killProcess(android.os.Process.myPid());
I have an app that include both a complex service and activity UI. The app runs on multiple devices which communicate with each other over WIFI via the service.
Since the app is a prototype/in-development, I want to add support for a "force restart" that will kill the app and re-launch it clean. There is a lot of shared UI stuff that has gotten gummed up depending on the use case, and it would be easier during testing (I have multiple devices) if I could just touch a button to restart the app completely.
So, does anyone have any suggestions on how to:
1) Force close/stop/kill your own app, from within your app.
2) Set a timer/intent that tells the OS to launch your app before you close/stop/kill it.
Any tips would be appreciated! Thank you.
Use the below code for restart the app:
Intent mStartActivity = new Intent(HomeActivity.this, SplashScreen.class);
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(HomeActivity.this, mPendingIntentId, mStartActivity,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager) HomeActivity.this.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
System.exit(0);
As you can figure out, finish() is what you want to use in order to kill off an activity. A.C.R.'s way would work, however it will only restart your activity, not really kill off the process, and start it back up. If that's what you are looking for, instead of having a dummy Activity that restarts your original Activity, the correct way to do it would be to use flags.
Intent i = new Intent(this, WrapperActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
Those flags will clear your back stack all the way down to the first instance of whatever Activity you are creating, it will kill it, and then create a new one. This is essentially what A.C.R's example is doing, but it's much more concise.
If this isn't good enough for you, In order to do this properly, it's quite a bit of work, and requires more advanced knowledge of the Android system. You'd want to create a service that's running in the background (will need to be a separate process if you want the application level state killed) that you could startup when you wanted to kill the app, have the app kill itself, or have the service kill the app for you, and then have the service launch an intent that would start your activity/application back up.
Hope this helps! Best of luck!
To restart my app, I'm simple doing this and it's working:
Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
System.exit(0);
If I don't use both flags, it won't work.
(Using Android 11, API 30, Pixel 3 device)
Try the below code for restarting the application.
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Here is what you need to do:
Create a sticky Service
Kill the app with killProcess call from the Service
The sticky Service will then restart, and you can open your app with an getLaunchIntentForPackage intent
I like to use a Handler to do this off the main UI thread:
private void scheduleForceClose() {
final Handler closeAppHandler = new Handler();
closeAppHandler.post(new Runnable() {
#Override public void run() {
prefs.edit().putBoolean(StringConstants.FORCE_CLOSED_APP, true).commit();
Log.i(TAG, "Gonna force kill the app process completely!");
System.exit(0);
android.os.Process.killProcess(android.os.Process.myPid());
}
});
}
private void scheduleForceOpen() {
final Handler openAppHandler = new Handler();
taskOpenApp = new TimerTask() {
#Override public void run() {
openAppHandler.post(new Runnable() {
#SuppressLint("ApplySharedPref") #Override public void run() {
Intent intent = getPackageManager().getLaunchIntentForPackage("com.company.yourpackagename");
// Reset the force-close flag so that the close timer can begin again
prefs.edit().putBoolean(StringConstants.FORCE_CLOSED_APP, false).commit();
startActivity(intent);
}
});
}
};
// Decide whether we already force-closed the app, so that we don't repeat it
boolean alreadyForceClosed = prefs.getBoolean(StringConstants.FORCE_CLOSED_APP, false);
if (alreadyForceClosed) {
Log.i(TAG, "App process has already been killed, so schedule app relaunch.");
Timer timerOpen = new Timer();
timerOpen.schedule(taskOpenApp, 5000 /* reopen the app after 5 sec */);
}
}
No can do. The operating system decides when to kill an application. Your app can come back to life whether it was truly dead or just hidden.
This is inconvenient, but the platform works like that. You can produce the same user-facing effect by managing your activities, which you can kill and restore.
There might be a more official way to do this, but here's how I would accomplish this.
For example I am going to pretend there are only two Activities, the one you're currently in (I'll call it FirstActivity), and another "helper" Activity (I'll call SecondActivity).
In the first one (the one you want to restart it from), you would have a button that initiates the restart of the app.
restartButton.setOnClickListener(new OnClickListener(){
#Override
onClick(View v){
//when clicked it starts the helper activity and closes the one you're in
startActivity(new Intent(this, SecondActivity.class));
finish(); //or you could use FirstActivity.onDestroy(); if you want it completely dead
}
});
Second Activity: It's entire purpose is so you can basically restart your app from your app (close everything else and then restart it in this)
Class SecondActivity extends Activity{
#Override
onCreate(Bundle savedInstanceState){
...
//it restarts the old activity so it's new and ends this one
startActivity(new Intent(this, FirstActivity.class));
finish(); //or you could use SecondActivity.onDestroy(); if you want it
}
}
That will completely restart the first activity. I'm not sure if it will be as thorough as you wish, but there really isn't another way to do this sort of thing AFAIK.
There are a lot of topics on this post. But i couldn't find a solution to my problem.
Let me describe my activity stack first.
SplashScreen->A->Login->Home.
What i would like to achieve is , when i click on back button after logging in to Home, i should come out of the application and go to Home if i use my application again. For this i am assuming i should clear the activity stack before Home, after i login. I would also like to preserve the activity stack if the user hasn't logged in yet.
I want this to work on or after 2.1
What i have tried already.
using finish() in Login Activity , before calling startActivity on Home. This will redirect me to A , if i use back button on Home.
All variations of FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TOP . Nothing worked, when i use back button, i am redirected to login screen.
Any suggestions or simple solution to achieve this?
using finish() in Login Activity , before calling startActivity on Home. This will redirect me to A , if i use back button on Home.
ok so use finish on all the activities that you want them to be popped before calling startActivity
go to Home if i use my application again
Simply save your login parameters in SharedPreference and from A startActivity Home directly if login successful.
You can also try to make use of BroadcastReceiver aswell if you want to try that route.
In your "SplashScreen" and "A" activities, in the onCreate method you can create and register and IntentFilter and a BroadcastReceiver like so:
Assuming you have a global variable called broadcastReceiver
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("ACTION_LOGIN");
this.broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
registerReceiver(broadcastReceiver, intentFilter);
Also don't forget to unregister your receiver in the onDestroy method (this is to prevent memory leaks in the program):
#Override
protected void onDestroy() {
unregisterReceiver(this.broadcastReceiver);
super.onDestroy();
}
Now in your "Login" activity, once the user has successfully logged in, you can broadcast a message to all the registered receivers, which will finish those activites in the back stack:
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("ACTION_LOGIN");
sendBroadcast(broadcastIntent);
Your SplashScreen and A activities will now be finished.
I have an app which I want to open, use, and then at the push of a button close. My question is do I need to keep singleton data of the application status in order to make this happen? I mean if I go with the solution of doing finish on resume() that means that I should need to keep a global data that each activity looks at to close out? This is a fine, albeit awkward way to close an app, but I'll go with it unless I hear another way soon.
Thanks.
PS please do not respond with android will decide when and what to do with your app. I'm sorry but I know my user does want to see this app again after they click Finish! And in the end that's what matters and they are not at all interested in what android needs to do with the app nor should they be.
Maybe you can use System.exit(0) if you want to kill your app.
As came up from comments, you need to do it from the main activity. My way (though there might be a cleaner way) is to add a static handler in the main activity:
static Handler handler = new Handler() {
#Override
public void handleMessage(Message msg)
{
System.exit(2);
}
}
and a static method:
static public Handler getExitHandler()
{
return handler;
}
and in each class I obtain this handler and send it a message when I want to exit:
MyMainActivity.getExitHandler().sendEmptyMessage(0);
again, not so clean, but the same about System.exit(2);
Well, there is a reason why everyone says that, and is the same as "you don't close a web page". I don't know what your users might expect, but this is the way Android/iOS works.
I've used, for something like what you want to do, the flag ACTIVITY_CLEAR_TOP (you set the flag on the intent to open the activity which contains the close button), so in this way the activity stack is deleted, only the current activity remaning: so when you do finish(); the app "closes".
Intent intent = new Intent(this, Some.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
You could pop up a dialogue that informs the user: "the app will close in x seconds" and start a timer that calls finish() on the activity when it ends.
i have a button to close my app with this code:
finish();
the problem is that this button doesn't exit of my app... it simply closes the current intent ant returns to the previous intent (window) of my app....
how i can do a real exit/close button?
i tryed with this:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
but it doesn't works, because when i turn back into my app, the app comes in the last opened window, and not in the first window of the app, how i can do that? i need that when i re-open my app it starts on the first window of my app
If you really want your app to die. You could initiate each intent with startActivityForResult(). then before each finish() set the result to send back. in each parent activity you can override onActivityResult() to test whether the result received means the application needs to end. if so you can call another set result and finish(). repeat this in all activities and you will find that your application terminates entirely.
Incidentally I'm writing this from memory. function names may not be exact.
Hope that helps.
p.s. re-read your requirements. you can always stop the finish loop at your first activity.
I would do it this way:
I would define my initial activity (i.e. MainMenu) with a Launch Mode of singleTop
I would then invoke my MainMenu from the activity that is going to close the application.
startActivity(new Intent(this, MainMenu.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).putExtra("closeProgram", true);
Then override the onNewIntent in the MainMenu activity; check for the extra boolean of "closeProgram", if the value is true, then do a finish();
Haven't tried it but I think it should work.
I recommend you read this: http://blog.radioactiveyak.com/2010/05/when-to-include-exit-button-in-android.html
Chances are, you don't want an exit button. Perhaps a logout button, but that's it.
finish() closes activity (this is what you call intent, but it's not correct), not application. Application can not be finished at all (only forcefully killed like task killers do). You should design your activity stack in such a way that it will suit your needs. May be you should look at stack rearrangement examples in ApiDemos.
you can try this: System.exit(0);