338

Firstly, I know that one should not really kill/restart an application on Android. In my use case, I want to factory-reset my application in a specific case where a server sends a piece of specific information to the client.

The user can only be logged in on the server with ONE instance of the application (i.e. multiple devices are not allowed). If another instance gets that "logged-in"-lock then all other instances of that user have to delete their data (factory-reset), to maintain consistency.

It is possible to forcibly get the lock because the user might delete the app and reinstall it which would result in a different instance-id and the user would not be able to free the lock anymore. Therefore it is possible to forcibly get the lock.

Because of that force-possibility, we need to always check in a concrete instance that it has the lock. That is done on (almost) each request to the server. The server might send a "wrong-lock-id". If that is detected, the client application must delete everything.


That was the use-case.

I have an Activity A that starts the Login Activity L or the app's main Activity B depending on a sharedPrefs value. After starting L or B it closes itself so that only L or B is running. So in the case that the user is logged in already B is running now.

B starts C. C calls startService for the IntentService D. That results in this stack:

(A) > B > C > D

From the onHandleIntent method of D, an event is sent to a ResultReceiver R.

R now handles that event by providing the user a dialog where he can choose to factory-reset the application (delete the database, sharedPrefs, etc.)

After the factory-reset I want to restart the application (to close all activities) and only start A again which then launches the login Activity L and finishes itself:

(A) > L

The Dialog's onClick-method looks like this:

@Override
public void onClick(DialogInterface dialog, int which) {

    // Will call onCancelListener
    MyApplication.factoryReset(); // (Deletes the database, clears sharedPrefs, etc.)
    Intent i = new Intent(MyApp.getContext(), A.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MyApp.getContext().startActivity(i);
}

And that's the MyApp class:

public class MyApp extends Application {
    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }

    public static Context getContext() {
        return context;
    }

    public static void factoryReset() {
        // ...
    }
}

The problem is if I use the FLAG_ACTIVITY_NEW_TASK the Activities B and C are still running. If I hit the back button on the login Activity I see C, but I want to go back to the home screen.

If I do not set the FLAG_ACTIVITY_NEW_TASK I get the error:

07-07 12:27:12.272: ERROR/AndroidRuntime(9512): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

I cannot use the Activities' Context, because the ServiceIntent D might also be called from a background task which is started by the AlarmManager.

So how could I solve this to the activity stack becoming (A) > L?

Stuck
  • 11,225
  • 11
  • 59
  • 104

32 Answers32

318

You can use PendingIntent to setup launching your start activity in the future and then close your application

Intent mStartActivity = new Intent(context, StartActivity.class);
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId,    mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
System.exit(0);
Tim Kist
  • 1,164
  • 1
  • 14
  • 38
