Background
I've found an app that somehow hides heads-up notifications, including even ongoing notifications (used by foreground services), called NCleaner .
I was wondering how such a thing works.
The problem
There isn't much information of how to control notifications of other apps. Only of the current app, and for some reason I've failed to cancel an ongoing notification, but I've succeeded canceling a normal one.
What I've found
I've found this sample showing how to monitor notifications. After searching on the docs about NotificationListenerService, I've also found how to cancel specific notifications of other apps.
However, it doesn't work for ongoing notifications.
For testing of normal notifications I just sent myself an email or wrote something on PushBullet app via my PC.
For testing of ongoing notifications, I've installed and ran my spare time app (here), which shows an ongoing notification right on the beginning of the app, starting from Android O. In fact, it can even hide the notifications of the OS, of USB connected and debugging (just connect the device to the PC via USB) ...
Here's the code I've made, based on the sample, to cancel all notifications it gets:
NotificationListenerExampleService.kt
class NotificationListenerExampleService : NotificationListenerService() {
override fun onNotificationPosted(sbn: StatusBarNotification) {
Log.d("AppLog", "sbn:" + sbn.toString())
cancelNotification(sbn.key)
}
override fun onListenerConnected() {
super.onListenerConnected()
Log.d("AppLog", "onListenerConnected")
}
override fun onNotificationRemoved(sbn: StatusBarNotification) {}
}
manifest:
<application
android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name=".NotificationListenerExampleService" android:label="@string/service_label" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService"/>
</intent-filter>
</service>
</application>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val isNotificationServiceEnabled: Boolean
get() {
val pkgName = packageName
val flat = Settings.Secure.getString(contentResolver, "enabled_notification_listeners"")
if (!TextUtils.isEmpty(flat)) {
val names = flat.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
for (i in names.indices) {
val cn = ComponentName.unflattenFromString(names[i])
if (cn != null) {
if (TextUtils.equals(pkgName, cn.packageName)) {
return true
}
}
}
}
return false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (!isNotificationServiceEnabled) {
startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
}
}
}
The questions
- How come my code can't remove ongoing notifications?
- How come the app I've found can do it? What does it do?
- Just how much does this API provide in terms of notifications? Looking at the docs, it seems it can do a lot: read notifications, dismiss them, get all kinds of information about them, ... But I can't find some other features: Is it possible to modify a notification? To change its priority? To make it avoid being a heads-up-notification and just be in the notification drawer? Is it possible to trigger an action of a notification?
Notification
viaStatusBarNotification
, and you can getPendingIntent
s fromNotification
– Kolinsky