11

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.

dubmojo
  • 6,660
  • 8
  • 41
  • 68
  • This may be helpful: http://stackoverflow.com/questions/4337819/android-forcing-full-restart-after-an-app-is-killed?rq=1 – Umer Farooq Jul 22 '13 at 18:55
  • You might be aware of "don't keep activities" in developer settings. Might be of help? – Simon Jul 22 '13 at 19:20
  • 1
    Does this answer your question? [Restarting Android app programmatically](https://stackoverflow.com/questions/46070938/restarting-android-app-programmatically) – grebulon Mar 08 '22 at 09:43

7 Answers7

7

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);
Rakesh Salian
  • 159
  • 10
Ramesh Bhati
  • 1,239
  • 16
  • 25
2

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!

spierce7
  • 14,797
  • 13
  • 65
  • 106
2

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)

ddeveloper
  • 53
  • 6
1

Try the below code for restarting the application.

Intent i = getBaseContext().getPackageManager()
             .getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
IamMHussain
  • 716
  • 8
  • 11
  • Would this erase static variables that were defined in the activity? – IgorGanapolsky Jan 03 '18 at 17:27
  • During the run the static variables may be killed if the activity they belong to are not visible, in this case they will have their default values when returning to the activity. – IamMHussain Jan 10 '18 at 12:25
1

Here is what you need to do:

  1. Create a sticky Service
  2. Kill the app with killProcess call from the Service
  3. 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 */);
    }
}
IgorGanapolsky
  • 26,189
  • 23
  • 116
  • 147
0

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.

salezica
  • 74,081
  • 25
  • 105
  • 166
0

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.

anthonycr
  • 4,146
  • 1
  • 28
  • 35