0

I am creating application that shows notification icon in statusbar. When user opens statusbar and taps on the icon the application should be launched.

I am searching a way to avoid re-creation of application during this launch. I have created test application and add log messages to handlers onCreate, onRestart, onResume, onStop and onDestroy. Log messages demonstrates the problem:

  1. User starts application - onCreate, onResume
  2. User presses HOME button - onStop
  3. User opens list of applications and starts application again - onRestart, onResume
  4. User presses HOME button - onStop
  5. User opens list of recent applications and selects the application - onRestart, onResume
  6. User presses HOME button - onStop
  7. User opens statusbar and taps on the application icon - onDestroy, onCreate, onResume.

Step 7 has a different behavior then 3) and 5) - there is onDestroy here. In other words, instance of the application is recreated. Is it possible to avoid this recreation?

This is a code of my test activity:

public class MainActivity extends Activity {
    private final String LOG_TAG = "com.example.notificationtest";

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showNotification(this);
        Log.d(LOG_TAG, "NotificationTest: OnCreate");
    }

    @Override protected void onRestart() {
        super.onRestart();
        Log.d(LOG_TAG, "NotificationTest: OnRestart");
    }

    @Override protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "NotificationTest: OnResume");
    }

    @Override protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "NotificationTest: OnDestroy");
    }

    @Override protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG, "NotificationTest: OnStop");
    }


    private static final int NOTIF_ID = 91371;

    public static void showNotification(Context context) {
        final Intent result_intent = new Intent(context, MainActivity.class);
        result_intent.setAction(Intent.ACTION_MAIN);
        result_intent.addCategory(Intent.CATEGORY_LAUNCHER);
        //result_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //result_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        //result_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);                

        TaskStackBuilder stack_builder = TaskStackBuilder.create(context);
        stack_builder.addParentStack(MainActivity.class);
        stack_builder.addNextIntent(result_intent);

        PendingIntent pending_intent = stack_builder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

        android.support.v4.app.NotificationCompat.Builder builder = new android.support.v4.app.NotificationCompat.Builder(context);

        Resources res = context.getResources();
        builder.setContentIntent(pending_intent)
            .setSmallIcon(R.drawable.ic_launcher)
            .setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher))
            .setTicker("test")
            .setWhen(System.currentTimeMillis())
            .setAutoCancel(false)
            .setContentTitle("title")
            .setContentInfo("cinfo")
            .setContentText("ctext");
        Notification n = builder.build();
        n.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;   

        NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
        nm.notify(NOTIF_ID, n);     
    }
}

There are some flags, that can be set to result_intent, like FLAG_ACTIVITY_CLEAR_TOP, FLAG_ACTIVITY_CLEAR_TASK and FLAG_ACTIVITY_NEW_TASK. They allow to specify that activity should be restarted on launch (with activity launch mode "singleTop", "singleTask" etc). But what flag should be set to avoid restarting? Probably I should configure pending_intent in some way?

Any help will be very appreciated.

Solved

Thanks a lot for the answers, the problem is solved.

Same problem is described here. I have checked test project from that topic and found difference with my code. To solve the problem my code should be changed in follow way:

final Intent result_intent = new Intent(context, MainActivity.class);
//result_intent.setAction(Intent.ACTION_MAIN); // (1)
//result_intent.addCategory(Intent.CATEGORY_LAUNCHER); // (2)
result_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

another set of flags works too:

result_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 

main point was to comment lines (1) and (2)

Community
  • 1
  • 1
dvpublic
  • 657
  • 8
  • 8
  • are `onSaveInstanceState()` and `onRestoreInstance()` being called? A better option than trying to work around the activity lifecycle might be to restore essential running data via those methods, which will make the data you store persistent across the onDestroy. – Alex Gittemeier Mar 05 '13 at 06:48
  • 1
    Check out this SO post: http://stackoverflow.com/questions/3305088/how-to-make-notification-intent-resume-rather-than-making-a-new-intent – appsroxcom Mar 05 '13 at 07:00
  • Yes, onSaveInstanceState() and onRestoreInstance() are called. I dont' try to workaround lifecycle. The origin of the problem is described here: http://forum.unity3d.com/threads/172700-open-Unity-application-using-notification-in-statusbar?p=1181292#post1181292 – dvpublic Mar 05 '13 at 09:59
  • to appsroxcom: thanks a lot! the problem was in exceeded addCategory(Intent.CATEGORY_LAUNCHER) and setAction(Intent.ACTION_MAIN) – dvpublic Mar 05 '13 at 10:28

1 Answers1

0

add this:

result_intent..setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                                    | Intent.FLAG_ACTIVITY_NEW_TASK);

It works like

Intent.FLAG_ACTIVITY_REORDER_TO_FRONT

also maintains activity stack