Oleg Koshkin
  • 3,483
  • 2
  • 15
  • 6
  • 2
    This one properly restarts the app, including reloading NDK libraries which was important for me. – Matthew Mitchell Sep 27 '13 at 21:42
  • 6
    This worked perfectly for me! I just used android.os.Process.killProcess(android.os.Process.myPid()); over System.exit(); – FDIM Feb 23 '14 at 19:15
  • 30
    On 4.3 and 4.4 devices (All I've tested) this seems to kill the current activity and then launch a new one over the top of the old one. I'm 2 activies deep (main -> prefs). Pressing back takes me to the old app, one screen back. – Mgamerz Apr 11 '14 at 02:37
  • 2
    You should correctly close activity stack trough OnActivityResult before executing this code – Oleg Koshkin Apr 11 '14 at 08:38
  • 6
    In my case, System.exit(0) didn't work as a transaction was rolling back. Instead I used activity.finish(); and it works just fine. – unify May 14 '14 at 03:24
  • Thanks for sharing at first. However with some mPendingIntentId values, application quits, and not restarts – support_ms Sep 24 '14 at 10:00
  • 1
    Doesn't work an BlackBerry devices. The app exits, but it will not be restarted. Got two different user reports (one of them uses Android runtime 4.3). – stefan222 Nov 05 '14 at 15:32
  • @support_ms Did you find safe pending intent id instead of listed above ? – Oleg Koshkin Nov 13 '14 at 13:45
  • 1
    @stefan222 Have you tried finish app with activity finish as unify suggested? Or have you tried to set diffrent tending intend id based on support_ms comment ? – Oleg Koshkin Nov 13 '14 at 13:47
  • @OlegKoshkin Of course I found. However, I think that, id's which I use, might not work on some android devices. – support_ms Nov 14 '14 at 04:16
  • @OlegKoshkin I used the original code from your post. Problem is that I have no device for testing, so I cannot dig deeper into the problem :-( – stefan222 Nov 14 '14 at 06:18
  • 1
    System.exit(0) is not recomonded – Shirish Herwade Mar 24 '15 at 08:32
  • 1
    To anybody getting an error with StartActivity, change it to whatever the name of your main activity is (probably MainActivity) – Pikamander2 Oct 02 '15 at 02:54
  • 1
    In my opinion, System.exit(0) is a VERY BAD behaviour. Because you don't know the states of all the threads. Assume one of them is doing I/O operations, it can lead to corrupted file issue. – Qylin Jan 14 '16 at 11:05
  • 11
    @Qulin, Guys! You cant be serious! This example is more like direction than real life example. You have to modify this snippet with starting activity name, intent id, and exit mechanics whatever you with. Do not blindly copy paste it. – Oleg Koshkin Jan 15 '16 at 07:37
  • 1
    using `Runtime.getRuntime().exit(0);` instead of `System.exit(0);` is recommended as you can not expect status of current threads running under your app – blueware Aug 22 '16 at 12:00
  • The perfect answer – Happy Oct 18 '16 at 05:23
  • Sometimes the app exited but not restarted. – chengsam Nov 30 '16 at 06:35
  • worked for me every time when I replaced `AlarmManager.RTC` with `AlarmManager.RTC_WAKE_UP` – Alexey Andronov Oct 24 '17 at 09:01
  • 2
    `activity.finishAffinity()` may be what you're after here - this will close all the activities related to the app, not just the current activity. – Michael Berry Nov 23 '17 at 22:38
  • It's not starting from the first activity. I just have given a breakpoint in the `onCreate()` of launcher activity. After running the above code, it's not `onCreate()`. Can anyone tell me how to achieve this? – Shambhu Apr 27 '18 at 06:58
  • How it works? For example `mPendingIntentId` - documentation at https://developer.android.com/reference/android/app/PendingIntent.html describes it as "Private request code" - is it actually OK to use easy to guess value like here? – reducing activity Jul 04 '19 at 06:52
  • 36
    This doesn't work anymore with Android Q due to new restrictions to background activities https://developer.android.com/preview/privacy/background-activity-starts – Marco Righini Aug 20 '19 at 21:17
  • 3
    @MarcoRighini They should be adding new capabilities at the same time as removing old ones. Otherwise the platform becomes less usable... I needed to use this as a workaround for another bug. Now I have one less option. – gregn3 May 07 '20 at 01:19
  • Using oneplus device, I had encounterred anr after restart. – Hunter Jan 19 '21 at 09:44
127

You can simply call:

public static void triggerRebirth(Context context, Intent nextIntent) {
    Intent intent = new Intent(context, YourClass.class);
    intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
    intent.putExtra(KEY_RESTART_INTENT, nextIntent);
    context.startActivity(intent);
    if (context instanceof Activity) {
      ((Activity) context).finish();
    }

    Runtime.getRuntime().exit(0);
}

Which is used in the ProcessPhoenix library


As an alternative:

Here's a bit improved version of @Oleg Koshkin answer.

If you really want to restart your activity including a kill of the current process, try following code. Place it in a HelperClass or where you need it.

public static void doRestart(Context c) {
        try {
            //check if the context is given
            if (c != null) {
                //fetch the packagemanager so we can get the default launch activity 
                // (you can replace this intent with any other activity if you want
                PackageManager pm = c.getPackageManager();
                //check if we got the PackageManager
                if (pm != null) {
                    //create the intent with the default start activity for your application
                    Intent mStartActivity = pm.getLaunchIntentForPackage(
                            c.getPackageName()
                    );
                    if (mStartActivity != null) {
                        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        //create a pending intent so the application is restarted after System.exit(0) was called. 
                        // We use an AlarmManager to call this intent in 100ms
                        int mPendingIntentId = 223344;
                        PendingIntent mPendingIntent = PendingIntent
                                .getActivity(c, mPendingIntentId, mStartActivity,
                                        PendingIntent.FLAG_CANCEL_CURRENT);
                        AlarmManager mgr = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
                        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
                        //kill the application
                        System.exit(0);
                    } else {
                        Log.e(TAG, "Was not able to restart application, mStartActivity null");
                    }
                } else {
                    Log.e(TAG, "Was not able to restart application, PM null");
                }
            } else {
                Log.e(TAG, "Was not able to restart application, Context null");
            }
        } catch (Exception ex) {
            Log.e(TAG, "Was not able to restart application");
        }
    }

This will also reinitialize jni classes and all static instances.

mikepenz
  • 12,708
  • 14
  • 77
  • 117
  • 1
    This solution is nice, but it will delay for few seconds till it restarts your application, even if you decreased the 100 Millis. However, this library [ProcessPhoenix](https://github.com/JakeWharton/ProcessPhoenix) by Jack Wharton does it better and quickly, but its not worth adding library for only this function inside the app. – blueware Aug 22 '16 at 12:22
  • @blueware I have updated my answer and added the code which is used inside ProcessPhonix – mikepenz Aug 22 '16 at 12:44
  • @mikepenz, this guy "Ilya_Gazman" did much better and without using such a library. – blueware Aug 22 '16 at 12:52
  • 3
    @blueware - Except Ilya's solution will not restart the process, so static data or loaded NDK libraries will not be correctly reinitialized. – Ted Hopp Sep 14 '16 at 08:03
  • Some Huawei and Samsung devices have restrictions on `AlarmManager` and mis behave if using this solution, Any better approach? – blueware Feb 18 '17 at 20:33
  • @mikepenz I have posted slightly modified solution of Ilya_Gazman https://stackoverflow.com/a/46848226/1635488 – android_dev Oct 20 '17 at 11:41
  • This is the best answer, all others have not satisifed me. – Ganesh Chowdhary Sadanala Oct 03 '19 at 08:40
  • From far best answer i agree – Zhar Jan 05 '20 at 01:07
  • 1
    What if my app shutsdown and doesn't restart? Various ways I've tried and the app doesn't start again. Sometimes it does, but it shutsdown again in a fraction of second. And I can't see any errors in Android Studio's logcat... Any ideas what might be the problem? – Edw590 Oct 01 '20 at 15:31
  • Does the `Activity.finish` call actually do anything? It seems like lifecycle methods (e.g. `onStop`) don't actually run because the process is killed too early. I had to use `Handler.post` to get around this. – gardenapple Sep 13 '21 at 21:38
126

I have slightly modified Ilya_Gazman answer to use new APIs (IntentCompat is deprecated starting API 26). Runtime.getRuntime().exit(0) seems to be better than System.exit(0).

 public static void triggerRebirth(Context context) {
    PackageManager packageManager = context.getPackageManager();
    Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
    ComponentName componentName = intent.getComponent();
    Intent mainIntent = Intent.makeRestartActivityTask(componentName);
    context.startActivity(mainIntent);
    Runtime.getRuntime().exit(0);
}
android_dev
  • 3,886
  • 1
  • 33
  • 52
  • 17
    Directly from [the docs](https://developer.android.com/reference/java/lang/System.html#exit%28int%29): "_The call_ `System.exit(n)` _is effectively equivalent to the call:_ `Runtime.getRuntime().exit(n)`". Internally, `System.exit()` just turns around and calls `Runtime.getRuntime().exit()`. There is nothing "better" about one or the other (unless one is concerned about how much typing one does or about one extra layer of method calls). – Ted Hopp Oct 20 '17 at 15:25
  • where and when call above method? – Makvin Aug 11 '18 at 05:29
  • 1
    @Makvin you decide where to call it. My case was restart app after language change. – android_dev Aug 11 '18 at 11:58
  • @TedHopp been commenting on every answer as "not good", do you have any feasible solution? Not being sarcastic, really need to recreate an application without any trace left behind; from statics variables to class instances. – Farid Jan 16 '19 at 07:37
  • 1
    @FARID - Any of the solutions that involve calling `Runtime.getRuntime().exit(0)` (or `System.exit(0)`) will probably work. Some of my "not good" comments are for answers (such as the one by [Ilya Gazman](https://stackoverflow.com/a/35984131/535871) that have since been edited to incorporate such a call. – Ted Hopp Jan 16 '19 at 16:24
  • You could add `Context context=getApplicationContext();` to the start to get your current context. – rubo77 May 24 '19 at 10:24
  • @rubo77 you can't always refer to getApplicationContext() from anywhere (e.g. suppose this method is in Utils class). Also it's a good practice to pass a method all the params that it needs. – android_dev May 26 '19 at 11:00
  • It's crashing on some devices... App has to be restarted manually. – Ronny Shibley Jun 05 '20 at 07:30
  • @RonnyShibley Can you please specify, which devices did you try? – Vít Kapitola Oct 27 '20 at 11:38
  • @VítKapitola I tried on many OnePlus 7 prod. It was crashing. But could be something else in the creation of the activity. – Ronny Shibley Oct 28 '20 at 14:48
  • This is the Kotlin version: fun triggerRebirth(context: Context) { val packageManager: PackageManager = context.packageManager val intent: Intent? = packageManager.getLaunchIntentForPackage(context.packageName) val componentName: ComponentName? = intent!!.component val mainIntent = Intent.makeRestartActivityTask(componentName) context.startActivity(mainIntent) Runtime.getRuntime().exit(0) } – Hossein Yousefpour May 18 '21 at 06:26
  • 1
    Good answer, because this solution works perfectly on newest API versions. – Akito Nov 03 '21 at 21:33
  • nice, saved my time – Sunil Nov 23 '21 at 18:32
  • Perfect, tested on API 26 tablet that is connected to a robot. Thank you!! – Mohamad Ghaith Alzin Aug 12 '22 at 09:28
  • How to use this code with a delay? – Venkata krishna Sundararajan Jul 13 '23 at 19:00
90

Jake Wharton recently published his ProcessPhoenix library, which does this in a reliable way. You basically only have to call:

ProcessPhoenix.triggerRebirth(context);

The library will automatically finish the calling activity, kill the application process and restart the default application activity afterwards.

TBieniek
  • 4,858
  • 2
  • 24
  • 29
48

IntentCompat.makeMainSelectorActivity - Last tested on 11/2020

The app will be restored with the launcher activity and the old process will be killed.

Works from Api 15.

public static void restart(Context context){
    Intent mainIntent = IntentCompat.makeMainSelectorActivity(Intent.ACTION_MAIN, Intent.CATEGORY_LAUNCHER);
    mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.getApplicationContext().startActivity(mainIntent);
    System.exit(0);
}
Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216
  • 9
    This relaunches the task, but it does not restart the process, or even the `Application` object. Therefore any `static` data, data initialized during creation of the `Application`, or jni classes remain in their current state and are not reinitialized. – Ted Hopp Mar 14 '16 at 15:29
  • 2
    @TedHopp Oh I missed that part. I added System.exit(0); But I am not sure 100% that it will work. I will test it latter on – Ilya Gazman Mar 14 '16 at 15:33
  • 2
    The best solution without using open source library to do it. Hands up and thanks for providing this answer, +1 – blueware Aug 22 '16 at 12:39
  • 4
    Unfortunately, [`IntentCompat.makeRestartActivityTask` is now deprecated](https://developer.android.com/sdk/support_api_diff/26.0.0-alpha1/changes/android.support.v4.content.IntentCompat.html). If you [inspect the source code](https://android.googlesource.com/platform/frameworks/support/+/android-support-lib-19.1.0/v4/java/android/support/v4/content/IntentCompat.java#57), it's as simple as simply adding the flags `Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK`. – Paul Lammertsma Dec 06 '17 at 13:34
  • IntentCompat.makeRestartActivityTask removed – luckyhandler Apr 26 '18 at 10:07
  • There's `Intent.makeRestartActivityTask()` which is not deprecated – Erik Ghonyan Jan 07 '19 at 10:48
  • You could add `Context context=getApplicationContext();` to the start to get your current context. – rubo77 May 24 '19 at 10:23
  • 2
    see answer below for a full up-to-date function: https://stackoverflow.com/a/46848226/1069083 – rubo77 May 24 '19 at 10:23
36

My solution doesn't restart the process/application. It only lets the app "restart" the home activity (and dismiss all other activities). It looks like a restart to users, but the process is the same. I think in some cases people want to achieve this effect, so I just leave it here FYI.

public void restart(){
    Intent intent = new Intent(this, YourHomeActivity.class);
    this.startActivity(intent);
    this.finishAffinity();
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
yongsunCN
  • 736
  • 7
  • 18
34

The only code that did not trigger "Your app has closed unexpectedly" is as follows. It's also non-deprecated code that doesn't require an external library. It also doesn't require a timer.

public static void triggerRebirth(Context context, Class myClass) {
    Intent intent = new Intent(context, myClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    context.startActivity(intent);
    Runtime.getRuntime().exit(0);
}
Haskell McRavin
  • 620
  • 5
  • 19
30

I've found that this works on API 29 and later - for the purpose of killing and restarting the app as if the user had launched it when it wasn't running.

public void restartApplication(final @NonNull Activity activity) {
   // Systems at 29/Q and later don't allow relaunch, but System.exit(0) on
   // all supported systems will relaunch ... but by killing the process, then
   // restarting the process with the back stack intact. We must make sure that
   // the launch activity is the only thing in the back stack before exiting.
   final PackageManager pm = activity.getPackageManager();
   final Intent intent = pm.getLaunchIntentForPackage(activity.getPackageName());
   activity.finishAffinity(); // Finishes all activities.
   activity.startActivity(intent);    // Start the launch activity
   System.exit(0);    // System finishes and automatically relaunches us.
}

That was done when the launcher activity in the app has this:

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

I've seen comments claiming that a category of DEFAULT is needed, but I haven't found that to be the case. I have confirmed that the Application object in my app is re-created, so I believe that the process really has been killed and restarted.

The only purpose for which I use this is to restart the app after the user has enabled or disabled crash reporting for Firebase Crashlytics. According to their docs, the app has to be restarted (process killed and re-created) for that change to take effect.

Mark Peters
  • 445
  • 6
  • 10
28

There is a really nice trick. My problem was that some really old C++ jni library leaked resources. At some point, it stopped functioning. The user tried to exit the app and launch it again -- with no result, because finishing an activity is not the same as finishing (or killing) the process. (By the way, the user could go to the list of the running applications and stop it from there -- this would work, but the users just do not know how to terminate applications.)

If you want to observe the effect of this feature, add a static variable to your activity and increment it each, say, button press. If you exit the application activity and then invoke the application again, this static variable will keep its value. (If the application really was exited, the variable would be assigned the initial value.)

(And I have to comment on why I did not want to fix the bug instead. The library was written decades ago and leaked resources ever since. The management believes it always worked. The cost of providing a fix instead of a workaround... I think, you get the idea.)

Now, how could I reset a jni shared (a.k.a. dynamic, .so) library to the initial state? I chose to restart application as a new process.

The trick is that System.exit() closes the current activity and Android recreates the application with one activity less.

So the code is:

/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity {
    // Do not forget to add it to AndroidManifest.xml
    // <activity android:name="your.package.name.MagicAppRestart"/>
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        System.exit(0);
    }
    public static void doRestart(Activity anyActivity) {
        anyActivity.startActivity(new Intent(anyActivity.getApplicationContext(), MagicAppRestart.class));
    }
}

The calling activity just executes the code MagicAppRestart.doRestart(this);, the calling activity's onPause() is executed, and then the process is re-created. And do not forget to mention this activity in AndroidManifest.xml

The advantage of this method is that there is no delays.

UPD: it worked in Android 2.x, but in Android 4 something has changed.

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • 3
    i used activity.startActivity(i); System.exit(0); genius solution – max4ever Nov 27 '12 at 11:36
  • 5
    This solution closes the app for me, but it doesn't restart. At least on Android 4.3. – Kirill Rakhman Oct 26 '13 at 20:07
  • 1
    On samsung galaxy mega android 4.2.2 It causes infinite loop of restart. So the app wont start again. – Gunhan Nov 26 '13 at 12:05
  • @Gunhan 1) what happens if you replace `System.exit(0)` by `android.os.Process.killProcess(android.os.Process.myPid());`? 2) an infinite loop most likely means that they do not remove the topmost activity when they restart an app. In principle, you can add a static boolean variable, set it to true before invoking the restart activity, and after the restart it will be false. Thus the activity can find out whether or not the restart has already happened (and if it has happened, just _finish()_). OTOH, your report means that the trick does not work identically on all devices. – 18446744073709551615 Nov 26 '13 at 13:12
  • @Gunham If you are starting the same activity that is causing the restart then it will be infinite loop on any device. – Lukas Hanacek Jul 08 '14 at 12:09
16

Ok, I refactored my app and I will not finish A automatically. I let this run always and finish it through the onActivityResult event. In this way I can use the FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_NEW_TASK flags to get what I want:

public class A extends Activity {

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        finish();
    }

    protected void onResume() {
        super.onResume();
        // ...
        if (loggedIn) {
            startActivityForResult(new Intent(this, MainActivity.class), 0);
        } else {
            startActivityForResult(new Intent(this, LoginActivity.class), 0);
        }
    }
}

and in the ResultReceiver

@Override
public void onClick(DialogInterface dialog, int which) {
    MyApp.factoryReset();
    Intent i = new Intent(MyApp.getContext(), A.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MyApp.getContext().startActivity(i);
}

Thanks anyway!

Stuck
  • 11,225
  • 11
  • 59
  • 104
  • 25
    This will **not** restart the application, only re-create the classes. Thus, any static variables within the classes will retain values from previous runs. – Brian White Dec 17 '13 at 01:25
13
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Nirav Ranpara
  • 13,753
  • 3
  • 39
  • 54
  • 27
    This will **not** restart the application, only re-create the classes. Thus, any static variables within the classes will retain values from previous runs. – Brian White Dec 17 '13 at 01:24
9

The best way to fully restart an app is to relaunch it, not just to jump to an activity with FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_NEW_TASK. So my solution is to do it from your app or even from another app, the only condition is to know the app package name (example: 'com.example.myProject')

 public static void forceRunApp(Context context, String packageApp){
    Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageApp);
    launchIntent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(launchIntent);
}

Example of usage restart or launch appA from appB:

forceRunApp(mContext, "com.example.myProject.appA");

You can check if the app is running:

 public static boolean isAppRunning(Context context, String packageApp){
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
    for (int i = 0; i < procInfos.size(); i++) {
        if (procInfos.get(i).processName.equals(packageApp)) {
           return true;
        }
    }
    return false;
}

Note: I know this answer is a bit out of topic, but it can be really helpful for somebody.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Choletski
  • 7,074
  • 6
  • 43
  • 64
7

Still Working Now

 public void resetApplication() {
    Intent resetApplicationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
    if (resetApplicationIntent != null) {
        resetApplicationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    }
    context.startActivity(resetApplicationIntent);
    ((Activity) context).overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
Kumar Santanu
  • 603
  • 1
  • 7
  • 14
  • 4
    That restarts the activity (and the task stack), but doesn't restart the entire app. Specifically, if you have an Application subclass, or if you have static classes with state data, those objects will not be re-initialized. – Ted Hopp Sep 30 '21 at 12:36
6

My best way to restart application is to use finishAffinity();
Since, finishAffinity(); can be used on JELLY BEAN versions only, so we can use ActivityCompat.finishAffinity(YourCurrentActivity.this); for lower versions.

Then use Intent to launch first activity, so the code will look like this:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    finishAffinity();
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
} else {
    ActivityCompat.finishAffinity(YourCurrentActivity.this);
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
}

Hope it helps.

Moinkhan
  • 12,732
  • 5
  • 48
  • 65
  • 6
    This ends all activities in the current task, but it does not restart the process, or even recreate the Application object. Therefore any static data, data initialized during creation of the Application, or by jni classes, remain in their current state and are not reinitialized. – Ted Hopp Feb 26 '19 at 15:40
3

This code passed the Android 8-13 test

public void restartApp() {
    Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );  
    startActivity(Intent.makeRestartActivityTask(i.getComponent()));  
    Runtime.getRuntime().exit(0);
}
2

Kotlin version of this answer:

val intent = Intent(this, YourActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent)
Runtime.getRuntime().exit(0)
bayram.cicek
  • 193
  • 2
  • 9
2

Try using FLAG_ACTIVITY_CLEAR_TASK

Pedro Loureiro
  • 11,436
  • 2
  • 31
  • 37
1

Use:

navigateUpTo(new Intent(this, MainActivity.class));

It works starting from API level 16 (4.1), I believe.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1

You can use startInstrumentation method of Activity. You need implement empty Instrumentation and pointed in manifest. After that you can call this method for restart your app. Like this:

try {           
    InstrumentationInfo info = getPackageManager().queryInstrumentation(getPackageName(), 0).get(0);
    ComponentName component = new ComponentName(this, Class.forName(info.name));
    startInstrumentation(component, null, null);
} catch (Throwable e) {             
    new RuntimeException("Failed restart with Instrumentation", e);
}

I get Instrumentation class name dynamically but you can hardcode it. Some like this:

try {           
    startInstrumentation(new ComponentName(this, RebootInstrumentation.class), null, null); 
} catch (Throwable e) {             
    new RuntimeException("Failed restart with Instrumentation", e);
}

Call startInstrumentation make reload of your app. Read description of this method. But it can be not safe if acting like kill app.

V-rund Puro-hit
  • 5,518
  • 9
  • 31
  • 50
Enyby
  • 4,162
  • 2
  • 33
  • 42
1

Directly start the initial screen with FLAG_ACTIVITY_CLEAR_TASK and FLAG_ACTIVITY_NEW_TASK.

Yijun Li
  • 57
  • 5
1

The application I'm working on has to give the user the possibility to choose which fragments to display (fragments are dynamically changed at run-time). The best solution for me was to restart completely the application.

So I tried plenty of solutions and none of them has worked for me, but this:

final Intent mStartActivity = new Intent(SettingsActivity.this, Splash.class);
final int mPendingIntentId = 123456;
final PendingIntent mPendingIntent = PendingIntent.getActivity(SettingsActivity.this, mPendingIntentId, mStartActivity,
                    PendingIntent.FLAG_CANCEL_CURRENT);
final AlarmManager mgr = (AlarmManager) SettingsActivity.this.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
this.finishAffinity(); //notice here
Runtime.getRuntime().exit(0); //notice here

Hoping that is going to help someone else!

hzitoun
  • 5,492
  • 1
  • 36
  • 43
  • Good thought to move to Splash. We can move directly to splash screen by using a normal intent too right. – Reejesh Jun 16 '23 at 07:17
1
fun triggerRestart(context: Activity) {
    val intent = Intent(context, MainActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    context.startActivity(intent)
    if (context is Activity) {
        (context as Activity).finish()
    }
    Runtime.getRuntime().exit(0)
}
1

I got this way.

Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( 
 getBaseContext().getPackageName() );
 i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 startActivity(i);
 finish();
Muhaiminur Rahman
  • 3,066
  • 20
  • 27
0

I had to add a Handler to delay the exit:

 mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 200, mPendingIntent);
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Runtime.getRuntime().exit(0);
            }
        }, 100);
0

try this:

Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
veeson
  • 195
  • 2
  • 6
  • 3
    As with every other answer here already suggesting the same thing, this will not restart the application, only re-create the classes. Thus, any static data within the process will not be reset. – Ted Hopp Sep 29 '17 at 02:32
0

With the Process Phoenix library. The Activity you want to relaunch is named "A".

Java flavor

// Java
public void restart(){
    ProcessPhoenix.triggerRebirth(context);
}

Kotlin flavor

// kotlin
fun restart() {
    ProcessPhoenix.triggerRebirth(context)
}
Raymond Chenon
  • 11,482
  • 15
  • 77
  • 110
  • This has the unfortunate result of making your debugger disconnect. – S.V. Feb 26 '20 at 16:17
  • 3
    @S.V. - AFAIK, ANY solution that kills the process (in order to restart in a clean state), will disconnect the debugger. Consider that "symptom" a sign that this approach is truly giving you a fresh start. – ToolmakerSteve Aug 05 '21 at 19:00
0

Apply delay restart

startDelay Startup delay (in milliseconds)

 public static void reStartApp(Context context, long startDelay) {
    //Obtain the startup Intent of the application with the package name of the application
    Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
    PendingIntent restartIntent = PendingIntent.getActivity(context.getApplicationContext(), -1, intent, PendingIntent.FLAG_CANCEL_CURRENT);

    AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    if (mgr != null) {
        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + startDelay, restartIntent);
    }
}
Richard Kamere
  • 749
  • 12
  • 10
