代码之家  ›  专栏  ›  技术社区  ›  android developer

如何取消正在进行的另一个应用程序通知?

  •  12
  • android developer  · 技术社区  · 7 年前

    背景

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

    我想知道这样的事是怎么回事。

    问题

    关于如何控制其他应用程序的通知,没有太多信息。仅限当前应用,并且由于某些原因,我未能取消正在进行的通知,但我已成功取消了正常的通知。

    我发现了什么

    我发现了 this sample 显示如何监视通知。在搜索了关于 NotificationListenerService ,我还发现了如何取消其他应用程序的特定通知。

    但是,它不适用于正在进行的通知。

    为了测试正常的通知,我刚刚给自己发了一封电子邮件,或者通过我的电脑在PushBullet应用程序上写了一些东西。

    为了测试正在进行的通知,我安装并运行了我的业余应用程序( here ),它在应用程序的开头显示一个正在进行的通知,从Android O开始。事实上,它甚至可以隐藏操作系统、USB连接和调试的通知(只需通过USB将设备连接到PC)。。。

    下面是我根据示例编写的代码,用于取消它收到的所有通知:

    通知ListenerExampleService.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>
    

    主要活动.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提供了多少通知?看看这些文档,它似乎可以做很多事情:阅读通知、取消通知、获取关于它们的各种信息。。。但我找不到其他功能:是否可以修改通知?改变它的优先权?为了避免它是一个提醒通知,只是在通知抽屉里?是否可以触发通知的操作?
    1 回复  |  直到 7 年前
        1
  •  2
  •   Ufkoku    7 年前

    我用这个代码来建立通知。它有标题,文字,图标, 诉讼 作为 广播消息 . 我希望这足以回答你的问题)

    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())
    

    一。你能触发通知动作吗?

    是的,你可以。 你可以得到 Notification StatusBarNotification ,然后获取 PendingIntent s表示动作并使用它们。
    例如,我想触发 诉讼 通知

    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。怎么 清理器 取消正在进行的通知?

    我首先想到的是 NotificationListenerService.snoozeNotification 这样地

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

    我百分之九十九的确信,NCLeaner使用这个代码。因为它不支持pre-O设备的这个特性。

    注意。你不能就这样 Long.MAX_VALUE ,通知将暂停几秒钟,然后再次出现。在像素28.1上测试。

    三。你能修改现有的通知吗?

    不,你不能。 只有通知所有者应用程序可以修改它。

    附笔。

    我也试图通过隐藏的方法和领域来克服反射的局限性 NotificationManager NotificationListenerService . 所有尝试的结果是:

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

    所以你的应用程序必须是系统一,或者也许根可以帮助成功。但我没有这种装置。

    推荐文章