按通知行动广播未在服务

时间:2017-01-14 12:25:42

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

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

(我知道也有可能在通知中使用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);
    
  3. 最后的结果是从不调用接收器的onReceive()。该服务是连续的,并且在通知操作发送广播时处于活动状态。由于我的性质无法调试广播,我在这里被阻止了。

1 个答案:

答案 0 :(得分:5)

您正在为Intent

创建此明确的PendingIntent
Intent i = new Intent(getBaseContext(), PlayerService.class);

由于几个原因,这项工作没有成功。显式Intent s - 为特定目标类创建的那些 - 不适用于动态注册的Receiver实例。此外,这是针对错误的类。具有Intent类目标的广播Service将彻底失败。 getBroadcast() PendingIntent需要BroadcastReceiver类作为目标。

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

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

然后,您将使用该String操作IntentFilter来注册接收者。

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

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

或者,您可以坚持使用显式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