未触发 Android 通知操作 (PendingIntent)
Posted
技术标签:
【中文标题】未触发 Android 通知操作 (PendingIntent)【英文标题】:Android Notification Action is not fired (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 上有同样的问题。我有两个动作,第一个叫罚款,第二个根本不叫。你找到解决这个问题的方法了吗? 好的,我找到了解决方案。看看我的答案底部。 【参考方案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
构造函数的所有参数都是相同的。我为此找到了两种解决方案...
-
使用 Nik 提到的 FLAG_CANCEL_CURRENT。
将唯一的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);
【讨论】:
以上是关于未触发 Android 通知操作 (PendingIntent)的主要内容,如果未能解决你的问题,请参考以下文章
当应用程序处于打盹模式时,警报管理器触发的 Android 通知未触发
UNUserNotificationCenter Swift - 在特定情况下未触发本地通知