如何取消另一个应用程序的正在进行的通知? [英] How to cancel an ongoing notification of another app?

查看:87
本文介绍了如何取消另一个应用程序的正在进行的通知?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了一个名为我想知道这样的事情是如何工作的.

I was wondering how such a thing works.

关于如何控制其他应用程序的通知的信息并不多.仅出于当前应用程序,由于某种原因,我未能取消正在进行的通知,但我却成功取消了正常的通知.

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.

我发现 此示例 显示如何监视通知.在搜索有关 NotificationListenerService 的文档后,我还发现了如何取消其他应用程序的特定通知.

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.

为了测试正常的通知,我只是通过PC给自己发送电子邮件或在PushBullet应用中写了一些东西.

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) {}
}

清单:

<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"))
        }
    }

}

问题

  1. 为什么我的代码无法删除正在进行的通知?
  2. 我找到的应用程序为何能做到?它是做什么的?
  3. 此API在通知方面提供了多少?看一下文档,似乎可以做很多事情:阅读通知,关闭它们,获取有关它们的各种信息,...但是我找不到其他功能:是否可以修改通知?要更改其优先级?为了使其避免成为平淡无奇的通知,而只是放在通知抽屉中?可以触发通知操作吗?

推荐答案

我使用此代码来构建通知.它具有标题,文本,图标, contentAction 作为广播消息.我希望这足以回答您的问题)

I used this code for notification building. It has title, text, icon, contentAction as Broadcast Message. It is enough for answering your questions, I hope)

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(this@MainActivity, CHANNEL_ID)

        val contentIntent = Intent(NOT_ACTION)
        contentIntent.putExtra(EXTRA_NOT_ID, notificationId)

        val contentAction = PendingIntent.getBroadcast(this@MainActivity, 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(this@MainActivity)
                .notify(notificationId++, builder.build())

1.您可以触发通知操作吗?

是的.您可以从 StatusBarNotification 获取 Notification ,然后获取 PendingIntent 进行操作并使用它们.
例如,我要触发通知的 contentAction

1. Can you trigger an actions of notification?

Yes, you can. You can get Notification from StatusBarNotification, and then get PendingIntents for actions and use them.
For example, I want to trigger a contentAction of notification

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)通知,因此您需要像这样手动处理

This code will trigger sending of Broadcast message. BUT it will ignore a .setAutoCancel(true) of notification, so you need to handle it manually like this

    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 如何取消正在进行的通知?

我想到的第一种方法是使用

2. How NCleaner cancels ongoing notifications?

The first way which comes on my mind is usage of NotificationListenerService.snoozeNotification like this

if (sbn.packageName == TARGET_PACKAGE) {
        snoozeNotification(sbn.key, Long.MAX_VALUE - System.currentTimeMillis())
}

我有99%的把握确定NCLeaner使用此代码.因为它不支持O之前的设备使用此功能.

I'm 99% percent sure, that NCLeaner uses this code. Because it doesn't support this feature for pre-O devices.

注意.您不能只使用 Long.MAX_VALUE ,通知将被延后几秒钟,然后再次出现.在Pixel 2 8.1上进行了测试.

Note. You can't just use Long.MAX_VALUE, notification will be snoozed for a couple of seconds, and then appear again. Tested on Pixel 2 8.1.

否,您不能.只有通知所有者应用可以修改它.

No, you cannot. Only notification owner app can modify it.

我还尝试通过隐藏方法和 NotificationManager NotificationListenerService 的字段克服反射的限制.所有尝试的结果是:

I also tried to overcome limits with reflection via hidden methods and fields of NotificationManager and NotificationListenerService. The result of all attempts is:

由以下原因引起:java.lang.SecurityException:调用uid 10210给出了uid.10211拥有的com.ns.notificationsender包.

Caused by: java.lang.SecurityException: Calling uid 10210 gave package com.ns.notificationsender which is owned by uid 10211

因此,您的应用必须是系统之一,否则root可以帮助成功.但是我没有这样的设备.

So you app need to be system one, or maybe root can help to succeed. But I don't have such device.

这篇关于如何取消另一个应用程序的正在进行的通知?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