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

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

问题描述

我发现了一个应用,它以某种方式隐藏了提醒通知,甚至包括正在进行的通知(由前台服务使用),名为 NCleaner .

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.

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

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.

为了测试正在进行的通知,我安装并运行了我的业余时间应用程序 (此处),它在应用程序的开头显示一个正在进行的通知,从 Android O 开始.实际上,它甚至可以隐藏通知操作系统,USB连接和调试(只需通过USB将设备连接到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,然后获取PendingIntents进行动作并使用它们.
比如我想触发一个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 如何取消正在进行的通知?

我想到的第一种方法是使用 NotificationListenerService.snoozeNotification 像这样

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 使用此代码.因为它不支持 pre-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.

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

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

Caused by: java.lang.SecurityException: Calling uid 10210给了包 com.ns.notificationsender,它属于 uid 10211

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天全站免登陆