Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Activity re-creation intent extras are null

My app contains a MainActivity and uses full screen fragments to display content. I'm trying to achieve the following during app re-creation (When the app has been in background for a long time, gets killed by the system and then it's brought to the foreground)

  1. If the user is manually re-creating the app (by selecting the app from the recent's apps list), the Main Activity should re-create and then the last fragment that was fullscreen should recreate. No problem here, this is the standard behaviour.

  2. If the app is being re-created because the user touched a push notification, The Main Activity should re-create but the last fragment that was in fullscreen should not re-create. Instead a new Fragment should be created and displayed. Why? The push notification contains the info as to what kind of Fragment should be displayed

My approach relies on checking the intent extras that I put when building the notification that starts the Main Activity, That part of the code is not shown for brevity's sake but I always put some extras in the intent, always

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    //debug
    System.out.println("MainActivity.onCreate() extras:"+getIntent().getExtras());
    if (savedInstanceState!=null && getIntent().getExtras()!=null){
        //case 2. passing null will prevent Fragment recreation
        super.onCreate(null)
    }
    else{
        //case 1.
        super.onCreate(savedInstanceState)
    }
    ...
}

@Override
public void onResume(){
    //debug
    System.out.println("MainActivity.onResume() extras:"+getIntent().getExtras());
    ...
}

Now, if the app is not running at all and a notification arrives, I get the following output:

MainActivity.onCreate() extras: Bundle[{android:viewHierarchyState=Bundle[mParcelledData....
MainActivity.onResume() extras: Bundle[{android:viewHierarchyState=Bundle[mParcelledData....

When the app is re-created manually by the user I get The following output:

MainActivity.onCreate() extras: null
MainActivity.onResume() extras: null

When the app is re-created by a notification

MainActivity.onCreate() extras: null
MainActivity.onResume() extras: Bundle[{android:viewHierarchyState=Bundle[mParcelledData....

This last case is not what I expected, somehow the notification intent extras are only available after calling super.onCreate()

Any ideas on how to achieve 1. and 2.?

Giant Edit: This is the notification code, as you can see, there is a splash screen activity that relays the intent to the Main Activity

GcmIntentService.java

@Override protected void onHandleIntent(Intent intent) {
    Bundle extras = intent.getExtras();
    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
    String messageType = gcm.getMessageType(intent);
    if (!extras.isEmpty()) {
        if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
            sendNotification(extras.getString(KEY_CATEGORY), extras.getString(KEY_CONTENT));
        }
    }
    GcmBroadcastReceiver.completeWakefulIntent(intent);
}

private void sendNotification(String category, String content) {
    category = evaluateCategory(category);
    mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
    Intent mIntent = new Intent(this, SplashActivity.class);
    mIntent.putExtra(KEY_CATEGORY, Integer.valueOf(category));
    mIntent.putExtra(KEY_NEW, true);
    mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent contentIntent = PendingIntent.getActivity(this, Integer.valueOf(category), mIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                                                .setSmallIcon(R.drawable.logo_actionbar)
                                                //customize notification

    mBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(Integer.valueOf(category), mBuilder.build());

SplashActivity.java

@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent mIntent = getIntent();
    if (mIntent.getExtras()!=null){
        category = mIntent.getExtras().getInt(GcmIntentService.KEY_CATEGORY);
        isNew = mIntent.getExtras().getBoolean(GcmIntentService.KEY_NEW);
    }
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            Intent mainIntent = new Intent(SplashActivity.this, MainActivity.class);
            mainIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_CLEAR_TOP);
            if (category!=null ){
                mainIntent.putExtra(GcmIntentService.KEY_CATEGORY, category);
                mainIntent.putExtra(GcmIntentService.KEY_NEW, isNew);
            }
            startActivity(mainIntent);
            overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
            finish();
        }
    }, SPLASH_DELAY);
}
like image 776
user1736003 Avatar asked Aug 26 '14 23:08

user1736003


1 Answers

What about overriding onNewIntent(Intent intent) method provided by Activity ?

  1. Read savedInstanceState can be null and getIntent() can contain extra with your GCM.

  2. According to Android Developers:

protected void onNewIntent (Intent intent)

This is called for activities that set launchMode to "singleTop" in their package, or if a client used the FLAG_ACTIVITY_SINGLE_TOP flag when calling startActivity(Intent). In either case, when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.

An activity will always be paused before receiving a new intent, so you can count on onResume() being called after this method.

Note that getIntent() still returns the original Intent. You can use setIntent(Intent) to update it to this new Intent.

like image 98
AndroidCoolestRulest Avatar answered Sep 18 '22 14:09

AndroidCoolestRulest