0
val i = baseContext.packageManager.getLaunchIntentForPackage(baseContext.packageName)
i!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(i)
finish()
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Osama Ibrahim
  • 995
  • 10
  • 13
-1

Mikepenz's Alternative Answer needed some changes in my case. https://stackoverflow.com/a/22345538/12021422 Major Credits to Mikepenz's Answer which I could modify.

Here is the Plug and Play static function that worked for me.

Just pass the Context of Application and this function will handle the restart.

    public static void doRestart(Context c) {
        try {
            // check if the context is given
            if (c != null) {
                // fetch the package manager so we can get the default launch activity
                // (you can replace this intent with any other activity if you want
                PackageManager pm = c.getPackageManager();
                // check if we got the PackageManager
                if (pm != null) {
                    // create the intent with the default start activity for your application
                    Intent mStartActivity = pm.getLaunchIntentForPackage(c.getPackageName());
                    if (mStartActivity != null) {
                        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        
                        c.getApplicationContext().startActivity(mStartActivity);
                        // kill the application
                        System.exit(0);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("restart", "Could not Restart");
        }
    }
Rahul Shyokand
  • 1,255
  • 10
  • 17
-3

in MainActivity call restartActivity Method:

public static void restartActivity(Activity mActivity) {
    Intent mIntent = mActivity.getIntent();
    mActivity.finish();
    mActivity.startActivity(mIntent);
}
farhad.kargaran
  • 2,233
  • 1
  • 24
  • 30
-3

hey bro if you want to restart your app with the click of a button so write this code and remember to change reset with the name of your button and if you will run this in the snippet it will not work because I have chosen javascript and it is java language

reset.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            finish();

                            startActivity(getIntent());
                        }
                    });
  • 2
    That restarts the activity, but doesn't restart the entire app. Specifically, if you have an Application subclass, or if you have static classes that have state data, those objects will not be re-initialized. – Ted Hopp Jul 11 '21 at 01:33
-6

You can restart your current activity like this:

Fragment :

activity?.recreate()

Activity :

recreate()