I use BroadcastReceiver to process some data after user clicks on action button from notification.
So in order to achieve that first I build PendingIntent:
val intent = Intent(context, CustomBroadcastReceiver::class.java).apply {
action = MY_ACTION
// Also put some extras here like notification id.
}
val pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0)
And this is called from Service which builds and shows the notification:
NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(getString(R.string.title))
.setContentText(getString(R.string.text))
.setSmallIcon(R.drawable.ic_notification)
.addAction(actionIcon, actionTitle, pendingIntent)
.setAutoCancel(true)
.build()
Then in CustomBroadcastReceiver I'm cancelling this notification (I have notification ID from intent):
getNotificationManager().cancel(notificationId)
The problem is that notification is not dismissed, it's till on notification drawer.
I saw answers from this question, but it doesn't help - I'm using applicationContext, notificationId is correct and it's greater than 0.
Related
UPDATE!!!
I solved this problem. The problem was with remoteMessage.notification.let {
which is triggered only when app is in foreground state, thus I removed this part and it worked like a charm)
When I send push notification and when app is in background state notification is coming but whem I click it is not doing anything. But when app is in foreground, the click is taking to an app again.
Here is some code from FirebaseMessagingService
remoteMessage.notification.let {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val intent = Intent(this, MainActivity::class.java)
.putExtra(CLICK_ACTION, mapData.get("click_action"))
.putExtra(PAGE_TO_GO, mapData.get("pagetogo"))
.putExtra(NOTIFIATION_TITLE, mapData.get("title"))
.putExtra(NOTIFICATION_BODY, mapData.get("body"))
.putExtra(COMPANY_ID, mapData.get("company_id"))
.putExtra(DOCUMENT_ID, mapData.get("document_id"))
.putExtra(ORDER_ID, mapData.get("order_id"))
.putExtra(FROM_DATE_EXTRA, mapData.get("from_date"))
.putExtra(TO_DATE_EXTRA, mapData.get("to_date"))
.putExtra(LEDGER_VIEW_ID_EXTRA, mapData.get("id_for_ledge_view"))
.putExtra(IS_CREDIT_EXTRA, mapData.get("is_credit"))
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val notification = NotificationCompat.Builder(this, getString(R.string.channel_id))
.setSmallIcon(R.drawable.ic_baseline_notifications_24)
.setContentTitle(it?.title)
.setContentText(it?.body)
.setContentIntent(pendingIntent)
.setStyle(
NotificationCompat.BigTextStyle()
.bigText(it?.body)
)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
with(notificationManager) {
notify(NOTIFICATION_ID, notification.build())
}
I solved this problem. The problem was with remoteMessage.notification.let { which is triggered only when app is in foreground state, thus I removed this part and it worked like a charm)
My app has one activity and one service. The service starts a foreground notification that has an action button that in some situations needs to tell the activity to do something besides just coming back to the front. It uses the Extras to indicate this something.
My issues are that I can't find any documentation on how to receive explicit intents other than through the "bundle" passed to onCreate() which isn't usually called because the activity could already be created.
How do you receive an intent after onCreate()?
Notification code snippet:
val actionIntent = Intent(this, MainActivity::class.java)
actionIntent.action = actionText
actionIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
val pendingActionIntent: PendingIntent = PendingIntent.getActivity(this, 0, actionIntent, 0)
val actionCancel: NotificationCompat.Action = NotificationCompat.Action.Builder(R.drawable.ic_cancel_black_24dp,
actionText,
pendingActionIntent).build()
val notificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setContentTitle(getText(R.string.notification_title))
.setSmallIcon(R.drawable.ic_logo_24dp)
.setContentIntent(pendingIntent)
.setOnlyAlertOnce(true)
.addAction(actionCancel)
.setContentText(text)
startForeground(ONGOING_NOTIFICATION_ID, notificationBuilder.build())
Override onNewIntent(). If the activity already exists, and an Intent is bringing it back to the foreground, that Intent is delivered to onNewIntent().
I am building a Voip app in android. Everything is working fine but I am not able to figure out how to accept and reject calls.
I use TelephoneManager#addNewIncomingCall to report new calls to the system. After that, I created a Connection object in ConnectionService#onCreateIncomingConnection and returned it. The onShowIncomingCallUi gets called and I create a notification this way:
val intent = Intent(context, TokboxActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
this.putExtras(this#Call.extras)
}
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val notification = NotificationCompat.Builder(context, "OKDOK")
.setSmallIcon(R.drawable.common_full_open_on_phone)
.setContentTitle("OKDOK")
.setContentText("Incoming call from ${extras.getString("docName")}")
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(pendingIntent, true)
.build()
notification.flags = notification.flags or NotificationCompat.FLAG_INSISTENT
val notificationManager = context.getSystemService(
NotificationManager::class.java)
notificationManager.notify("OKDOK", 0, notification)
I am getting the notification too. But I have two buttons in TokboxActivity. I want them to accept and reject the call. How do I implement that?
I wrote the following method to check if a notification is active (visible on the status bar):
public static boolean isNotificationActive(Context context, int id) {
Intent intentPopup = new Intent(context, PopupActivity.class);
PendingIntent test = PendingIntent.getActivity(context, id, intentPopup, PendingIntent.FLAG_NO_CREATE);
return test != null;
}
I create a PendingIntent exactly like the one I want to be checked (the same 'intentPopup' and 'id' are passed to this PendingIntent) and, because of FLAG_NO_CREATE, I expect this PendingIntent to be null if it doesn't exist yet. I read about this method in a thread posted years ago here.
If the notification has not yet been issued, the method returns the expected value (false). When the notification is issued and is in the status bar, the method returns true.
However, after I dismiss the notification, the method still returns true, as if the PendingIntent is still there.
What am I missing here? Is the PendingIntent still available or am I misunderstanding something?
Is there a better way to check if a specific notification is active (being displayed in the status bar)?
EDIT: here's the code that creates the notification:
Intent intentPopup = new Intent(context, PopupActivity.class);
intentPopup.putExtra("id", id);
intentPopup.putExtra("timeQ", timeQ);
PendingIntent pendingIntentPopup = PendingIntent.getActivity(context, id, intentPopup, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntentPopup)
.setSmallIcon(R.drawable.q_notification_icon)
.setContent(contentView)
.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/raw/notification_sound"))
.setVibrate(vibrate_pattern);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR;
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(id, notification);
Unfortunately PendingIntents that you embed in a Notification do not automatically disappear when the Notification is dismissed, viewed, or canceled. You can't use the presence or absence of a PendingIntent (using PendingIntent.FLAG_NO_CREATE like you've done) to determine whether or not a Notification is active.
To determine if a Notification is active, you can call NotificationManager.getActiveNotifications(). This will return all active Notifications that your app has posted.
Notification setAutoCancel(true) doesn't work if clicking on Action
I have a notification with an action within it. When I tap on the notification it gets removed from the list. However, when I click on the Action it successfully completes the Action (namely makes a call), but when I return to the list of notifications, it remains there.
Relative code of the AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
Meeting meeting;
/**
* Handle received notifications about meetings that are going to start
*/
#Override
public void onReceive(Context context, Intent intent) {
// Get extras from the notification intent
Bundle extras = intent.getExtras();
this.meeting = extras.getParcelable("MeetingParcel");
// build notification pending intent to go to the details page when click on the body of the notification
Intent notificationIntent = new Intent(context, MeetingDetails.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
notificationIntent.putExtra("MeetingParcel", meeting); // send meeting that we received to the MeetingDetails class
notificationIntent.putExtra("notificationIntent", true); // flag to know where the details screen is opening from
PendingIntent pIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
// build intents for the call now button
Intent phoneCall = Call._callIntent(meeting);
if (phoneCall != null) {
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, 0, phoneCall, PendingIntent.FLAG_CANCEL_CURRENT);
int flags = Notification.FLAG_AUTO_CANCEL;
// build notification object
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder.setContentTitle("Call In")
.setContentText(intent.getStringExtra("contextText"))
.setTicker("Call In Notification")
.setColor(ContextCompat.getColor(context, R.color.colorBluePrimary))
.setAutoCancel(true) // will remove notification from the status bar once is clicked
.setDefaults(Notification.DEFAULT_ALL) // Default vibration, default sound, default LED: requires VIBRATE permission
.setSmallIcon(R.drawable.icon_notifications)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(meeting.description))
.addAction(R.drawable.icon_device, "Call Now", phoneCallIntent)
.setCategory(Notification.CATEGORY_EVENT) // handle notification as a calendar event
.setPriority(Notification.PRIORITY_HIGH) // this will show the notification floating. Priority is high because it is a time sensitive notification
.setContentIntent(pIntent).build();
notification.flags = flags;
// tell the notification manager to notify the user with our custom notification
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notification);
}
}
}
use this flag:
Notification.FLAG_AUTO_CANCEL
inside this:
int flags = Notification.FLAG_AUTO_CANCEL;
Notification notification = builder.build();
notification.flags = flags;
Documentation
Ok turns out it's a known problem already, and it needs extra code to be done (keeping reference to notification through id). Have no clue why API does not provide this, as it seems very logical to do. But anyways,
see this answer in stackoverflow:
When you called notify on the notification manager you gave it an id - that is the unique id you can use to access it later (this is from the notification manager:
notify(int id, Notification notification)
To cancel, you would call:
cancel(int id)
with the same id. So, basically, you need to keep track of the id or possibly put the id into a Bundle you add to the Intent inside the PendingIntent?
I faced this problem today, and found that FLAG_AUTO_CANCEL and setAutoCanel(true), both work when click on notification,
but not work for action click
so simply, in the target service or activity of action, cancel the notification
NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancelAll();
or if have more notification
manager.cancel(notificationId);
You have created two pending intent use in boths and change Flag too.
PendingIntent pIntent = PendingIntent.getActivity(context, (int) System.currentTimeMillis(), notificationIntent, 0);
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, (int) System.currentTimeMillis(), phoneCall, PendingIntent.FLAG_UPDATE_CURRENT);
// CHANGE TO THIS LINE
PendingIntent pIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, 0, phoneCall, PendingIntent.FLAG_CANCEL_CURRENT);