NotificationCompat.Builder addAction - Boolean always true - android

I have the following code:
public void sendNewNotification (Booking updateBooking) {
String msg;
if (updateBooking.getJobStatus () == Booking.eeJob_OnRoute) {
msg = "Your driver has been dispatched.";
} else if (updateBooking.getJobStatus () == Booking.eeJob_POB) {
msg = "Your driver has arrived.";
} else if (updateBooking.getJobStatus () == Booking.eeJob_Complete) {
Variables.driverrated = false;
msg = "Your booking has been completed. Thank you for using " + Variables.setting.getCompanysName () + ".";
} else if (updateBooking.getJobStatus () == Booking.eeJob_NoShow) {
msg = "Unfortunately your driver was unable locate you. Please call the office on " + Variables.setting.getCompanytelephone () + ".";
} else if (updateBooking.getJobStatus () == Booking.eeJob_Cancelled) {
msg = "Your booking has been cancelled. Please call the office on " + Variables.setting.getCompanytelephone () + " if this is incorrect.";
} else {
return;
}
PendingIntent detailsIntent = PendingIntent.getActivity (this, 0, new Intent (this, HomeActivity.class)
.putExtra ("booking", updateBooking)
.putExtra ("track", false),
PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent trackingIntent = PendingIntent.getActivity (this, 0, new Intent (this, HomeActivity.class)
.putExtra ("booking", updateBooking)
.putExtra ("track", true),
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder (this);
builder.setAutoCancel (true);
builder.setDefaults (Notification.DEFAULT_ALL);
builder.setWhen (System.currentTimeMillis ());
builder.setContentTitle (Variables.setting.getCompanysName () + " - booking update");
builder.setSmallIcon (R.drawable.notification);
builder.setTicker (Variables.setting.getCompanysName () + " - booking update");
builder.setPriority (NotificationCompat.PRIORITY_HIGH);
builder.setContentText (msg);
builder.setContentIntent (trackingIntent);
builder.addAction (R.drawable.documents_32px, "DETAILS", detailsIntent);
if (updateBooking.getJobStatus () != Booking.eeJob_Complete) {
builder.addAction (R.drawable.notification, "TRACK", trackingIntent);
} else {
builder.addAction (R.drawable.profile_32px, "RATE", detailsIntent);
}
NotificationManager manager = (NotificationManager) getSystemService (NOTIFICATION_SERVICE);
manager.notify (getTaskId (), builder.build ());
}
My issue is in my onCreate function I have these two lines:
m_updateBooking = (Booking) getIntent ().getSerializableExtra ("booking");
m_TrackDriver = (Boolean) getIntent ().getSerializableExtra ("track");
m_updateBooking works flawlessly. But m_TrackDriver is ALWAYS true. No matter what button I press. Can anyone explain why this is?
Thanks in advance for all your help.

Since your Intent has the same action for both the PendingIntent, you need to specify a different requestCode otherwise with FLAG_UPDATE_CURRENT the extras in the PendingIntent will be replaced by the new extras in the Intent. For this reason you have always true, because it is in the last PendingIntent requested.
This StackOveflow answer explains in details how PendingIntent works.
To resolve your issue change your code like this:
PendingIntent detailsIntent = PendingIntent.getActivity (this, 0, new Intent (this, HomeActivity.class)
.putExtra ("booking", updateBooking)
.putExtra ("track", false),
PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent trackingIntent = PendingIntent.getActivity (this, 1, new Intent (this, HomeActivity.class)
.putExtra ("booking", updateBooking)
.putExtra ("track", true),
PendingIntent.FLAG_UPDATE_CURRENT);

Related

FCM foreground notification received, but application is not opening on Click

First of all, I am developing an app in C# Xamarin.form. But any advice not related to Xamarin is welcome as well.
As described in the title, I am able to receive notifications no matter when the app is in background, foreground or killed.
But the problem is that I can't open (re-activate would be the better word) the app (let's say I hit android home button) when I click the foreground-received notification. Otherwise, things are all working as expected.
The server sends FCM with notification and data;
{
data: {
topic : "push",
title : subject,
body : contents,
...data,
},
priority : "high",
notification: {
title: subject,
body: contents,
},
tokens,
};
{
// [FirebaseMessagingService]
var notificationBuilder = new NotificationCompat.Builder(this, MainActivity.CHANNEL_ID)
.SetContentTitle(title)
.SetContentText(messageBody)
.SetPriority((int)NotificationPriority.Max)
.SetAutoCancel(true)
.SetContentIntent(StartActivity(url))
.SetSmallIcon(Resource.Mipmap.icon)
.SetStyle(new NotificationCompat.BigTextStyle().BigText(messageBody));
var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
var timestamp = timeSpan.TotalSeconds;
NotificationManager notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify((int)timestamp, notificationBuilder.Build());
}
public PendingIntent StartActivity(string _url)
{
Intent intent = new Intent(MainActivity.instance, typeof(FCMReceiver));
//Intent intent = new Intent(MainActivity.instance, typeof(MainActivity));
//MainActivity.instance.Intent.AddFlags(ActivityFlags.ClearTop);
MainActivity.instance.Intent.AddFlags(ActivityFlags.NewTask);
MainActivity.instance.Intent.SetAction("notification_cancelled");
MainActivity.instance.Intent.PutExtra("url", _url);
intent.AddFlags(ActivityFlags.NewTask);
intent.SetAction("notification_cancelled");
intent.PutExtra("url", _url);
//DataManager.RedirectUrl = _url;
var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
var timestamp = timeSpan.TotalSeconds;
return PendingIntent.GetBroadcast(MainActivity.instance, (int) timestamp, intent, PendingIntentFlags.OneShot);
//return PendingIntent.GetActivity(MainActivity.instance, 5000, intent, PendingIntentFlags.CancelCurrent);
}
[BroadcastReceiver(Enabled = true, Exported = false)]
public class FCMReceiver : BroadcastReceiver
{
public override void OnReceive(Context _context, Intent intent)
{
Device.BeginInvokeOnMainThread(() =>
{
// .. does nothing
});
}
}

unable to open second notification

I wanted to open different articles in one activity using different post id's which i am sending via notification. and i am able to open one post on clicking on notification but with same activity open i m unable to open or process second notification.
public void onMessageReceived(RemoteMessage remoteMessage) {
sharedPref = new SharedPref(this);
if (sharedPref.getNotification()) {
// play vibration
if (sharedPref.getVibration()) {
((Vibrator) getSystemService( Context.VIBRATOR_SERVICE)).vibrate(VIBRATION_TIME);
}
RingtoneManager.getRingtone(this, Uri.parse(sharedPref.getRingtone())).play();
JSONObject json = null;
if (remoteMessage.getData().size() > 0) {
Map<String, String> data = remoteMessage.getData();
FcmNotif fcmNotif = new FcmNotif();
fcmNotif.setTitle(data.get("title"));
fcmNotif.setPosttitle( data.get("posttitle"));
fcmNotif.setPost_id(data.get("post_id"));
fcmNotif.setPost_slug( data.get( "post_slug" ) );
fcmNotif.setCat_name(data.get("cat_name"));
fcmNotif.setType(data.get("type"));
if(!data.get("cat_name").equals("No Notification"))
{
displayNotificationIntent(fcmNotif);
}
}
}
}
private void displayNotificationIntent(FcmNotif fcmNotif) {
Intent intent = new Intent(this, MainActivity.class);
if (fcmNotif.getPost_id() != "tnd") {
intent = new Intent(this, PostDetails.class);
intent.putExtra( "PostId",fcmNotif.getPost_id());
intent.putExtra( "type",fcmNotif.getType() );
intent.putExtra( "PostSlug",fcmNotif.getPost_slug() );
intent.putExtra("CategoryName",fcmNotif.getCat_name());
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(fcmNotif.getTitle());
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(fcmNotif.getPosttitle()));
builder.setContentText(Html.fromHtml(fcmNotif.getPosttitle()));
builder.setSmallIcon( R.mipmap.custom_icon);
builder.setDefaults( Notification.DEFAULT_LIGHTS);
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
builder.setPriority(Notification.PRIORITY_HIGH);
}
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
int unique_id = (int) System.currentTimeMillis();
notificationManager.notify(unique_id, builder.build());
}
Note:
I have tried using intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK); and it opens all notifications easily but when pressing HOME button and reopening app from drawer its opens first notification post not last opened one.
and XML is simple `
android:name=".PostDetails"
android:label="#string/back"
android:parentActivityName=".AllCategoryList"
android:screenOrientation="portrait"/>
<activity`
Finally Got solution:
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);
from ans from diffrent question of #Jitendra ramoliya

