Android: BackStack misbehaves, if application was started from another app

992 views Asked by At

I have an application, which starts with a SplashScreenActivity. Afterwards, a LoginActivity is shown, or if the user is already logged in, a MainActivity is shown. If the application is already running, SplashScreenActivity is dismissed with the following

//SplashScreenActivity
 @Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //Adding this check for following cases
    if (!isTaskRoot())
    {
        String intentAction = getIntent().getAction();
        if (getIntent().hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
            finish();
            return;
        }

        if(getIntent().getCategories().contains(GCMIntentService.INTENT_CATEGORY_GH_NOTIFICATION)){
            finish();
            return;
        }
    }

Problem occurs

If I start the application from another activity like PlayStore, it resumes at the right activity if already running. This is the Intent I'm using to reproduce within a second app

//AnotherApplication.apk
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("my.package.name");
startActivity(launchIntent);

However, this action is somehow breaking the Backstack. Instead of closing the application on backpress in the MainActivity, it restarts the application.

//MainActivity.class
@Override
public void onBackPressed() {
    if (getNavDrawerMain().isDrawerOpen()) {
        getNavDrawerMain().closeDrawer();
    } else {
        closeApp();
    }
}

protected void closeApp() {
    if (doubleBackToExitPressedOnce) {
        //super.onBackPressed();   //i tried both, but behaviour is the same
        finish();
        return;
    }
    this.doubleBackToExitPressedOnce = true;

    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() 
            doubleBackToExitPressedOnce = false;
        }
    }, 500);
}

I used breakpoints and found out that MainActivity:onDestroy() get called, but instead of resuming application to the HomeScreen, it always restarts and I don't know why.

I tried the following: - Used different launchmodes like singleTask and singleInstance, but it didn't make any difference. onNewIntent is called, but if i call finish, HomeActivity restarts - as commeted below, i tried moveTaskToBack(true), but Activity is restaring too (and we really want to close the app instead of moving it to the BackStack)

2

There are 2 answers

5
JohanShogun On

Trying adding this flag to your intent starting your app: RESET_TASK_IF_NEEDED, URL=http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

What it does:

If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task.

You may also use: http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_REORDER_TO_FRONT

What it does:

If set in an Intent passed to Context.startActivity(), this flag will cause the launched activity to be brought to the front of its task's history stack if it is already running.

Which one you use depend on the desired end result.

If you can't control who starts you you need to set or launch mode to single task or single instance.

Described here:

http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en

The interesting part:

singleTask

This mode is quite different from standard and singleTop. An Activity with singleTask launchMode is allowed to have only one instance in the system (a.k.a. Singleton). If there is an existed Activity instance in the system, the whole Task hold the instance would be moved to top while Intent would be delivered through onNewIntent() method. Otherwise, new Activity would be created and placed in the proper Task.

1
Joanmi Bardera On

Try with moveTaskToBack(true); instead of finish(); to close the app. It will then go to OnRestart() and then OnStart()->OnResume() (and won't go to OnCreate).

And make sure you don't have the "Don't keep activities" marked at Developer Options in your Android Settings (destroy every activity as soon as the user leaves it).