SHOW ME THE CODE!

First, we will create the GcmBroadcastReceiver.java, that will be the entry point from a notification coming from GCM.

And configure it to AndroidManifest.xml as usual:

This following code works with Google Play Services — GCM < 8.3.0.

If you are working with the newest version of Google Play Services — GCM >= 8.3.0, the configuration change as following:

The GcmBroadcastReceiver will be a service that extends the GcmListenerService (I will keep the same name as declared in the previous version, even not being a BroadcastService but actually a Service).

And the AndroidManifest in Play-Services >= 8.3.0 is something like this:

The GcmBroadcastReceiver has only one objective: Receive the notification from GCM and start a new IntentService called PushReceiverIntentService, which will process the message. We can skip the use for PushReceiverIntentService, but using this approach we can easily change the provider with minimum effort, just replacing the GcmService to another class depending on your provider.

The second step is create the PushReceiverIntentService to handle this call:

I use in this example a Notification object:

Now, in the PushReceiverIntentService the magic happens: We are broadcasting a ordered event, using the sendOrderedBroadcast method. This event will be delivered in receivers registered in order of priority, so we can set which listeners will receive this event first. This sendOrderedBroadcast will emit the intent with the extras containing a Notification object and two methods: One for process the error delivering the Intent (In case of no one register to receive the event), and another for the completion, just to log or save something if you want to.

About EventBus, Otto, RxJava and related:

Using the sendOrderedBroadcast by the Context instead of LocalBroadcastManager, EventBus or RxJava, we guarantee that the app will receive the notification even if it was started by another process, like a SyncAdapter running in a different process than the application is. This cannot be done using another Bus related system. Also, we can wake up the application using a default broadcast receiver.

Now let's create the default receiver in case that nobody process the notification. To do this we need to create a BroadcastReceiver.

And register in AndroidManifest.xml with zero priority (to be the last one to receive the broadcast).

The zero priority is the main point: Any part of the application can receive the notification broadcast before this receiver just setting the priority to some value greater than zero. It also can abort the broadcast to not show the notification on status bar or leave it to this receiver show the notification.

Just like the GcmBroadcastReceiver, we just start a new IntentService:

The PushIntentService is the class that actually shows the notification on the status bar. So, if this message came to this class, it will be show always.

Until now, we have the first case in the diagram completed: