2

I am trying to build a notification while a music playback service is running and use the notification to interact with the service (play, pause, stop) using the Broadcast mechanism.

(I know there is also the possibility to use PendingIntent.getService() as an action button in the notification, but I don't like this idea, because this would trigger the onStartCommand() of the service and I need to parse and analyze the Intent object to take action, which seems not as clean as the BroadcastReceiver approach, described below).

Let's illustrate what we have so far with some (truncated) code.

  1. We are creating a Notification object inside the service lifecycle, add an action button, and showing the notification using 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. Then we are registering a BroadcastReceiver inside the onCreate() of the service (and unregistering it in onDestroy of course; this is a more simplified example).

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

And the final result is that the onReceive() of the receiver is never called. The service is a continuous one and is active when the Notification action sends the broadcast. Since I have no way of debugging broadcasts due to their nature, I'm kind of blocked here.

Dzhuneyt
  • 8,437
  • 14
  • 64
  • 118
  • I used a mechanism in which Notification sends broadcast to a BroadcastReceiver 'A'. This BroadcastReceiver 'A' sends the broadcast to inner(inside service) BroadcastReceiver 'B'. In B's onReceive(), I handle the task. Here's a [sample github repo](https://github.com/rupinderjeet/NotificationActionButtonExample/tree/master/app/src/main/java/com/rupinderjeet/notificationactionbuttonexample) I made for another answer. **See mike's answer**. – rupinderjeet Jan 14 '17 at 12:46

1 Answers1

10

You're creating this explicit Intent for the PendingIntent:

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

This won't work for a couple of reasons. Explicit Intents - those created for a specific target class - do not work with dynamically registered Receiver instances. Also, this is targeting the wrong class. A broadcast Intent with a Service class target will just fail outright. A getBroadcast() PendingIntent would need a BroadcastReceiver class as the target.

With your current setup - the dynamically registered Receiver instance - you'll need to use an implicit Intent; i.e., an Intent with an action String, rather than a target class. For example:

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

You would then use that action String for the IntentFilter you're using to register the Receiver.

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

Do note that an IntentFilter can have multiple actions, so you can register a single Receiver to handle several different actions.


Alternatively, you could stick with using an explicit Intent, and statically register a BroadcastReceiver class in the manifest. For example:

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

In the manifest:

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

Then your Intent would be similar to:

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

However, this would require an additional step, as you would then need to somehow pass the broadcast info from NotificationReceiver to the Service; e.g., with an event bus, LocalBroadcastManager, etc.

Mike M.
  • 38,532
  • 8
  • 99
  • 95
  • 2
    Wow i've been trying to figure this out for hours that implicit intent is exactly what I was looking for Thank you! – Gallo2fire Nov 15 '17 at 03:37