【问题标题】:Broadcast by Notification Action not handled in BroadcastReceiver inside Service通过通知操作广播未在服务内的 BroadcastReceiver 中处理
【发布时间】:2017-01-14 22:02:25
【问题描述】:

我正在尝试在音乐播放服务运行时构建通知,并使用通知通过广播机制与服务交互(播放、暂停、停止)。

(我知道也可以使用 PendingIntent.getService() 作为通知中的操作按钮,但我不喜欢这个想法,因为这会触发服务的 onStartCommand() 和我需要解析和分析 Intent 对象以采取行动,这似乎不如 BroadcastReceiver 方法干净,如下所述)。

让我们用一些(截断的)代码来说明我们目前所拥有的。

  1. 我们正在服务生命周期内创建一个通知对象,添加一个操作按钮,并使用startForeground()显示通知。

    ...
    Intent i = new Intent(getBaseContext(), PlayerService.class);
    PendingIntent piStop = PendingIntent.getBroadcast(getBaseContext(), 1, i, PendingIntent.FLAG_ONE_SHOT);
    NotificationCompat.Action actionStopPlayback = new NotificationCompat.Action(R.drawable.ic_stop_white_36dp, "Stop playback", piStop);
    notification.addAction(actionStopPlayback);
    ...
    
  2. 然后我们在服务的 onCreate() 中注册一个 BroadcastReceiver(当然在 onDestroy 中取消注册;这是一个更简化的示例)。

    IntentFilter intentFilter = new IntentFilter();
    registerReceiver(new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             Log.d(getClass().toString(), "Broadcast received");
         }
    }, intentFilter);
    

最后的结果是接收者的onReceive()永远不会被调用。该服务是连续的,并且在通知操作发送广播时处于活动状态。由于广播的性质,我无法调试广播,所以我在这里有点受阻。

【问题讨论】:

  • 我使用了一种机制,通知将广播发送到广播接收器“A”。此 BroadcastReceiver 'A' 将广播发送到内部(内部服务)BroadcastReceiver 'B'。在 B 的 onReceive() 中,我处理任务。这是我为另一个答案所做的sample github repo查看 Mike 的回答

标签: android android-service android-notifications android-broadcastreceiver


【解决方案1】:

您正在为PendingIntent 创建这个明确的Intent

Intent i = new Intent(getBaseContext(), PlayerService.class);

这不起作用有几个原因。显式 Intents - 为特定目标类创建的那些 - 不适用于动态注册的 Receiver 实例。此外,这是针对错误的班级。带有Service 类目标的广播Intent 将完全失败。 getBroadcast() PendingIntent 需要 BroadcastReceiver 类作为目标。

使用您当前的设置 - 动态注册的 Receiver 实例 - 您需要使用隐式 Intent;即,带有动作StringIntent,而不是目标类。例如:

Intent i = new Intent("com.hasmobi.action.STOP_PLAYBACK");

然后您将使用该操作String 来注册您用于注册接收器的IntentFilter

IntentFilter intentFilter = new IntentFilter("com.hasmobi.action.STOP_PLAYBACK");

请注意,IntentFilter 可以有多个操作,因此您可以注册一个接收器来处理多个不同的操作。


或者,您可以坚持使用显式Intent,并在清单中静态注册BroadcastReceiver 类。例如:

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

在清单中:

<receiver android:name=".NotificationReceiver" />

那么您的Intent 将类似于:

Intent i = new Intent(PlayerService.this, NotificationReceiver.class);

但是,这需要一个额外的步骤,因为您需要以某种方式将广播信息从NotificationReceiver 传递到Service;例如,使用事件总线、LocalBroadcastManager 等。

【讨论】:

  • 哇,我花了好几个小时才弄清楚隐含的意图正是我想要的,谢谢!
猜你喜欢
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
  • 2014-06-02
  • 1970-01-01
相关资源
最近更新 更多