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);
Related
I'm using example code to create a notification, which I then want to handle in onNewIntent() if my App is already running. However, onNewIntent() was not being called. I searched for a few hours and no one seemed to have a proper answer--just some workarounds.
I had to search forever to find the solution here: Android OnNewIntent not called and the answer is not actually explained.
Question
Can anyone explain why we need the lines:
resultIntent.setAction(Intent.ACTION_MAIN);
resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);
in order to receive the notification through onNewIntent()? The App launches just fine without them, but will always go through onCreate() instead.
Example Code
public void createNotification(String s){
// The id of the channel.
String CHANNEL_ID = "my_channel_01";
NotificationCompat.Builder mBuilder =
(NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.icon_missing)
.setContentTitle(getString(R.string.notification_channel_name))
.setContentText(R.string.text);
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, MainActivity.class);
resultIntent.setAction(Intent.ACTION_MAIN);
resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// 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 app to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.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) getSystemService(Context.NOTIFICATION_SERVICE);
// mNotificationId is a unique integer your app uses to identify the
// notification. For example, to cancel the notification, you can pass its ID
// number to NotificationManager.cancel().
Notification n = mBuilder.build();
n.flags = n.flags | Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(1, n);
}
I launch an activity from a notification I receive. If that notification is pressed it launches an activity. If there are no previous activities on the back-stack, or only a certain one, I want to remove that certain activity and insert my main activity in there and than the new activity.
I found this Thread but I don't understand how he handles it with two intents and flags.
i.e. intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK)
Is it wise to do it the way he did it or should I edit the activity stack for that?
I am fairly new to android dev, so some advice could help me here out.
Thanks a lot ;)
Update: so I went with the stackbuilder but somehow it doesn't get set right ... I don't find my error, my boolean noActivity gets set for sure, but I think somehow I misunderstood how the stack actually puts a previous activity in there.
private void sendNotification(messageType type, Map<String, String> data, boolean noActivities) {
Intent i;
String message = "";
switch (type) {
case newFOLLOWER:
User cur = new User(data.get("other.name"));
User.lookAT = User.getOtherUserByName(cur);
i = new Intent(this, other_profile.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
message = data.get("other.name") + " is following you now. Click to see his profile";
i.putExtra("Notification", data.get("other.name") + " is following you now. Click to see his profile");
break;
default:
i = null;
break;
}
if (i != null) {
TaskStackBuilder stack = TaskStackBuilder.create(this);
if(noActivities){
stack.addParentStack(Photostream.class);
}
stack.addNextIntent(i);
PendingIntent pendingIntent = stack.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);//PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("PIC LOC")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSound)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
Update 2: So after searching quite a lot I found out that I missunderstood how the stack builder works. I found another thread where they described how the adding works. Editing the Manifest in order to have a previous stack.
I was to fast and skipped part of the tutorial you provided me so kindly ...
Thanks for your guys help ;)
You should make stack builder while creating notification like this.
Intent resultIntent = new Intent(this, NotificationTapActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
So whenever user will tap on notification, MainActivity will be inserted in stack.
One more solution in which you can handle the back press of NotoificationTapActivity. In which you can check if noting is there in stack then you can finish the current activity and starts MainActivity from there.
You should use TaskStackBuilder. This is the most efficient way and the TaskStackBuilder structure developed for that reason.
I allways use TaskStackBuilder when Push Notifications are included to my project.
Overriding onBackPress() is not good approach because it requires complex structures in your app and you need to handle many things.
Check this tutorial.
/**Just use below code inside onMessageReceived()**/
PendingIntent pendingIntent;
Uri defaultSoundUri;
Intent notification_intent;
String message = "Your Message";
notification_intent = new Intent(this, YourActivity.class);
notification_intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = PendingIntent.getActivity(this, 0 , notification_intent, PendingIntent.FLAG_ONE_SHOT);
defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(getNotificationIcon(notificationBuilder))
.setContentTitle(this.getResources().getString(R.string.app_name))
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
.setContentIntent(pendingIntent);
String[] multilineDescription = new String[]{message};
message = multilineDescription[0];
for (int i=1; i<multilineDescription.length; i++)
{
message += System.getProperty("line.separator");
message += multilineDescription[i];
}
notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
/***Above commented is for strecting the big message in Push Notification******/
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int)MESSAGE_NOTIFICATION_ID /* ID of notification */, notificationBuilder.build());
You can simply handle that in onBackPressed of notification activity.
With help of flag you may know that your notification activity is opened through notification click and then in onBackPressed go to your mainactivity as following:
Intent intent =new Intent(context,MainActivity.class)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
PendingIntent can implement multi intent. Just create an array intent
Intent[] intents = new Intent[2];
Intent intent1 = new Intent(this, MainActivity.class);
Intent intent2 = new Intent(this, YourActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivities(this, 0, intents,PendingIntent.FLAG_ONE_SHOT);
And when you finish YouActivity, it will back to MainActivity.
Intent intent = getIntent();
String data= intent.getStringExtra("from");
if(data.equalsIgnoreCase("notificaton")
{
// call Mainactivity
}
else if(){}
Is it possible not launch new activity if we receive a push notification while the app is running?
My activity works with fragments and I want to do transition to a determinate fragment when the notification is received. My activity have data that I need to show the fragments. The problem is that when I receive the push notification while the app is running the method onDestroy is called and here I clear the data and then the app crash because the data are null. How can I do to not create new activity when the app receive a push notification while is running? In case the app is running I want that if you click the notification do a transition fragment, not create again the activity.
Thanks in advance.
First of all, I think that you mean "notification" to be a "message", but not android.app.Notification class.
And second, I don't think it's a best practise to raise new GUI when receiving a message, which would interrupt the user interaction. For details, please refer to: http://developer.android.com/training/notify-user/index.html and http://developer.android.com/design/patterns/notifications.html.
At last, if you really wanna do what you stated in your thread, I wonder why the data used to generate the show-data fragment is held in the activity. Try holding the data in an android.app.IntentService object, and then generate transfer the data to new activity, and then use android.app.Fragment.setArguments method to transfer the data from activity to fragment.
I think that this code will help you. This which you need is PendingIntent, it make transaction to desired activity.
/**
* Issues a notification to inform the user that server has sent a message.
*/
private static void generateNotification(Context context, String title,
String message) {
//get the default notification sound URI
Uri uriNotificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
//make intent to the application. if the application is opened just maximize it.
Intent homeIntent = new Intent(context, 'your desired activity');
homeIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
homeIntent, 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("eCommCongress")
.setContentText(message)
.setLights(Color.GREEN, 1500, 1500)
.setSound(uriNotificationSound)
.setAutoCancel(true)
.setContentIntent(contentIntent);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(counter, mBuilder.build());
counter++;
}
It is perfectly possible and I do such a thing in one of my apps. First, you need to declare your activity as android:launchMode="singleTop",
Then, when you build you must configure your pending intent not to fire a new instance of your activity:
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent("YOUR ACTION HERE");
intent.setClassName(this, MainActivity.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent resultPendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.defaults |= Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS;
notification.flags |= Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(idNotificacion,notification);
Now all you have to do is to override your onNewIntent inside your Activity and do whatever you want with your fragment:
#Override
protected void onNewIntent(Intent intent) {
MiLog.i(getApplicationContext(),"IntentShit","new intent received");
MiLog.i(getApplicationContext(),"IntentShit","Action: "+intent.getAction());
if(intent.getAction()!=null && intent.getAction().equals("YOUR ACTION HERE"){
//DO your stuff here
}
}
You should also take a look at this page for more info:
http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode
I have problem my MainActivity can be created by 3 ways:
1) standart launch App
2) from Service
3) from notification click.
How I can check when it starts from notification click?
Notification code:
private void createNotification()
{
Log.d("service createNotification",MainActivity.TAG);
Context context = getApplicationContext();
Intent notificationIntent = new Intent(this,MainActivity.class);
intent.putExtra(AppNames.IS_NOTIFICATION_INTENT,true);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(this.getString(R.string.notification_title))
.setContentText(this.getString(R.string.notification_text))
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_launcher);
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(AppNames.APP_NOTIFICATION, builder.getNotification());
}
add
intent.putExtra("started_from","notification");
to the code that starts the intent from the notifications, and the same thing to the other startActivity calls just change the value, then inside your activity
String startedFrom = getIntent().getStringExtra("started_from");
for more refer to this question: How do I get extra data from intent on Android?
I am using an Activitiy with various Tabs on it. From a different part of the application, Notifications are created to tell the user that something has changed. I now managed to Call the Activity, when the user clicks on the Notification. But how can i determine wheter a Activity is created the "normal" way during runtime or by clicking on the notification?
(Depending on the notification clicked, i want to forward to another tab instead of showing the main Tab.)
Intent intent = new Intent(ctx, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, intent, 0);
// TODO: Replace with .Build() for api >= 16
Notification noti = new Notification.Builder(ctx)
.setContentTitle("Notification"
.setContentText(this.getName())
.setSmallIcon(R.drawable.icon)
.setContentIntent(pendingIntent)
.setDefaults(
Notification.DEFAULT_SOUND
| Notification.DEFAULT_LIGHTS)
.setAutoCancel(true)
.getNotification();
NotificationManager notificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
// Hide the notification after its selected
notificationManager.notify(this.getId(), noti);
This successfully calls my MainActivity. But is there some Method that is called when the Activity is triggered by the pendingIntent?
Thought about to define something like this in the Main Activity:
onTriggeredByNotification(Notification noti){
//determinte tab, depending on Notification.
}
Pass a boolean value from notification and check for the same in the onCreate method of the activity.
Intent intent = new Intent(ctx, MainActivity.class);
intent.putExtra("fromNotification", true);
...
if (getIntent().getExtras() != null) {
Bundle b = getIntent().getExtras();
boolean cameFromNotification = b.getBoolean("fromNotification");
}
You can try this in your Notification
Intent intent=new Intent();
intent.setAction("Activity1");
In the Activity override onNewIntent() method and get action so you can determine the activity is called or not.
Better than using the reserved action field of your intent as specified by #ricintech, you could use an extra parameter in your pending intent and detect it in your onCreate method and in your onNewIntent metod inside your activity.