I can find a way to send parameters to my activity from my notification.
I have a service that creates a notification. When the user clicks on the notification I want to open my main activity with some special parameters. E.g an item id, so my activity can load and present a special item detail view. More specific, I'm downloading a file, and when the file is downloaded I want the notification to have an intent that when clicked it opens my activity in a special mode. I have tried to use putExtra on my intent, but cant seem to extract it, so I think I'm doing it wrong.
Code from my service that creates the Notification:
// construct the Notification object.
final Notification notif = new Notification(R.drawable.icon, tickerText, System.currentTimeMillis());
final RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.custom_notification_layout);
contentView.setImageViewResource(R.id.image, R.drawable.icon);
contentView.setTextViewText(R.id.text, tickerText);
contentView.setProgressBar(R.id.progress,100,0, false);
notif.contentView = contentView;
Intent notificationIntent = new Intent(context, Main.class);
notificationIntent.putExtra("item_id", "1001"); // <-- HERE I PUT THE EXTRA VALUE
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notif.contentIntent = contentIntent;
nm.notify(id, notif);
Code from my Activity that tries to fetch the extra parameter from the notification:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Bundle extras = getIntent().getExtras();
if(extras != null){
Log.i( "dd","Extra:" + extras.getString("item_id") );
}
The extras is always null and I never gets anything into my log.
Btw... the onCreate is only run when my activity starts, if my activity is already started I also want to collect the extras and present my activity according to the item_id I receive.
Any ideas?
Take a look at this guide (creating a notification) and to samples ApiDemos "StatusBarNotifications" and "NotificationDisplay".
For managing if the activity is already running you have two ways:
Add FLAG_ACTIVITY_SINGLE_TOP flag to the Intent when launching the activity, and then in the activity class implement onNewIntent(Intent intent) event handler, that way you can access the new intent that was called for the activity (which is not the same as just calling getIntent(), this will always return the first Intent that launched your activity.
Same as number one, but instead of adding a flag to the Intent you must add "singleTop" in your activity AndroidManifest.xml.
If you use intent extras, remeber to call PendingIntent.getActivity() with the flag PendingIntent.FLAG_UPDATE_CURRENT, otherwise the same extras will be reused for every notification.
I had the similar problem my application displays message notifications.
When there are multiple notifications and clicking each notification it displays that notification detail in a view message activity. I solved the problem of same extra parameters is being received in view message intent.
Here is the code which fixed this.
Code for creating the notification Intent.
Intent notificationIntent = new Intent(getApplicationContext(), viewmessage.class);
notificationIntent.putExtra("NotificationMessage", notificationMessage);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(getApplicationContext(),notificationIndex,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.setLatestEventInfo(getApplicationContext(), notificationTitle, notificationMessage, pendingNotificationIntent);
Code for view Message Activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onNewIntent(getIntent());
}
#Override
public void onNewIntent(Intent intent){
Bundle extras = intent.getExtras();
if(extras != null){
if(extras.containsKey("NotificationMessage"))
{
setContentView(R.layout.viewmain);
// extract the extra-data in the Notification
String msg = extras.getString("NotificationMessage");
txtView = (TextView) findViewById(R.id.txtMessage);
txtView.setText(msg);
}
}
}
Maybe a bit late, but:
instead of this:
public void onNewIntent(Intent intent){
Bundle extras = intent.getExtras();
Log.i( "dbg","onNewIntent");
if(extras != null){
Log.i( "dbg", "Extra6 bool: "+ extras.containsKey("net.dbg.android.fjol"));
Log.i( "dbg", "Extra6 val : "+ extras.getString("net.dbg.android.fjol"));
}
mTabsController.setActiveTab(TabsController.TAB_DOWNLOADS);
}
Use this:
Bundle extras = getIntent().getExtras();
if(extras !=null) {
String value = extras.getString("keyName");
}
Encounter same issue here.
I resolve it by using different request code, use same id as notification, while creating PendingIntent. but still don't know why this should be done.
PendingIntent contentIntent = PendingIntent.getActivity(context, **id**, notificationIntent, 0);
notif.contentIntent = contentIntent;
nm.notify(**id**, notif);
After reading some email-lists and other forums i found that the trick seems to add som unique data to the intent.
like this:
Intent notificationIntent = new Intent(Main.this, Main.class);
notificationIntent.putExtra("sport_id", "sport"+id);
notificationIntent.putExtra("game_url", "gameURL"+id);
notificationIntent.setData((Uri.parse("foobar://"+SystemClock.elapsedRealtime())));
I dont understand why this needs to be done, It got something to do with the intent cant be identified only by its extras...
I tried everything but nothing worked.
eventually came up with following solution.
1- in manifest add for the activity
android:launchMode="singleTop"
2- while making pending intent do the following, use bundle instead of directly using intent.putString() or intent.putInt()
Intent notificationIntent = new Intent(getApplicationContext(), CourseActivity.class);
Bundle bundle = new Bundle();
bundle.putString(Constants.EXAM_ID,String.valueOf(lectureDownloadStatus.getExamId()));
bundle.putInt(Constants.COURSE_ID,(int)lectureDownloadStatus.getCourseId());
bundle.putString(Constants.IMAGE_URL,lectureDownloadStatus.getImageUrl());
notificationIntent.putExtras(bundle);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),
new Random().nextInt(), notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
AndroidManifest.xml
Include launchMode="singleTop"
<activity android:name=".MessagesDetailsActivity"
android:launchMode="singleTop"
android:excludeFromRecents="true"
/>
SMSReceiver.java
Set the flags for the Intent and PendingIntent
Intent intent = new Intent(context, MessagesDetailsActivity.class);
intent.putExtra("smsMsg", smsObject.getMsg());
intent.putExtra("smsAddress", smsObject.getAddress());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(context, notification_id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
MessageDetailsActivity.java
onResume() - gets called everytime, load the extras.
Intent intent = getIntent();
String extraAddress = intent.getStringExtra("smsAddress");
String extraBody = intent.getStringExtra("smsMsg");
Hope it helps, it was based on other answers here on stackoverflow, but this is the most updated that worked for me.
It's easy,this is my solution using objects!
My POJO
public class Person implements Serializable{
private String name;
private int age;
//get & set
}
Method Notification
Person person = new Person();
person.setName("david hackro");
person.setAge(10);
Intent notificationIntent = new Intent(this, Person.class);
notificationIntent.putExtra("person",person);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.notification_icon)
.setAutoCancel(true)
.setColor(getResources().getColor(R.color.ColorTipografiaAdeudos))
.setPriority(2)
.setLargeIcon(bm)
.setTicker(fotomulta.getTitle())
.setContentText(fotomulta.getMessage())
.setContentIntent(PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.setWhen(System.currentTimeMillis())
.setContentTitle(fotomulta.getTicketText())
.setDefaults(Notification.DEFAULT_ALL);
New Activity
private Person person;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification_push);
person = (Person) getIntent().getSerializableExtra("person");
}
Good Luck!!
In your notification implementation, use a code like this:
NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
...
Intent intent = new Intent(this, ExampleActivity.class);
intent.putExtra("EXTRA_KEY", "value");
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
nBuilder.setContentIntent(pendingIntent);
...
To Get Intent extra values in the ExampleActivity, use the following code:
...
Intent intent = getIntent();
if(intent!=null) {
String extraKey = intent.getStringExtra("EXTRA_KEY");
}
...
VERY IMPORTANT NOTE: the Intent::putExtra() method is an Overloaded one. To get the extra key, you need to use Intent::get[Type]Extra() method.
Note: NOTIFICATION_ID and NOTIFICATION_CHANNEL_ID are an constants declared in ExampleActivity
After doing some search i got solution from android developer guide
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") ;
Please use as PendingIntent while showing notification than it will be resolved.
PendingIntent intent = PendingIntent.getActivity(this, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Add PendingIntent.FLAG_UPDATE_CURRENT as last field.
G'day,
I too can say that I tried everything mentioned in these posts and a few more from elsewhere.
The #1 problem for me was that the new Intent always had a null bundle.
My issue was in focusing too much on the details of "have I included .this or .that".
My solution was in taking a step back from the detail and looking at the overall structure of the notification. When I did that I managed to place the key parts of the code in the correct sequence.
So, if you're having similar issues check for:
1. Intent notificationIntent = new Intent(MainActivity.this, NotificationActivity.class);
2a. Bundle bundle = new Bundle();
//I like specifying the data type much better. eg bundle.putInt
2b. notificationIntent.putExtras(bundle);
3. PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this, WIZARD_NOTIFICATION_ID, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
4. NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
5. NotificationCompat.Builder nBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notify)
.setContentTitle(title)
.setContentText(content)
.setContentIntent(contentIntent)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setAutoCancel(false)//false is standard. true == automatically removes the notification when the user taps it.
.setColor(getResources().getColor(R.color.colorPrimary))
.setCategory(Notification.CATEGORY_REMINDER)
.setPriority(Notification.PRIORITY_HIGH)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
notificationManager.notify(WIZARD_NOTIFICATION_ID, nBuilder.build());
With this sequence I get a valid bundle.
If you use
android:taskAffinity="myApp.widget.notify.activity"
android:excludeFromRecents="true"
in your AndroidManifest.xml file for the Activity to launch, you have to use the following in your intent:
Intent notificationClick = new Intent(context, NotifyActivity.class);
Bundle bdl = new Bundle();
bdl.putSerializable(NotifyActivity.Bundle_myItem, myItem);
notificationClick.putExtras(bdl);
notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));
notificationClick.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); // schließt tasks der app und startet einen seperaten neuen
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(NotifyActivity.class);
stackBuilder.addNextIntent(notificationClick);
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(notificationPendingIntent);
Important is to set unique data e.g. using an unique id like:
notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));
Related
I am seriously confused now, I have been reading several SE examples and they all seem to be doing slightly different things.
What i want to do: Is have a single Activity called NotificationActivity, when I click on a notification it must open that activity and provide the activity with a DeviceId. I don't want to override or update any pending activities. Each activity should be its own intent.
There should only be once instance of NotificationActivity.
here is the code I have so far:
MyGcmListenerService:
Intent intent = new Intent(this, NotificationActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
//ADD My Extras
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_ID, content.DeviceId);
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_TYPE_ID, content.DeviceTypeId);
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_NAME, content.DeviceName);
//
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(content.DeviceName)
.setContentText("Notification")
.setAutoCancel(true)
.setSound(ingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setGroup("Mi:" + content.DeviceId)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NotificationID++, notificationBuilder.build());
and my NotificationActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification);
deviceId = getIntent().getExtras().getLong(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_ID, -1);
deviceName = getIntent().getExtras().getString(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_NAME, "");
deviceTypeId = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_TYPE_ID, 0);
What am I missing here/ I think I am getting mixed up with all the different flags and launcher types.
If there is already an NotificationActivty in memory, I want to close it and open a new one with the latest intent. If there are 3 notifications on the users phones, and they click on all three. it must open the NotificationActivty for the last clicked Notification.
There must be an issue with my pending intent?
In NotificationActivity, you collect int or long value using following code i.e.
notificationID = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, 0);
then please pass a proper value with putExtra() i.e. if collect int then pass Integer.parseInt(content.DeviceId) or collect long then pass Long.parseLong(content.DeviceId)
hope it's helpful to you
In Notification class add this line
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, NotificationID);
In NotificationActivity
notificationID = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, 0);
I am trying to create a notification that when clicked will open an external app. I've seen the documentation for creating notifications and for sending the user to another app. But I can't seem to figure out how to combine the two. The problem is that the advised way to launch an app from a notification, is to creating the pending intent like this:
Intent intent = new Intent(this, MyActivity.class);
TaskStackBuilder stackBuidler = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MyActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
But to launch an external app, you have to create an implicit intent like this:
String uri = ...
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
As far as I can tell, there is no way to create the TaskStackBuilder with this kind of intent, because addParentStack() will only take an Activity, a Class, or a ComponentName.
I guess the question boils down to... is it possible to create a intent that is both pending and implicit?
The only workaround I can think of right now is to create an Activity in my app that does nothing but launch the external app.
I did try creating the intent from the URI then doing the following, but nothing happens when you click the notification:
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Well, a lot later, I think I have the solution for you.
For all the other guys who are searching for an answer to launching an external app from your own custom notification.
Here it is:
public void createMyNotification(String titl, String titlcont, String conti){
Context context = getApplicationContext();
PackageManager pm = context.getPackageManager();
Intent LaunchIntent = null;
String apppack = "com.mycompany.appack.apname.app";
String name = "";
try {
if (pm != null) {
ApplicationInfo app = context.getPackageManager().getApplicationInfo(apppack, 0);
name = (String) pm.getApplicationLabel(app);
LaunchIntent = pm.getLaunchIntentForPackage(apppack);
}
Toast.makeText(context,"Found it:" + name,Toast.LENGTH_SHORT).show();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Intent intent = LaunchIntent; // new Intent();
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
Notification noti = new Notification.Builder(this)
.setTicker(titl)
.setContentTitle(titlcont)
.setContentText(conti)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent).getNotification();
noti.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, noti);
}
This does not use an additional Activity to launch the external app.
If you know packageName what you want start it, You can get Intent for startActivity.
Read this link start application knowing package name
I don't know if this is the best approach, but this is the solution that ended up working:
Create the notification
//Create the pending intent
Intent intent = new Intent(context, MyActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MyActivity.class);
stackBuilder.addNextIntent(intent);
PendingIndent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
//Create the notification builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle("Notification Title")
.setContentText("Hello world!")
.setContentIntent(pendingIntent); //Attach the pending intent to launch when notification is clicked
//Send the notification
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(mId, builder.build());
MyActivity.java
public class MyActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Create implicit intent - see http://developer.android.com/training/basics/intents/sending.html
String uri = "...";
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
}
I'd still be interested to know if there's a way to bypass having an additional Activity that does nothing but launch an implicit intent.
from Android Development, i implement a simple notification by the sample code, but in my app, i don't want to new intent and create the activity again, i just want to back to my last activity(it's a mediaplayer UI). if i use the sample code, it will create a new activity by
Intent resultIntent = new Intent(this, ResultActivity.class);
i comment relative code about new intent and got a notification, but didn't have idea how to back to my last activity...
back to my app from long press home key and touch my app is OK.
what i want is just like this behavior.
bleow is the sample code from Android Development, i comment the new intent portion.
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");
/*Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ResultActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);*/
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(mId, mBuilder.build());
[UPDATE]
i thought i need to set flag for intent and properity for activity.
therefore, for the activity i want to back to i set
android:launchMode="singleInstance"
and because, i don't want a new activity from intent, i just want my last activity, so i add
Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
from documentation i got that using Pendingintent.contentIntent it must include the FLAG_ACTIVITY_NEW_TASK flag and When using this flag, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in. so i also add
Intent.FLAG_ACTIVITY_NEW_TASK
but from logCat, i still saw that when i touch the notification for back to activity, the pendingintent still called onCreate() function rather than just show the last activity which still "alive".
If you want to call the Activity from background try this:
Intent intent = new Intent(this, YourLauncherActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, 0);
mBuilder.setContentIntent(pendingIntent);
If you click the Notification while on Homescreen the last shown Activity of your App will be get to the foreground without starting it new. If the Activity was killed by the system you will get a new Activity.
I have used PendingIntent.getActivities instead of getActivity. This is working well in my project.
Intent backIntent = new Intent(this, HomeActivity.class);
backIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent notificationIntent = new Intent(this, NextActivity.class);
final PendingIntent pendingIntent = PendingIntent.getActivities(this, 1,
new Intent[] {backIntent, notificationIntent}, PendingIntent.FLAG_ONE_SHOT);
For me, this worked :
.setContentIntent(
PendingIntent.getActivity(
context,
0,
new Intent(context, YOUR_MAIN.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP ),PendingIntent.FLAG_ONE_SHOT))
FLAG_ONE_SHOT : DO NOT CREATE TWICE (associated with
Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
In SingleTop mode, I use this method without define explicitly the root activity class:
Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER)
.setComponent(getPackageManager().getLaunchIntentForPackage(getPackageName()).getComponent());
and this to resume last activity from notification:
builder.setContentIntent(PendingIntent.getActivity(context, 0, intent, 0));
or this to resume last activity from a service:
try {
PendingIntent.getActivity(this, 0, intent, 0).send();
} catch (CanceledException e) {
e.printStackTrace();
}
Code hear
Intent resultIntent = new
Intent(getApplicationContext(),MainActivity.class);
resultIntent.putExtra("splash",2);
resultIntent.putExtra("message","test");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntentWithParentStack(resultIntent);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent notifyPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationCompatBuilder.setContentIntent(notifyPendingIntent);
Intent intent = this.getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
String extraValue = extras.getString("notificationType");
if(extraValue !=null){
int value = Integer.parseInt(extraValue);
if (value == 1) {
intent = new Intent(SplashActivity.this,MainActivity.class);
intent.putExtra("splash",value);
intent.putExtra("message", "fromsplash");
startActivity(intent);
finish();
} else
if (value == 2){
intent = new Intent(SplashActivity.this,MainActivity.class);
intent.putExtra("swip","2");
intent.putExtra("message", "test");
startActivity(intent);
finish();
}
}
}
}
My MainActicity starts RefreshService with a Intent which has a boolean extra called isNextWeek.
My RefreshService makes a Notification which starts my MainActivity when the user clicks on it.
this looks like this:
Log.d("Refresh", "RefreshService got: isNextWeek: " + String.valueOf(isNextWeek));
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.putExtra(MainActivity.IS_NEXT_WEEK, isNextWeek);
Log.d("Refresh", "RefreshService put in Intent: isNextWeek: " + String.valueOf(notificationIntent.getBooleanExtra(MainActivity.IS_NEXT_WEEK,false)));
pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
builder = new NotificationCompat.Builder(this).setContentTitle("Title").setContentText("ContentText").setSmallIcon(R.drawable.ic_notification).setContentIntent(pendingIntent);
notification = builder.build();
// Hide the notification after its selected
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(NOTIFICATION_REFRESH, notification);
As you can see the notificationIntent should have the booleanextra IS_NEXT_WEEK with the value of isNextWeek which is put in the PendingIntent.
When I click now this Notification I always get false as value of isNextWeek
This is the way I get the value in the MainActivity:
isNextWeek = getIntent().getBooleanExtra(IS_NEXT_WEEK, false);
Log:
08-04 00:19:32.500 13367-13367/de.MayerhoferSimon.Vertretungsplan D/Refresh: MainActivity sent: isNextWeek: true
08-04 00:19:32.510 13367-13573/de.MayerhoferSimon.Vertretungsplan D/Refresh: RefreshService got: isNextWeek: true
08-04 00:19:32.510 13367-13573/de.MayerhoferSimon.Vertretungsplan D/Refresh: RefreshService put in Intent: isNextWeek: true
08-04 00:19:41.990 13367-13367/de.MayerhoferSimon.Vertretungsplan D/Refresh: MainActivity.onCreate got: isNextWeek: false
When I directly start the MainActivity with an Intent with the ìsNextValue` like this:
Intent i = new Intent(this, MainActivity.class);
i.putExtra(IS_NEXT_WEEK, isNextWeek);
finish();
startActivity(i);
everything works fine and I get true when isNextWeek is true.
What do I make wrong that there is always a false value?
UPDATE
this solves the problem:
https://stackoverflow.com/a/18049676/2180161
Quote:
My suspicion is that, since the only thing changing in the Intent is
the extras, the PendingIntent.getActivity(...) factory method is
simply re-using the old intent as an optimization.
In RefreshService, try:
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
See:
http://developer.android.com/reference/android/app/PendingIntent.html#FLAG_CANCEL_CURRENT
UPDATE 2
See answer below why it is better to use PendingIntent.FLAG_UPDATE_CURRENT.
Using PendingIntent.FLAG_CANCEL_CURRENT not a good solution because of inefficient use of memory. Instead use PendingIntent.FLAG_UPDATE_CURRENT.
Use also Intent.FLAG_ACTIVITY_SINGLE_TOP (the activity will not be launched if it is already running at the top of the history stack).
Intent resultIntent = new Intent(this, FragmentPagerSupportActivity.class).
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
resultIntent.putExtra(FragmentPagerSupportActivity.PAGE_NUMBER_KEY, pageNumber);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
Then:
#Override
protected void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
int startPageNumber;
if ( savedInstanceState != null)
{
startPageNumber = savedInstanceState.getInt(PAGE_NUMBER_KEY);
//so on
It should work now.
If you still have not expected behaviour, try to implement void onNewIntent(Intent intent) event handler, that way you can access the new intent that was called for the activity (which is not the same as just calling getIntent(), this will always return the first Intent that launched your activity.
#Override
protected void onNewIntent(Intent intent) {
int startPageNumber;
if (intent != null) {
startPageNumber = intent.getExtras().getInt(PAGE_NUMBER_KEY);
} else {
startPageNumber = 0;
}
}
I think you need to update the Intent when you receive a new one by overriding onNewIntent(Intent) in your Activity. Add the following to your Activity:
#Override
public void onNewIntent(Intent newIntent) {
this.setIntent(newIntent);
// Now getIntent() returns the updated Intent
isNextWeek = getIntent().getBooleanExtra(IS_NEXT_WEEK, false);
}
Edit:
This is needed only if your Activity has already been started when the intent is received. If your activity is started (and not just resumed) by the intent, then the problem is elsewhere and my suggestion may not fix it.
Following code should work:-
int icon = R.drawable.icon;
String message = "hello";
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.putExtra("isNexWeek", true);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, pIntent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
In MainActivity onCreate:
if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("isNextWeek")) {
boolean isNextWeek = getIntent().getExtras().getBoolean("isNextWeek");
}
So the actual reason is that the PendingIntent will cache the previous intent if the intents only differ in their extras. In my situation no combination of PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_CANCEL_CURRENT solves this as either the old intent will be replaced or the new one will stay the same as the initial one.
You need to ensure that Android cannot cache the Intents behind the PendingIntent. The solution for me is to make them differ in their data attribute.
so in the original posters code you would need to ensure that the data attribute is unique per each combination of extras that you are attaching.
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.putExtra(MainActivity.IS_NEXT_WEEK, isNextWeek);
notificationIntent.setData(Uri.parse("myapp://nextWeek/" + (isNextWeek ? "1" : "0"))
Alternatively you could probably also just add a uuid to the data uri (however, if you have lots and lots of notifications, it might be nice to cache them
i developed an basic notification example and tried to catch which notification clicked. But i couldnt.
I put an arraylist my notificaiton and pass it to reciever activity by putting extras, then try to catch but no way !
Are there anyway to catch which one cliked ?
You can pass a Bundle along with PendingIntent to the next Activity.
Bundle bundle = new Bundle();
bundle.putString("Any String");
NotificationManager notifManager = (NotificationManager) this.getSystemService(this.NOTIFICATION_SERVICE);
int uniqueInteger = //create a unique Integer
int icon = R.drawable.ic_launcher;
NotificationCompat2.Builder mNotification = new NotificationCompat2.Builder(this).setSmallIcon(icon)
.setContentTitle(contentTitle).setContentIntent(getPendingIntent(bundle, uniqueInteger));
mNotification.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
mNotification.setAutoCancel(true);
notifManager.notify(uniqueInteger, mNotification.build());
and the method getPendingIntent()
private PendingIntent getPendingIntent(Bunble bundle, int rc) {
Intent notificationIntent = new Intent(this, YourNextActivity.class);
notificationIntent.putExtras(bundle);
return PendingIntent.getActivity(this, rc, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
I am using NotificationCompat2 by Jake Wharton here but the answer does not depend on that.