Second button from notification, the bundle I receive in IntentService contains the extras from the first button

So this is the code I use for my intents:
String tag = "#business"; String secondTag = "#personal";
Intent action1Intent = new Intent(context, NotificationActionService.class)
.setAction("tag").putExtra("id", psTrip.getId()).putExtra("tag", tag);
PendingIntent action1PendingIntent = PendingIntent.getService(context, 0,
action1Intent, PendingIntent.FLAG_ONE_SHOT);
Intent action2Intent = new Intent(context, NotificationActionService.class)
.setAction("tag").putExtra("id", psTrip.getId()).putExtra("tag", secondTag);
PendingIntent action2PendingIntent = PendingIntent.getService(context, 0,
action2Intent, PendingIntent.FLAG_ONE_SHOT);
This is how I create the actions:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
RemoteInput remoteInput = new RemoteInput.Builder("Business")
.setLabel("Business")
.build();
Notification.Action action =
new Notification.Action.Builder(R.drawable.btn_tag_trip,
tag, action1PendingIntent)
.addRemoteInput(remoteInput)
.build();
RemoteInput remoteInput2 = new RemoteInput.Builder("Personal")
.setLabel("Personal")
.build();
Notification.Action action2 =
new Notification.Action.Builder(R.drawable.btn_tag_trip,
secondTag, action2PendingIntent)
.addRemoteInput(remoteInput2)
.build();
noti = new Notification.Builder(context)
.setContentTitle(context.getString(R.string.passenger_name))
.setContentText(content).setSmallIcon(R.drawable.notification_icon)
.setContentIntent(pIntent)
.addAction(action)
.addAction(action2).build();
}
Action2 calls action2PendingIntent and action calls action1PendingIntent.
But in my intentService. I have this in my onHandleIntent:
final NotificationManager notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notifManager.cancelAll();
String action = intent.getAction();
Log.i("", "Received notification action: " + action);
Bundle bundle = intent.getExtras();
if (bundle != null) {
final String id = bundle.getString("id");
final String tag = bundle.getString("tag");
Log.i("", "Received notification action: id: " + id + " / tag: " + tag);
}
BUT the bundle.getString("tag"); will always return "#business" (the tag of the first action, even if I press the second button.
Why is this happening?
Use the PendingIntent.FLAG_UPDATE_CURRENT above mentioned flags helps in updating pending intent for the activity.
Thanks to #pskink I did manage to make it work, by changing the request code for the second pending intent, like this:
PendingIntent action2PendingIntent = PendingIntent.getService(context, 2,
action2Intent, PendingIntent.FLAG_ONE_SHOT);

Create multiple pendingIntent

The value for myRange is always 1, 2 or 3.
It is giving a nullpointer exception error.pending must be specified.
If I do not check myRange value inside if statement, it does not give an error but it does not create pendingIntent2 and pendingIntent3.
I tried sending different Request code but it did not work.
private PendingIntent createGeofencePendingIntent(int myRange) {
Log.d(TAG, "createGeofencePendingIntent");
Toast.makeText(getContext(),"creating intent function" + myRange ,Toast.LENGTH_SHORT).show();
if ( geoFencePendingIntent1 != null && myRange == 1)
return geoFencePendingIntent1;
if ( geoFencePendingIntent2 != null && myRange == 2 )
return geoFencePendingIntent2;
if ( geoFencePendingIntent3 != null && myRange == 3)
return geoFencePendingIntent3;
if(myRange == 1)
{
Toast.makeText(getContext(),"creating intent 1",Toast.LENGTH_SHORT).show();
Intent intent1 = new Intent( getContext(), GeofenceTransitionService.class);
intent1.putExtra("region",inString[0]);
geoFencePendingIntent1 = PendingIntent.getService(
getContext(), GEOFENCE_REQ_CODE, intent1, PendingIntent.FLAG_UPDATE_CURRENT );
return geoFencePendingIntent1;
}
else if (myRange ==2)
{
Toast.makeText(getContext(),"creating intent 2",Toast.LENGTH_SHORT).show();
Intent intent2 = new Intent( getContext(), GeofenceTransitionService.class);
intent2.putExtra("region",inString[1]);
geoFencePendingIntent2 = PendingIntent.getService(
getContext(), 5, intent2, PendingIntent.FLAG_NO_CREATE );
return geoFencePendingIntent2;
}
else if (myRange == 3)
{
Intent intent3 = new Intent( getContext(), GeofenceTransitionService.class);
return PendingIntent.getService(
getContext(), GEOFENCE_REQ_CODE, intent3, PendingIntent.FLAG_UPDATE_CURRENT );
}
geoRange++;
// Toast.makeText(getContext(), "leaving my geofence", Toast.LENGTH_SHORT).show();
return null;
}
You have several problems here. The first one is this:
geoFencePendingIntent2 = PendingIntent.getService(
getContext(), 5, intent2, PendingIntent.FLAG_NO_CREATE );
This will probably always return null as you you've specified FLAG_NO_CREATE. This will only return a non-null result if a matching PendingIntent already exists (which it probably doesn't). Use FLAG_UPDATE_CURRENT instead.
The second problem is that you need to make sure that each of your 3 different PendingIntents are unique. To do this you need to provide either a unique requestCode in the call to PendingIntent.getService() OR you need to provide a unique ACTION in the Intent that you pass to PendingIntent.getService(). Otherwise, when you call PendingIntent.getService(), you will just keep getting the same PendingIntent returned (and a new one will not be created).
There are about a million questions on Stackoverflow about this and in most of them there is a detailed explanation of how PendingIntent creation and matching works.

