未触发Android通知操作(PendingIntent)

时间:2013-02-12 21:00:54

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

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

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()中注册我的app接收器:

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

的onPause()

unregisterReceiver(dataUpdateReceiver);

现在,如果我从onPause() - 方法中删除取消注册,即使app / activity不在前台,也会收到广播。但这是正确的方法吗?我从网上的教程中得到了这个注册/取消注册的内容我认为..

10 个答案:

答案 0 :(得分:10)

我在Google代码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);

答案 1 :(得分:7)

这是非常晚的答案,但它可能对某人有所帮助:

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

活动使用以下内容:

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

您可能需要更改请求代码和Flags(如果需要)

答案 2 :(得分:6)

我今天遇到了这个问题。在我的情况下,由于pendingIntent构造函数的所有参数都相同,所以它使用了之前的intent实例的缓存intent extras。我找到了两个解决方案...

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

    PendingIntent pi = PendingIntent.getService(this, UNIQUE_ID, pi, 0);
    
  3. 在我的情况下,第二种方法解决了问题,因为我需要保持以前的通知存活。可能这会帮助有类似问题的人。

答案 3 :(得分:5)

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

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

如果其他答案都没有解决您的问题,那么希望这样做。通常棘手的问题是简单而愚蠢的结果。

答案 4 :(得分:1)

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

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

当然,如果意图的行为等于startCommand,请停止在服务的功能ACTION_STOP中播放。

这应该可以解决问题;)

答案 5 :(得分:0)

由于您在onPause中取消注册,因此当它在后台时您不会收到广播。将unregisterReceiver代码移动到onDestroy函数。只有在活动被销毁时才会调用此方法。或者,您可以在预期事件发生后取消注册。

答案 6 :(得分:0)

这里有多个问题:

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

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

答案 7 :(得分:0)

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

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

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

答案 8 :(得分:0)

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

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

答案 9 :(得分:0)

不要使用显式 Intent

就我而言,我在 BroadcastReceiver 类中创建了一个动态上下文注册 Service,用于监听通知操作。


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 是动态上下文注册的,因此您不必担心对隐式意图的限制