Android - 从通知中移除操作按钮

19

我想在点击通知操作按钮时(而不是整个通知),关闭这些操作按钮。(比如:一个有“停止”操作按钮的下载通知。当点击“停止”后,关闭“停止”按钮,并将contentText更改为“下载已取消”)

我能想到的唯一方法就是取消通知并通过相同的id发布另一个通知,但这似乎是一个丑陋的解决方案......

那么,是否有任何方法可以从通知中删除操作按钮?

(我认为没有必要放置任何代码,但如果需要的话,我可以提供...)

6个回答

29

如果你正在使用v4支持库中的NotificationCompat.Builder,你可以直接访问生成器的操作集合(不幸的是,没有提供公共mutators)。

以下操作可以解决问题(当然你必须更新re-notify):

NotificationCompat.Builder notifBuilder = NotificationCompat.Builder(context);
...
notifBuilder.mActions.clear();

2
我知道这篇文章很旧了,但我第一次遇到这个问题,说实话,这显然是通知API的一个非常糟糕的缺陷。要么你必须创建一个新的构建器实例,然后重新设置所有字段,这会降低代码的可读性,要么你使用你的解决方案 - 这是有效的 - 但非常丑陋,因为 mActions 应该是一个私有成员,并且Google没有提供清除操作的方法。真是可惜... - Mackovich
8
当你更新到Gradle插件版本3.3.0时,它会抱怨上面的语句:错误:Builder.mActions只能从同一库组(groupId = androidx.core)内访问[RestrictedApi]。 - Etienne Lawlor
7
"Builder.mActions只能从同一库组(groupId=com.android.support)内访问。" - Roshana Pitigala
3
尽管它以红色 (RestrictedApi) 显示,好像是一个错误,但它仍然可以工作。我不知道这样做的缺点。有没有人知道?从头开始创建 NotificationBuilder 对象可能不是一个好的解决方案,因为在更新时它 "可能" 会导致通知弹出/闪烁。所以,我仍然使用它,而且盲目地忽略 RestrictedApi... - frankish

3

我正在使用以下解决方法:

NotificationCompat.Builder builder = //existing instance of builder
//...
try {
    //Use reflection clean up old actions
    Field f = builder.getClass().getDeclaredField("mActions");
    f.setAccessible(true);
    f.set(builder, new ArrayList<NotificationCompat.Action>());
} catch (NoSuchFieldException e) {
    // no field
} catch (IllegalAccessException e) {
    // wrong types
}

从这里开始:https://code.google.com/p/android/issues/detail?id=68063 注意: 在混淆构建中,Proguard可能会破坏按钮清除。解决方法是在proguard-rules.pro中添加以下两行代码。
-keep class androidx.core.app.NotificationCompat { *; }
-keep class androidx.core.app.NotificationCompat$* { *; }

2

我曾经遇到过同样的问题,并找到了解决方法。 我创建了另一个构建器,并添加了两个“空”操作,如下所示:

builder.addAction(0, null, null);
builder.addAction(0, null, null);

我有几个按钮,每个按钮都需要调用一次(如果你有三个按钮,就要调用三次)。

当调用 Notify 方法时,它会移除这些按钮。


2
移除按钮的内容,但保留按钮曾经存在的空白空间。 - lostintranslation

1

尽管已接受的答案可行,但根据文档,执行此操作的设计方式是使用NotificationCompat.Extender类。例如,在Kotlin中:

private val clearActionsNotificationExtender = NotificationCompat.Extender { builder ->
    builder.mActions.clear()
    builder
}

private val notificationBuilder by lazy {
     NotificationCompat.Builder(context)
           .addAction(R.drawable.ic_play_arrow, "Play", playPendingIntent)
}

private fun updateNotification(){
     notificationBuilder
          .extend(clearActionsNotificationExtender) // this will remove the play action
          .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent)
}

与被接受的答案相同的错误:“Builder.mActions只能从同一库组内访问”。 - frankish

-1
NotificationCompat.Builder notifBuilder = NotificationCompat.Builder(context);

移除整个操作按钮:

builder.mActions.clear();

移除特殊操作按钮:

builder.mActions.remove(index);

最后:

notificationManager.notify(notificationID, builder.build());

-3
Android 提供了通知区域来提醒用户发生的事件。它还提供了一个通知抽屉,用户可以下拉以查看有关通知的更详细信息。
通知抽屉包括:
  • 视图(包含标题、详细信息和小图标)
  • 操作(如果用户点击通知抽屉视图可能发生的任何操作)
要设置通知以便可以更新它,请通过调用 NotificationManager.notify(ID, notification) 为其分配通知 ID。一旦您已经发布了通知,要更新此通知,请更新或创建一个 NotificationCompat.Builder 对象,从中构建一个 Notification 对象,并使用先前使用的相同 ID 发布通知。
mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    // Sets an ID for the notification, so it can be updated
    int notifyID = 1;
    mNotifyBuilder = new NotificationCompat.Builder(this)
    .setContentTitle("New Message")
    .setContentText("You are downloading some image.")
    .setSmallIcon(R.drawable.ic_stop)
   numMessages = 0;  
  // Start of a loop that processes data and then notifies the user
  ...
  mNotifyBuilder.setContentText("Download canceled")
    .setNumber(++numMessages);
  // Because the ID remains unchanged, the existing notification is
  // updated.
  mNotificationManager.notify(
        notifyID,
        mNotifyBuilder.build());
  ...

我已经知道了这一点...我也使用了NotificationCompat.builder.setAction()函数。但是我需要知道如何删除添加的动作,所以你的答案并没有帮到我 :( - BamsBamx
抱歉,我觉得我没有完全理解你的问题。也许这个链接 http://shashikawlp.wordpress.com/2013/05/08/android-jelly-bean-notifications-with-actions/ 可以帮到你。 - android_Muncher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接