【问题标题】:Android Notification Action is not fired (PendingIntent)未触发 Android 通知操作 (PendingIntent)
【发布时间】:2013-01-28 07:14:42
【问题描述】:

我正在尝试在我的音乐播放器应用中添加通知操作项。当流启动时,应触发通知,并且应在通知中显示流的停止按钮。到目前为止,通知工作正常,我遇到了停止操作项的问题。以下是它在启动流的服务中的声明方式:

Intent stopIntent = new Intent(this, MusicPlayerNew.class);
stopIntent.putExtra("STOP", "STOP");
PendingIntent stopPendingIntent = PendingIntent.getActivity(this, 0,
                stopIntent, PendingIntent.FLAG_UPDATE_CURRENT, null);
mBuilder.addAction(R.drawable.ic_stat_stop, "Stop", stopPendingIntent);

现在在我的活动的 onResume() 方法中,我使用 getIntent().getStringExtra() 检查“STOP”额外内容,但我通过 getIntent() 检索到的意图没有设置额外内容:(

我还尝试检查是否发送广播(我有一个广播接收器,用于从服务到活动进行通信)

Intent stopIntent2 = new Intent(MusicPlayerNew.STOP_MEDIAPLAYER);
PendingIntent stopPendingIntent2 = PendingIntent.getBroadcast(this, 0,
                stopIntent2, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.addAction(R.drawable.ic_stat_stop, "Stop", stopPendingIntent2); 

现在,如果活动当前处于前台,则此方法有效。如果活动在后台,停止按钮什么也不做:(

编辑: 我的 Activity 中有 BroadcastReceiver 作为私有类

private class DataUpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
..
}}

在 onResume() 中为这个接收者注册我的应用程序:

intentFilter = new IntentFilter(STOP_MEDIAPLAYER);
registerReceiver(dataUpdateReceiver, intentFilter);

onPause()

unregisterReceiver(dataUpdateReceiver);

现在,如果我从 onPause() 方法中删除取消注册,即使应用程序/活动不再处于前台,也会收到广播。但这是正确的方法吗?我认为我从网上的教程中得到了这个注册/取消注册的东西..

【问题讨论】:

  • 我在 KitKat 上有同样的问题。我有两个动作,第一个叫罚款,第二个根本不叫。你找到解决这个问题的方法了吗?
  • 好的,我找到了解决方案。看看我的答案底部。

标签: android android-intent android-activity android-notifications android-pendingintent


【解决方案1】:

这是一个很晚的答案,但它可能对某人有所帮助:

您应该根据要运行的意图选择正确的待处理意图。以下是一些示例:

对于活动,请使用以下:

Intent i = new Intent(this, YourActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);

对于服务,请使用以下:

Intent i = new Intent(this, YourService.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);

对于广播接收器,请使用以下:

Intent i = new Intent(this, YourReciver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);

如果需要,您可能需要更改请求代码和标志

【讨论】:

  • 我将意图发送到服务,但随后重构为 BroadcastReceiver。
  • 它可能对某人有所帮助。它帮助我意识到我正在使用 getService,但需要更改为 getActivity.. 谢谢!
【解决方案2】:

我在谷歌代码https://code.google.com/p/android/issues/detail?id=61850的这个帖子中找到了解决方案

要修复它,您必须将 PendingIntent.FLAG_CANCEL_CURRENT 标志添加到您的 PendingIntent

PendingIntent stopPendingIntent2 = PendingIntent.getBroadcast(this, 0,
            stopIntent2, PendingIntent.FLAG_CANCEL_CURRENT);

【讨论】:

  • 谢谢。当我遇到类似的问题时,这真的让我发疯了。这成功了。可能重新启动设备也会有所帮助,但这很干净。
【解决方案3】:

我今天遇到了这个问题。在我的情况下,它使用了来自先前意图实例的缓存意图附加内容,因为 pendingIntent 构造函数的所有参数都是相同的。我为此找到了两种解决方案...

  1. 使用 Nik 提到的 FLAG_CANCEL_CURRENT。
  2. 将唯一的requestCode 传递给pendingIntent,如下所示

    PendingIntent pi = PendingIntent.getService(this, UNIQUE_ID, pi, 0);
    

就我而言,第二种方法解决了这个问题,因为我需要保持之前的通知有效。可能这会对有类似问题的人有所帮助。

【讨论】:

  • 我认为不需要 UNIQUE_ID,除非与其他服务发生冲突。
【解决方案4】:

我今天遇到了这个问题,它是由于没有注册或添加到 AndroidManifest.xml 的活动引起的。我以为我有它,但它不是。此外,尝试使用其意图调用该操作时没有记录任何错误。

我通过创建一个意图然后在不使用通知的情况下调用 startAcitivty(intent) 来解决这个问题。然后它给了我一个错误,说明清单中可能缺少该活动。

如果其他答案都不能解决您的问题,那么希望这能解决。通常棘手的问题是一些简单而愚蠢的事情的结果。

【讨论】:

    【解决方案5】:

    除了使用广播接收器之外,您还应该使用服务并以这种方式在服务中声明新操作:

    public final String ACTION_STOP = "yourpackagename.ACTION_STOP";
    

    然后像这样创建你的意图:

    Intent stopIntent = new Intent(this, YourService.class).setAction(YourService.ACTION_STOP);
    PendingIntent stopPendingIntent = PendingIntent.getService(this, 0, stopIntent, 0);
    

    当然,如果 Intent 的操作等于 ACTION_STOP,则在服务的函数 startCommand 中停止播放。

    这应该可以解决问题;)

    【讨论】:

      【解决方案6】:

      不要使用显式 Intent

      在我的例子中,我在 Service 类中创建了一个动态上下文注册的 BroadcastReceiver 来监听通知操作。

      
      class MyService:Service(){
      
      private val receiver: BroadcastReceiver = NotificationActionReceiver()
      ...
      
      inner class NotificationActionReceiver : BroadcastReceiver() {
              override fun onReceive(context: Context, intent: Intent) {
                  ...
              }
       }
      
      override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
              ...
              registerReceiver(receiver,IntentFilter("SOME_ACTION"))
              return super.onStartCommand(intent, flags, startId)
       }
      
      override fun onDestroy() {
              ...
              unregisterReceiver(receiver)
              super.onDestroy()
       }
      
      

      PendingIntent 带有显式 Intent

      
      val nextIntent = Intent(this, NotificationActionReceiver::class.java) //Explicit Intent
      val nextPendingIntent: PendingIntent= PendingIntent.getBroadcast(this,0x11,nextIntent, PendingIntent.FLAG_CANCEL_CURRENT)
      

      但是,使用此设置,BroadcastReceiver 从未触发。

      为了让它发挥作用,我需要用隐含的意图替换我的显式意图

      所以我所做的只是,

      
      val nextIntent = Intent("SOME_ACTION") //Implicit Intent
      val nextPendingIntent: PendingIntent= PendingIntent.getBroadcast(this,0x11,nextIntent, PendingIntent.FLAG_CANCEL_CURRENT)
      
      

      注意:由于 BroadcastReceiver 是动态注册的上下文,您不必担心隐式意图的限制

      【讨论】:

      • 谢谢老兄,浪费时间来解决这个问题
      【解决方案7】:

      您在后台收不到广播,因为您正在取消注册 onPause。将 unregisterReceiver 代码移至 onDestroy 函数。这只会在活动被销毁时调用。或者,您可以在预期事件发生后取消注册。

      【讨论】:

        【解决方案8】:

        这里有多个问题:

        第 1 部分:为什么您的意图没有收到额外的“STOP”? 虽然在您提供的代码中没有看到,但我想确认您是否使用标志 FLAG_ACTIVITY_SINGLE_TOP 来表示通知意图?如果是这样,您在活动中收到的意图将是启动活动的意图,因此“停止”额外内容将不可用。在这种情况下,您需要扩展onNewIntent()(发送新意图的位置)。 More info here.
        如果你没有使用过 FLAG_ACTIVITY_SINGLE_TOP,那么这意味着在点击通知时会创建一个新的活动,在这种情况下,Intent 必须具有“STOP”参数。如果您能提供所有相关代码,我可以更好地帮助您。

        第 2 部分:使用广播接收器 正如您已经发现的那样,这不是直截了当的。您需要在 onDestroy 中注销,如果您的活动被用户关闭,则 onDestroy 可能会被调用,并且您的广播接收器可能在用户点击通知时未激活。如果您根本不取消注册,它似乎可以正常工作,但这是内存泄漏,GC 可能随时清理,这可能导致您的程序崩溃,即,您必须取消注册。如果您需要使用广播接收器方法,则需要有一个服务来执行此操作,并且服务有其自身的缺陷 -> 由系统重启、电池耗尽等。我强烈建议您使用第一种方法。

        【讨论】:

          【解决方案9】:

          我遇到了一个非常相似的问题,但解决方案却截然不同。如果您在 manifest.xml 文件中声明了<service android:enabled="false"></service>,则也不会触发待处理的意图。

          android:enabled="false"替换为android:enabled="true"

          这可能不是问题的直接问题。但是,如果您在 android studio 中使用默认模板创建服务,它会自动将这些属性添加到服务中。

          【讨论】:

            【解决方案10】:

            对我来说,解决方案是设置意图标志:

            resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                            Intent.FLAG_ACTIVITY_CLEAR_TASK);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-11-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多