Intent from notification does not have extras
AndroidAndroid IntentAndroid NotificationsAndroid Problem Overview
This seem to be a common problem and I went through all the related questions I could find already: https://stackoverflow.com/questions/5628382/activity-isnt-picking-up-new-intent, https://stackoverflow.com/questions/10456655/why-extra-data-integer-is-not-sent-in-android-notification-intent, https://stackoverflow.com/questions/7370324/notification-passes-old-intent-extras/9330144, https://stackoverflow.com/questions/7098893/cant-put-extras-for-an-intent-in-notification, https://stackoverflow.com/questions/3009059/android-pending-intent-notification-problem; but still cannot figure this out.
Problem is the same. I set a notification with a PendingIntent carrying some extra information and I don't get it on the other side.
Here is the code for generating the notification:
Notification notification = new Notification(R.drawable.icon, getResources().getString(R.string.notification_ticker), System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONLY_ALERT_ONCE;
Intent start_test = new Intent(this, MyActivity.class);
start_test.putExtra("start_test", true);
start_test.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pi = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), start_test, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, getResources().getString(R.string.notification_title), getResources().getString(R.string.notification_content, expired), pi);
nm.notify(NOTIFICATION_ID, notification);
And on the other side:
boolean start_test=getIntent().getBooleanExtra("start_test", false);
The bundle is actually not there (getExtras() returns null).
I tried the different flags for PendingIntent.getActivity
(FLAG_UPDATE_CURRENT
, FLAG_CANCEL_CURRENT
, FLAG_ONE_SHOT
), none of those helped.
As shown in the code, I use getCurrentMillis to make sure the requestID changes....
Also found that in MyActivity, onCreate
and onNewIntent
are not getting called. only onResume
is. Even though the FLAG_ACTIVITY_NEW_TASK
is set... ?
Am I missing something very simple ?
Android Solutions
Solution 1 - Android
Setting FLAG_ACTIVITY_NEW_TASK
for the notification Intent will cause the following:
-
If the activity is not already running in a task, a new task will be started and the Intent will be delivered to the activity in
onCreate()
-
However, if the activity is already running in a task, that task will be brought to the foreground. That's all. The Intent will not be delivered and
onNewIntent()
will not be called.
If you want the Intent to actually be delivered you need to specify:
start_test.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
It makes no difference whether the launchMode
of the activity is singleTop
or not, you still must specify Intent.FLAG_ACTIVITY_SINGLE_TOP
in the Intent.
Note: If the activity is already running in a task and the activity is not on top of the activity stack in that task, the task will be brought to the foreground. That's all. The Intent will not be delivered. The only way to make this happen would be to add Intent.FLAG_ACTIVITY_CLEAR_TOP
to the other 2 flags, but this may not be what you want to happen (depends on your specific scenario).
See my (still) open issue on Google code at http://code.google.com/p/android/issues/detail?id=17137
Solution 2 - Android
I just added the PendingIntent.FLAG_UPDATE_CURRENT
flag to my pending intent, and it started working for me (skipped all flags for Intent).
Example Code:
PendingIntent pendIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Solution 3 - Android
-
If not needed then avoid setting your activity in manifest as a single task. omit this line or change it to singleTop if you can:
android:launchMode="singleTask”
-
If you must have a single task then in pending intent set flags to : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK And PendingIntent.FLAG_CANCEL_CURRENT.
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_CLEAR_TASK); pIntent = PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_CANCEL_CURRENT );
-
If you have a single task - Reset your extras in your activity inside onNewIntent() by setIntent(intent);
protected void onNewIntent(Intent intent) { setIntent(intent); ... }
Solution 4 - Android
You can send extras in intent following way
PendingIntent contentIntent ;
Intent intent = new Intent(this,TestActivity.class);
intent.putExtra("extra","Test");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ArticleDetailedActivity.class);
contentIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
To Get Intent extra value in Test Activity class you need to write following code :
Intent intent = getIntent();
String extra = intent.getStringExtra("extra") ;
Solution 5 - Android
Simpler approach: the real problem is that the Intent, being to the same target, gets replaced. I've solved this by just created a new service, a "NotificationDismissalService". The only intent going to that service is the setDeleteIntent item. Because it's a unique service, the parameters do not get replaced. The body of NotificationDismissalService (and it would really be one such dismissal service per unique intent type) is a simple implementation of "onStartCommand" that sends an intent to the preferred service (reading/writing the correct parameters). Because that's an actual send of a service, without a pendingintent in between, it works just fine.
Solution 6 - Android
When app is not running or is in background and user clicks on Notification in tray, you can get Intent extra and check the keys:
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("RC","MainActivity.onCreate() called");
if (getIntent().getExtras() != null){
Bundle extra = getIntent().getExtras();
Log.d("RC", "MainActivity.onCreate() : keys count = " + extra.keySet().size());
for ( String key : extra.keySet()) {
Log.d("RC","MainActivity.onCreate() : key = " + key + " = " + extra.getString(key));
}
}
}
This will show:
D/RC: MainActivity.onCreate() called
D/RC: MainActivity.onCreate() : keys count = 8
D/RC: MainActivity.onCreate() : key = google.delivered_priority = high
D/RC: MainActivity.onCreate() : key = google.sent_time = null
D/RC: MainActivity.onCreate() : key = google.ttl = null
D/RC: MainActivity.onCreate() : key = google.original_priority = high
D/RC: MainActivity.onCreate() : key = from = 631131412302
D/RC: MainActivity.onCreate() : key = google.message_id = 0:1627370460932539%952b1da9952b1da9
D/RC: MainActivity.onCreate() : key = gcm.n.analytics_data = null
D/RC: MainActivity.onCreate() : key = collapse_key = com.reflectcode.demo.cloudmessaging
Solution 7 - Android
I have used something like this
Intent myIntent = new Intent(context, DoSomething.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
context,
0,
myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);
Check out the full example here