Force application to restart on first activity

Android

Android Problem Overview


For an unknown reason, I can't get my application leaving properly so that when I push the home button and the app icon again, I resume where I was in the app. I would like to force the application to restart on the first Activity.

I suppose this has something to do with onDestroy() or maybe onPause() but I don't know what to do.

Android Solutions


Solution 1 - Android

Here is an example to restart your app in a generic way by using the PackageManager:

Intent i = getBaseContext().getPackageManager()
             .getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

Solution 2 - Android

The solution marked as 'answer' works but has one disadvantage that was critical for me. With FLAG_ACTIVITY_CLEAR_TOP your target activity will get onCreate called before your old activity stack receives onDestroy. While I have been clearing some necessary stuff in onDestroy I had to workaroud.

This is the solution that worked for me:

public static void restart(Context context, int delay) {
    if (delay == 0) {
        delay = 1;
    }
    Log.e("", "restarting app");
    Intent restartIntent = context.getPackageManager()
            .getLaunchIntentForPackage(context.getPackageName() );
    PendingIntent intent = PendingIntent.getActivity(
            context, 0,
            restartIntent, Intent.FLAG_ACTIVITY_CLEAR_TOP);
    AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    manager.set(AlarmManager.RTC, System.currentTimeMillis() + delay, intent);
    System.exit(2);
}

The idea is to fire a PendingIntent via AlarmManager that will be invoked a bit later, giving old activity stack some time to clear up.

Solution 3 - Android

if you want to always start at the root you want to set android:clearTaskOnLaunch to true on your root activity

Solution 4 - Android

android:clearTaskOnLaunch="true"
android:launchMode="singleTask"

Use this property in manifest file in starting class (first activity).

Solution 5 - Android

Does FLAG_ACTIVITY_CLEAR_TOP do what you need to do?

Intent i = new Intent(getBaseContext(), YourActivity.class);
			i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			startActivity(i);

Solution 6 - Android

FLAG_ACTIVITY_CLEAR_TOP didn't work for me because I had to support 2.3.3. My first solution was:

Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
    intent.addFlags(Build.VERSION.SDK_INT >= 11 ? Intent.FLAG_ACTIVITY_CLEAR_TASK : Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);

This almost works, but not quite.

Since I have a base Activity, I added a kill broadcast that closes all my running activities.

public abstract class BaseActivity extends AppCompatActivity {

    private static final String ACTION_KILL = "BaseActivity.action.kill";
    private static final IntentFilter FILTER_KILL;
    static {
        FILTER_KILL = new IntentFilter();
        FILTER_KILL.addAction(ACTION_KILL);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        registerReceiver(killReceiver, FILTER_KILL);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(killReceiver);
    }

    private final BroadcastReceiver killReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    };

    public void killApp(){
        sendBroadcast(new Intent(ACTION_KILL));
    }
}

All of my activities extend from this class, so

((BaseActivity)getActivity()).killApp();
startActivity(new Intent(getActivity(), StartActivity.class));

restarts the app. Tested on genymotion v10, v16, v21 and Nexus 5 with v22.

Edit: this does not remove an activity if it is destroyed at the time of sending the intent. I'm still looking for a solution.

Solution 7 - Android

The following code is work for me, it can restart full app perfectly!

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);

Solution 8 - Android

Marc's answer works great, except in my case where my main activity has a launchMode of singleTop. Once I run this intent and then navigate to new Activities and press the home button on the device, then launch my app again from the app icon, I end up creating a new instance of the main Activity, with my previous activity on the back stack.

According to this question it's because the intents don't match. Looking at adb dumpsys activity, I see that from my standard android launcher, the package is null, whereas when I do as Marc suggests, the intent package is the name of my package. This difference causes them to not match and to start a new instance when the app icon is tapped again and the main activity isn't on top.

However, on other launchers, like on Kindle, the package is set on the launcher intent, so I needed a generic way to handle launchers. I added static methods like such:

static boolean mIsLaunchIntentPackageNull = true;    

public static boolean isLaunchIntent(Intent i) {
    if (Intent.ACTION_MAIN.equals(i.getAction()) && i.getCategories() != null
            && i.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
        return true;
    }

    return false;
}

public static void handleLaunchIntent(Intent i) {
    if (isLaunchIntent(i)) {
        if (i.getPackage() != null) {
            mIsLaunchIntentPackageNull = false;
        }
        else {
            mIsLaunchIntentPackageNull = true;
        }
    }
}

with a go home mechanism like this:

    Intent intentHome = appContext.getPackageManager()
            .getLaunchIntentForPackage( appContext.getPackageName());
    intentHome.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    // need to match launcher intent exactly to avoid duplicate activities in stack
    if (mIsLaunchIntentPackageNull) {
        intentHome.setPackage(null);
    }
    appContext.startActivity(intentHome);

then in the main activity defined in my manifest, I added this line:

public void onCreate(Bundle savedInstanceState) {
    [class from above].handleLaunchIntent(getIntent());

this works for me on kindle and my phone, and lets me properly reset the app w/o adding another instance of the main activity.

Solution 9 - Android

You can use Jake Wharton's lib ProcessPhoenix in order to restart your application process.

Solution 10 - Android

this worked for me:

Intent mStartActivity = new Intent(ctx.getApplicationContext(), ActivityMain.class);
   

    mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    mStartActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        mStartActivity.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK

   int mPendingIntentId = 123456;


    PendingIntent mPendingIntent = PendingIntent.getActivity(ctx, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, mPendingIntent);

    ActivityManager manager =  (ActivityManager) ctx.getApplicationContext().getSystemService(ctx.getApplicationContext().ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> activityes = ((ActivityManager)manager).getRunningAppProcesses();




    ((Activity)ctx).moveTaskToBack(true);
    manager.killBackgroundProcesses("com.yourpackagename");
    System.exit(0);

Solution 11 - Android

You should checkout this question:

https://stackoverflow.com/questions/46070938/restarting-android-app-programmatically

The way to do it is:

private void restartApp() 
{
   Intent intent = new Intent(getApplicationContext(), YourStarterActivity.class);
   int mPendingIntentId = MAGICAL_NUMBER;
   PendingIntent mPendingIntent = PendingIntent.getActivity(getApplicationContext(), mPendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
   AlarmManager mgr = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
   mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
   System.exit(0);
}

Solution 12 - Android

After hard thinking and testing I finally got the right way of calling my activity to recreate when the app is left with the home button :

android:clearTaskOnLaunch

in the manifest

@Override
public void onRestart(){
    onCreate();
}

That does the trick...(better than when it is put in onResume which is called each time you launch the app, even the first time, causing a double display)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSephyView Question on Stackoverflow
Solution 1 - AndroidMarcView Answer on Stackoverflow
Solution 2 - AndroidAAverinView Answer on Stackoverflow
Solution 3 - AndroidjqpubliqView Answer on Stackoverflow
Solution 4 - AndroidRishi GautamView Answer on Stackoverflow
Solution 5 - AndroidBertView Answer on Stackoverflow
Solution 6 - AndroidDariusLView Answer on Stackoverflow
Solution 7 - AndroidBeatrice LinView Answer on Stackoverflow
Solution 8 - AndroidMike VenzkeView Answer on Stackoverflow
Solution 9 - AndroidmolView Answer on Stackoverflow
Solution 10 - AndroidVeljko MilisavljevićView Answer on Stackoverflow
Solution 11 - AndroidYonatan NirView Answer on Stackoverflow
Solution 12 - AndroidSephyView Answer on Stackoverflow