Kaloyan Roussev
Kaloyan Roussev

Reputation: 14711

Android: when coming from notification, activities are added on top of already open activities and memory increases

Android: when coming from notification, activities are added on top of already open activities and memory increases. How to clear all the previous activities or even kill the app when notification is tapped?

Here is how I build my notifications:

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)//
            .setContentTitle(notificationTitle)//
            .setContentText(notificationText)//
            .setSmallIcon(R.drawable.app_icon_transparent)//
            .setAutoCancel(true)//
            .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.asd));//

    // Creates an explicit intent for an Activity in your app
    Intent resultIntent = new Intent(context, StarterActivity.class);
    resultIntent.putExtra("comingFromNotification", true);

    // The stack builder object will contain an artificial back stack for
    // the
    // started Activity.
    // This ensures that navigating backward from the Activity leads out of
    // your application to the Home screen.
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    // Adds the back stack for the Intent (but not the Intent itself)
    stackBuilder.addParentStack(StarterActivity.class);
    // Adds the Intent that starts the Activity to the top of the stack
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    mBuilder.setContentIntent(resultPendingIntent);
    NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    // mId allows you to update the notification later on.

    mNotificationManager.notify((int) now.getTimeInMillis(), mBuilder.build());

Now, when the user receives a notification and clicks it, StarterActivity is started. It initiates all the resources the app needs and then starts the main activity.

If the app had been running up to this moment and had been taking up 50 mb of ram, now ram goes up to 65, which means the previous process is not killed and this one starts on top of it.

Question is, how to kill the app if its running in the moment the user clicks the notification?

EDIT: In some similar question I found this

notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_NEW_TASK);

will this help? What do these flags mean?

EDIT2: Nope. those flags didnt help. The application process that has some cached objects in memory still lives and the RAM goes up again.

Upvotes: 1

Views: 1829

Answers (3)

David Wasser
David Wasser

Reputation: 95578

Your architecture doesn't lend itself to solving this problem. As you mentioned in some comments, StarterActivity is your root activity (ie: the one with ACTION=MAIN and CATEGORY=LAUNCHER), but you don't keep it in the activity stack, so you cannot take advantage of FLAG_ACTIVITY_CLEAR_TOP.

To solve your problem you should not call finish() on StarterActivity when it launches MainActivity. This will allow you to use FLAG_ACTIVITY_CLEAR_TOP (with or without FLAG_ACTIVITY_SINGLE_TOP, depending on whether or not you want to use the existing instance of StarterActivity or create a new instance).

Once you've got that working, you now need to deal with the problem of the user pressing BACK in MainActivity and having it return to StarterActivity, which is obviously not what you want. You can solve that in several ways, here are 2 examples:

  1. Add a boolean member variable to StarterActivity. In StarterActivity.onResume() set that variable to true at the very end of the method. At the start of onResume(), check the variable, and if it is true, you can assume that the user has pressed BACK in MainActivity, so you can just call finish().

  2. In MainActivity override onBackPressed() and instead of calling super.onBackPressed(), call startActivity() with an Intent for StarterActivity with an extra named "exit" and FLAG_ACTIVITY_CLEAR_TOP. This will cause a new instance of StarterActivity to be created. In StarterActivity.onCreate(), check the presence of the extra "exit" in the Intent, and if it is there, it means that the user pressed BACK from MainActivity. In this case, you just want to call finish() to end your application. If you use this mechanism, make sure that StarterActivity has standard launchMode in the manifest, not launchMode="singleTop".

Upvotes: 2

Yarh
Yarh

Reputation: 4607

FLAG_ACTIVITY_CLEAR_TOP - Clears intermidiate activities, not every activity e.g:
You have call A > B > C > D >E , then from E you call B. After such call Activities C and D will be removed, activity A will remain. If you have calls A > B > C > E and from E you call activity F, no activity will be purged.

FLAG_ACTIVITY_SINGLE_TOP ensures the top activity is not recreated if it is called again. eg:
you cal A > B > C , then you call B again. After such call B will not be recreated, but Current existent will be called. If you will call A, it will be recreated as it is not on top of stack.

Activity_new_task - is used for complecated back navigation. You can manage several tasks or in other words several histories of activity calls. Creating new task will not erase previos task. Is an absolute requirenment, when starting app with notification, deeplinks or any other "launcher" behaviour. Purifications inside one task will have no effect on another task history

I assume, a propper reset of history after launch will be achived with those 3 flags together: FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |FLAG_ACTIVITY_CLEAR_TASK This shoul, clear task history, close it and create new task. If it does not work try to replace Clear_Task with FLAG_ACTIVITY_RESET_TASK_IF_NEEDED.

Upvotes: 2

Nasir
Nasir

Reputation: 2122

You don't need to kill the app and start it again. Use android:launchMode="singleTop" in your manifest for the activity:

    <activity
        android:name=".StarterActivity"
        android:launchMode="singleTop"/>

This will open the same activity rather than creating a new one.

Upvotes: 1

Related Questions