I tried the code form the answer of this question: How to put media controller button on notification bar?
By calling the
showNotification()
method my app gets closed. How to prevent this? And how can i handle that this method is just called if the mobile phone api is >= 16. Because i think it is just available since api 16.
I've read, that there is a solution for lower API:
import android.support.v4.app.NotificationCompat;
But i didn't got it working, so i just wanted to prevent calling it.
And can i delete the notification from the bar, by onDestroy() of my app?
The code on that page is for the most difficult case using RemoteViews, and it looks dubious anyway. (E.g. it creates a subclass of Notification with a constructor that creates another Notification.)
The normal approach is to use a NotificationCompat.Builder to build your notification, and NotificationManager or NotificationManagerCompat to show and cancel it. See the Notifications API Guide for details and example code.
Also see the Notifying the User documentation and the Notifications design guide.
Generally, your app should only show a notification when its activity is not visible. When the user taps on the notification, it should usually open the activity which should in turn cancel the notification.
Related
As per Android docs for setFullScreenIntent:
An intent to launch instead of posting the notification to the status bar.
Reality: Fullscreen intent is launched....but notification also gets posted to the status bar.
The screen is locked, so the user is not using the device.
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_lock_idle_alarm)
.setContentTitle(timer.title)
.setContentText("Description!")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_REMINDER)
.setFullScreenIntent(pendingIntent, true) // tried with false too.
Any ideas why this doesn't work according to the docs?
I know I can remove the notification after it appears but the docs mention clearly that it should not appear.
This is reproducible both on a real device (Android 11) and on an emulator (Android 12).
I also notice the same thing with some other apps from the Play Store. They seem to use such notification (I can't know for sure but they appear on the lockscreen as fullscreen at least).
imho thats some old mistake in docs. I've never read this methods doc so carefully, but my experience says that full screen intent was/is always show Activity ADDITIONALLY to always-present notification. or will not, then freshly posted notification will appear as heads up, e.g. when user is using unlocked device at the moment of notification posting
also docs shows some use cases for such feature
Only for use with extremely high-priority notifications demanding the user's immediate attention, such as an incoming phone call or alarm clock
considering call: user didn't make any touch in GUI, instead just pressed home. Phone is ringing, how to close/reject/get back to managing Activity without Notification left? such Activity won't stay in recents history (noHistory), you may even press this home button accidentally and you don't even know in which app looking for sound source
imho this notification should also appear with started Activity, just like it happens. It isn't even visible on screen when user starts to use your extremely high-priority Activity. When job is done and Activity is finishing then Notification may also disappear, but when user won't take any decision and it is still crucial to pick some option - he need a fast option to get back to (even accidentally) "homed"/closed Activity
Background
Ever since heads-up notifications appeared on Android, some people liked it for its quick handling, yet some hated it for showing on top of apps (especially games).
In order to show heads-up notifications, developers can use something like that:
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setContentTitle("aa").setContentText("bb").setTicker("cc")
.setColor(0xffff0000).setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setPriority(Notification.PRIORITY_HIGH);
if (Build.VERSION.SDK_INT >= 21)
builder.setVibrate(new long[0]);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
Because of this, some apps came up with the idea to show ticker-text notifications that replace them somehow, just as it used to be before heads-up notifications:
https://play.google.com/store/apps/details?id=com.jamworks.noheadsup&hl=en
There are various scenarios where this could be useful. It could be, for example, useful in case of games, where full screen is used. That's because if the user is about to press the top area, and the heads-up notifications are shown, we would like to avoid accidental click on this notification.
The problem
Not only I can't find a way of how people did it, but it seems it doesn't work anymore on new versions of Android (tested on Android 7).
The only app I've found that blocks notification is this:
https://play.google.com/store/apps/details?id=com.aboutmycode.NotificationsOff&hl=en
yet it doesn't convert the heads-up notifications to "normal" ones. Instead, it just blocks them all. Plus it requires root, and seems to just change the settings of the notifications to "blocked" .
The question
Is it possible to temporarily block the heads up notifications (and yet convert them to ones without heads-up notifications ) ? If so, how?
Which restrictions does it have? Can it work without root? If it's possible with root, how? How does the "NotificationsOff" work?
Maybe this ability was possible before, but now it is not?
On Android 18+ there is a NotificationListenerService. This service gets notified when new notifications are shown. Then, I understand there are three ways to act:
Intercepting the notifications so they don't get displayed (not completely sure this can be done) Checked: if the NotificationListenerService doesn't call super.xxx when receiving a notification, the notification is also showed. So this method seems to not work.
Clearing notifications as they get posted. For this, you can use NotificationManager to either clear a given notification or clearAllNotifications Checked: it partially works to clear the notifications, but you still see the notification showing up and then it's not in the notification area (it's weird effect).
In API 21+ Lollipop it seems that you can override NotificationListenerService#getCurrentInterruptionFilter(). This method could return NotificationListenerService#INTERRUPTION_FILTER_NONE (or any other of the constants), (haven't tested, should be verified). Checked: NotificationListenerService#getCurrentInterruptionFilter() is final, so it cannot be overridden.
In API 23+ you can use both NotificationManager#setNotificationPolicy() and NotificationManager#setInterruptionFilter() (in that specific order) to control which notifications are shown to the user. Permissions are required for those APIs. Notice that this methods seem to be a convenience to be able to access the functionality, but skip implementing a complete NotificationListenerService. That's the only option that can work in a satisfying way
About NotificationListenerService, you can see the following samples in GitHub kpbird/NotificationListenerService-Example and in this post.
About NotificationManager, see additional information in this post in StackOverflow (specially interesting the highlighted comment) and in this post.
Example, tests and additional notes
I've uploaded the following repository to GitHub with an example based on kpbird's, to test all the assumptions and provide final conclusions.
Notice that the following steps to enable the permission for the app to be able to access the notifications must be followed in order for the app to function properly. This answer also provides a way to open System Settings in the correct section.
Also, for completeness, the following answer provides a way to check whether the permission is already granted or not.
Additional note: apparently first versions of Marshmallow have a bug where NotificationManager#setInterruptionFilter() doesn't work. See here and here.
In one of Activity-derived class methods I'm trying to send a Notification, clicking on which will bring the Activity to foreground if my app is in background (not visible) right now. There are reasons why I don't use Service, but use Activity (that will hold PARTIAL_WAKE_LOCK) for that.
I remember Notification worked for me when I used it like this, but I sent it from Service. Now when I send it from Activity method and it doesn't show up, though I hear its notification sound.
So are there any reasons that prevent Notification show up sent from Activity method and how can it be solved?
Thank you.
I was not exactly precise copying Notification code sample. I removed setSmallIcon() call from code as I was too lazy to add icons. As a result system was really dropping my Intent, saying that no icon is provided for it and it'll be a crash in future releases.
I am working towards managing the notifications that my app creates in the Android device. Is there any method that can provide me the number of notifications from my app that are active (i.e. still visible in the notification drawer) at any given time?
You can use NotificationManager for getting list of all the active notifications posted by your application using getActiveNotifications()
As per the reference doc for getActiveNotifications():
Recover a list of active notifications: ones that have been posted by the calling app that have not yet been dismissed by the user or cancelled by the app.
to expand on commonswares comment:
I see two approaches here:
1) manage this number via a count sharedpreferences or a database, etc. you will need to supply a deleteIntent which starts something to update this number when they dismiss the notification and a contentIntent for when they open the notification (this will also update your count).
2) read this number explicitly from a notification listener service.
https://developer.android.com/reference/android/service/notification/NotificationListenerService.html
#1 is much preferred because the user doesn't have to opt in to the behavior and asking for their full notification list is entirely unnecessary.
fun getNotificationCount(): Int {
return notificationManager.activeNotifications.size
}
My intention is to display a notification with a personalised icon. However, if a notification with the same id is already displayed and then I need to add a new notification with the same id, my program will instead prepare a "stacked" version of the notification where the icon is changed to some generic icon and the notification content shows excerpts from the last and current notifications. Similar to how Gmail does when there are multiple emails.
To implement that I need to check if there are notifications of my app, currently displayed. I do not see any API to retrieve my own notifications.
I cannot simply cache the notification details that I have displayed till now, since in that case I need to know when they will be dismissed by the user, and update my cache accordingly. I also do not see any API to listen for dismiss events.
If you observe the gmail app notification behaviour properly u will notice that even when u dismiss one notification gmail shows you the same notification again in the list when a new notification comes. It looks to me that gmail is relying on total unread/unopened messages rather than keeping a cache of notifications.
There is no direct api for ur suggested SDK version. You need to fallback to ur own implementation. However, there is a way to know if a already showed notification was dismissed - How to know when my notification is cleared via Clear button?
This is possible with android 4.3 upwards now
See http://developer.android.com/reference/android/service/notification/NotificationListenerService.html#getActiveNotifications()