18

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

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

暂停()

unregisterReceiver(dataUpdateReceiver);

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

4

10 回答 10

17

这是很晚的答案,但它可能会帮助某人:

您应该根据要运行的意图选择正确的待处理意图。这里有些例子:

对于以下活动使用:

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

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

于 2016-06-17T02:38:54.670 回答
12

我在谷歌代码的这个线程中找到解决方案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);
于 2014-02-03T18:10:58.777 回答
7

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

  1. 使用Nik提到的 FLAG_CANCEL_CURRENT 。
  2. 传递一个独特requestCodependingIntent如下

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

就我而言,第二种方法解决了这个问题,因为我需要保持以前的通知处于活动状态。可能这会帮助有类似问题的人。

于 2014-12-06T12:28:03.690 回答
6

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

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

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

于 2014-10-15T15:49:27.633 回答
2

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

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,如果 Intent 的 action 等于 ,请在服务的 function 中停止播放ACTION_STOP

这应该可以解决问题;)

于 2013-04-29T18:51:08.167 回答
1

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

于 2021-05-25T08:34:09.147 回答
0

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

于 2013-02-12T21:34:30.230 回答
0

这里有多个问题:

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

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

于 2013-04-30T03:16:44.523 回答
0

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

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

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

于 2016-01-20T19:37:14.157 回答
0

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

resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                Intent.FLAG_ACTIVITY_CLEAR_TASK);
于 2016-04-20T14:27:24.360 回答