GCM start background operations (make post to server) on notification click

I'm using Google Play Services lib for GCM and all works great.
Now I implement 2 buttons (actions) in my notificationCompat.Builder:
- One open app.
- Other one delete some unread messages: for this operation I post some dato to server.
How can I launch a post to my server on notification action click without open any activity in front of user?
Thank you very much!!!!!
Here my code:`Intent openIntent = new Intent();
Intent cancelIntent = new Intent();
if (has1Id) {
//go details!
openIntent = new Intent(this, NotificationActivity.class);
openIntent.putExtra("id", ids.get(0));
//cancell intent: start async operation in background
cancelIntent = new Intent(this, HomeActivity.class);
cancelIntent.putExtra("id", ids.get(0));
}else{
//go home!
openIntent = new Intent(this, HomeActivity.class);
//cancell intent: start async operation in background
cancelIntent = new Intent(this, HomeActivity.class);
cancelIntent.putExtra("id", ids);
}
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
openIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent cancelNotificationIntent = PendingIntent.getActivity(this, 0,
cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT);
long[] vibrationPattern = {0, 200, 800, 200, 100, 500};
Uri soundUri = Uri.parse("android.resource://"+ getPackageName() + "/" + R.raw.jingle1);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.drawable.ic_notification)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))
.setContentTitle(title) //set title
.setContentInfo(numNotRead) //number of unread content
.setAutoCancel(true)
.setContentText(msgs.get(0)+"...")
.setVibrate(vibrationPattern)
.setSound(soundUri)
.setLights(Color.rgb(255, 165, 00), 800, 800)
.setContentIntent(contentIntent).addAction(R.drawable.ic_notification, getString(R.string.open_app), contentIntent)
.setContentIntent(cancelNotificationIntent).addAction(android.R.drawable.ic_delete, getString(R.string.mark_read), cancelNotificationIntent);
if (has1Id) {
NotificationCompat.BigTextStyle bigTextStyle =new NotificationCompat.BigTextStyle().bigText(msgs.get(0));
mBuilder.setContentTitle(getString(R.string.notification_new_content));
//get only 1 long text: the description of content
mBuilder.setStyle(bigTextStyle);
}else{
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle(getString(R.string.notification_new_contents));
for (int i=0; i < msgs.size(); i++) {
inboxStyle.addLine(msgs.get(i));
}
mBuilder.setStyle(inboxStyle);
}
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());`
You should use another class as the intent receiver for cancelIntent, like a BroadcastReceiver and handle the intent there with no UI.
public class MyIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context _context, Intent _intent) {
if (_intent.getAction().equals(MY_INTENT)) {
// TODO Handle a notification
}
}
}
You also can use a Activity with no UI as the intent, but I think previous option is better.
More info:
Android Activity with no GUI

Categories

Resources