Ответ 1
Я использовал этот код для создания уведомлений. Он имеет название, текст, значок, contentAction как широковещательное сообщение. Наверное, достаточно ответить на ваши вопросы)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notChannel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT)
notManager.createNotificationChannel(notChannel)
}
val builder = NotificationCompat.Builder([email protected], CHANNEL_ID)
val contentIntent = Intent(NOT_ACTION)
contentIntent.putExtra(EXTRA_NOT_ID, notificationId)
val contentAction = PendingIntent.getBroadcast([email protected], NOT_REQ_CODE, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT)
builder.setContentTitle("Notification $notificationId")
.setContentText("Awesome text for $notificationId notification")
.setContentIntent(contentAction)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setDefaults(NotificationCompat.DEFAULT_ALL)
NotificationManagerCompat
.from([email protected])
.notify(notificationId++, builder.build())
1. Можете ли вы инициировать действия уведомления?
Да, ты можешь. Вы можете получить Notification
из StatusBarNotification
, а затем получить PendingIntent
для действий и использовать их.
Например, я хочу вызвать contentAction уведомления
override fun onNotificationPosted(sbn: StatusBarNotification) {
super.onNotificationPosted(sbn)
Log.d(TAG, "Gotcha notification from ${sbn.packageName}")
if (sbn.packageName == TARGET_PACKAGE) {
val contentIntent = sbn.notification.contentIntent
contentIntent.send()
}
}
Этот код инициирует отправку широковещательного сообщения. НО он будет игнорировать .setAutoCancel(true)
, поэтому вам нужно вручную обрабатывать его
if (sbn.packageName == TARGET_PACKAGE) {
val contentIntent = sbn.notification.contentIntent
contentIntent.send()
if (sbn.notification.flags and Notification.FLAG_AUTO_CANCEL != 0) {
cancelNotification(sbn.key)
}
}
2. Как NCleaner отменяет текущие уведомления?
Первый способ, который приходит мне на ум, - использование NotificationListenerService.snoozeNotification
как это
if (sbn.packageName == TARGET_PACKAGE) {
snoozeNotification(sbn.key, Long.MAX_VALUE - System.currentTimeMillis())
}
Я на 99% уверен, что NCLeaner использует этот код. Потому что он не поддерживает эту функцию для устройств pre-O.
Заметка. Вы не можете просто использовать Long.MAX_VALUE
, уведомление будет отложено на пару секунд, а затем снова появится. Проверено на пикселе 2 8.1.
3. Можете ли вы изменить существующее уведомление?
Нет, ты не можешь. Только приложение владельца уведомлений может его изменить.
PS
Я также пытался преодолеть границы с помощью скрытых методов и полей NotificationManager
и NotificationListenerService
. Результатом всех попыток является:
Вызвано: java.lang.SecurityException: вызов uid 10210 дал пакет com.ns.notificationsender, который принадлежит uid 10211
Таким образом, приложение должно быть системным, или root может помочь добиться успеха. Но у меня нет такого устройства.