Android > Advanced

Intercepting notifications

In this article, we'll run through the process of intercepting Batch Push and manually display notifications. Before we start, just keep in mind that you may want to display notifications yourself but you should do it only if you know what you're doing, Batch provides with a simple way to do it automaticaly so you should bypass it with caution.

This article uses Support V4 methods and classes : WakefulBroadcastReceiver, NotificationCompat and NotificationManagerCompat.

Enabling Manual display

If you don't want Batch to display notifications, you should activate the manual display mode, you shall do it in your Application.onCreate method:

@Override
public void onCreate()
{
    super.onCreate();

    Batch.Push.setGCMSenderId("Your GCM sender ID");
    Batch.Push.setManualDisplay(true);

    Batch.setConfig(new Config(API_KEY));
}

Be sure to do it in the onCreate method of your Application not your Activity because your Activity may not be started when you receive a push notification from GCM.

Registering your own receiver

To receive GCM intents, you'll have to register your own push receiver and service in addition to Batch one.

First create an IntentService and a BroadcastReceiver to subcribe to GCM notifications

Here's the IntentService (note that PushReceiver references your BroadcastReceiver):

public class PushService extends IntentService
{
    public PushService()
    {
        super("MyPushService");
    }

    @Override
    protected void onHandleIntent(Intent intent)
    {
        try
        {
            // Code to display notification will go there
        }
        finally
        {
            PushReceiver.completeWakefulIntent(intent);
        }
    }
}

And here's the BroadcastReceiver (note that PushService references the IntentService):

public class PushReceiver extends WakefulBroadcastReceiver
{

    @Override
    public void onReceive(Context context, Intent intent)
    {
        ComponentName comp = new ComponentName(context.getPackageName(), PushService.class.getName());
        startWakefulService(context, intent.setComponent(comp));
        setResultCode(Activity.RESULT_OK);
    }

}

Then register them into your application Manifest, near Batch ones:

<service android:name=".PushService" />

<receiver android:name=".PushReceiver" android:permission="com.google.android.c2dm.permission.SEND"> 
  <intent-filter> 
    <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
    <category android:name="YOUR-PACKAGE-NAME" /> 
  </intent-filter>  
</receiver>

Be sure to replace YOUR-PACKAGE-NAME with your actual package name, like you've done on Batch receiver.

Retreiving data from a Batch push

If you want to standard data contained in your Batch Push intent, Batch provides with easy way to retrieve them.

First of all, you can retrieve your push message and title (if you set one) this way:

@Override
protected void onHandleIntent(Intent intent)
{
    try
    {
        if( Batch.Push.shouldDisplayPush(this, intent) ) // Check that the push is valid
        {
            String alert = intent.getStringExtra(Batch.Push.ALERT_KEY);
            // Use the alert text to display the notification

            String title = intent.getStringExtra(Batch.Push.TITLE_KEY);
            if( title != null && !title.trim().isEmpty() )
            {
                // Use the title to display the notification
            }
        }
    }
    finally
    {
        PushReceiver.completeWakefulIntent(intent);
    }
}

If you use advanced features like deeplink, custom large icon or big picture, Batch provides with an object that make it easy to retrieve them. Here's how it works:

@Override
protected void onHandleIntent(Intent intent)
{
    try
    {
        if( Batch.Push.shouldDisplayPush(this, intent) ) // Check that the push is valid
        {
            BatchPushData pushData = BatchPushPayload.payloadFromReceiverIntent(intent);

            // Deeplink
            if( pushData.hasDeeplink() )
            {
                String deeplink = pushData.getDeeplink();
            }

            // Custom large icon
            if( pushData.hasCustomLargeIcon() )
            {
                String largeIconURL = pushData.getCustomLargeIconURL();
                // You are responsible of downloading the image at the given url and use it in your notification
            }

            // Big picture
            if( pushData.hasBigPicture() )
            {
                String bigPictureURL = pushData.getBigPictureURL();
                // You are responsible of downloading the image at the given url and use it in your notification
            }
        }
    }
    finally
    {
        PushReceiver.completeWakefulIntent(intent);
    }
}

You can also read the custom payload you've set while creating the campaign or sending a transactional push:

@Override
protected void onHandleIntent(Intent intent)
{
    try
    {
        if( Batch.Push.shouldDisplayPush(this, intent) ) // Check that the push is valid
        {
            // Custom payload fields. Root keys are always of the string type, due to GCM limitations.
            // Here we'll read the "article_id" key of the following custom payload : {"article_id": 2}
            String articleId = intent.getStringExtra("article_id");

            // If you have more complex objets, you'll need to parse them using a JSON parser
            // Matching custom payload: {"user_data": {"id": 2}}
            JSONObject userData = new JSONObject(intent.getStringExtra("user_data"));
            int userId = userData.getInt("id");
        }
    }
    finally
    {
        PushReceiver.completeWakefulIntent(intent);
    }
}

Note: If you want to read your custom payload, this should be done directly from the intent using getStringExtra(). While you might be tempted to read the extra with the key Batch.Push.PAYLOAD_KEY, this key is not applicable in this context, and will not return anything.

That's it, you are now ready to handle push messages that come from Batch Push servers. You can either:

Performing action before push display

If you want to simply do an action based on the received intent but don't want to display the notification yourself, you can do it quite simply:

@Override
protected void onHandleIntent(Intent intent)
{
    try
    {
        if( Batch.Push.shouldDisplayPush(this, intent) ) // Check that the push is valid
        {
            // Your code goes here

            // Display the notification
            Batch.Push.displayNotification(this, intent);
        }
    }
    finally
    {
        PushReceiver.completeWakefulIntent(intent);
    }
}

Displaying your own notification

If you want to display your own custom notification, you can do it yourself using the Notification.Builder API. Batch provides with helpers that you'll need to use if you want to have the open rate available from our dashboard. Here's how to do it:

@Override
protected void onHandleIntent(Intent intent)
{
    try
    {
        if( Batch.Push.shouldDisplayPush(this, intent) ) // Check that the push is valid
        {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
            // Build your own notification here...

            // Assuming you have a drawable named notification_icon, can otherwise be anything you want
            builder.setSmallIcon(R.drawable.notification_icon) 
                .setContentTitle(intent.getStringExtra(Batch.Push.TITLE_KEY))
                .setContentText(intent.getStringExtra(Batch.Push.ALERT_KEY));

            // Create intent
            Intent launchIntent = yourFunction(); // Create your own intent
            Batch.Push.appendBatchData(intent, launchIntent); // Call this method to add tracking data to your intent to track opens

            // Finish building the notification using the launchIntent
            PendingIntent contentIntent = PendingIntent.getActivity(this, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            builder.setContentIntent(contentIntent);

            // Display your notification
            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

            // "id" is supposed to be a unique id, in order to be able to update the notification if you want.
            // If you don't care about updating it, you can simply make a random it, like below
            int id = (int) (Math.random() * Integer.MAX_VALUE);
            notificationManager.notify(id, builder.build());

            // Call Batch to keep track of that notification
            Batch.Push.onNotificationDisplayed(this, intent);
        }
    }
    finally
    {
        PushReceiver.completeWakefulIntent(intent);
    }
}

Be sure to use the PendingIntent.FLAG_UPDATE_CURRENT flag when getting your pending intent. Failure to do so will make open tracking unreliable.