Chapter 9. Push Notifications and Analytics

We will start the chapter by talking about push notifications. You will learn how to implement custom solutions with notifications using Google Cloud Messaging, both on the server side and app side. Then, we will add notifications with Parse to our example. To finish with notifications, we will display our custom notifications using NotificationCompat.

In the second half of the chapter, we will talk about analytics. Having analytics to track what the user does in our app is essential to know how the user behaves, allowing us to identify patterns and improve the experience. We will implement one example with Parse and take an overview of the most popular solutions in the market.

  • Push notifications
    • Sending and receiving with GCM
    • Notifications from Parse
    • NotificationCompat
  • Analytics
    • Analytics with Parse
  • Error report

Push notifications

Push notifications are important to engage users and provide real-time updates. They are useful to remind the user that there is an action pending. For instance, in the Qkr! app created by MasterCard, one can order food and drink in some restaurants, and if the user hasn't paid after a considerable period of time, they send a notification to remind the user that he/she needs to pay before leaving the restaurant.

They also work very well when we need to tell the user that we have new content or that other users have sent them a message. Any change that happens on the server side and requires informing the user is the perfect scenario to use notifications.

Notifications can also be sent locally from our own app; for example, we can schedule an alarm and show a notification. They don't necessarily have to be sent from a server.

They are shown at the top of the screen in the status bar, in a place called the notification area.

Push notifications

The minimum information required for a notification is an icon, a title, and detail text. With the arrival of material design, we can customize the notifications in different ways; for instance, we can add different actions to them:

Push notifications

If we scroll down from the top of the screen, we will show the notification drawer where we can see all the information displayed by the notifications:

Push notifications

Notifications shouldn't be used as part of two-way channel communication. If our app needs constant communication with the server, as in the case of messaging apps, we should consider using sockets, XMPP, or any other messaging protocol. In theory, notifications are not reliable, and we can't control when exactly they will be received.

However, don't abuse notifications; they are a good reason for a user to uninstall your app. Try to keep them to a minimum and use them only when necessary.

You can assign a priority level to a notification, and Android Lollipop onward, you can filter the notifications you want to receive based on this priority level.

These are the key points and concepts you should have in mind while working with notifications. Before going into more theory, we will practice sending notifications to our app.

Sending and receiving notifications using GCM

There are different solutions on the market to send push notifications; one of these is Parse, which has a friendly control panel where anyone can easily send push notifications. We will use Parse as an example, but first, it's good to understand how this works internally and how we can build our own system to send notifications.

GCM (Google Cloud Messaging) uses push notifications, which we will send to our mobile. Google has servers called GCM connection servers that handle this process. If we want to send a push notification, we need to tell these servers first, and they will send it to our device later. We need to create a server or use a third-party server, which will communicate with the GCM servers over HTTP or XMPP as the communication can be done using both protocols.

Sending and receiving notifications using GCM

As we said earlier, we can't control exactly when a message is received because we have no control over the GCM server. It queues the message and dispatches it when the device is online.

To create our custom solution, the first thing we need to do is enable the messaging services on our app from the Google developers' website at https://developers.google.com/mobile/add?platform=android.

Sending and receiving notifications using GCM

After you create the app, enable GCM messaging, and you will be provided with a Sender ID and a Server API Key. The sender ID was previously known as project number.

If we want to receive GCM messages, we need to register our client, which is our mobile app, with this project. To do this, our app will use the GCM API to register and obtain a token as confirmation. When this is done, the GCM servers will know that your device is ready to receive push notifications from this particular project/sender.

Sending and receiving notifications using GCM

We need to add the play services to use this API:

 compile "com.google.android.gms:play-services:7.5.+"

The registration is done through the Instance ID API, calling instanceID.getToken with the SenderID as a parameter:

InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

We need to call this asynchronously and keep a Boolean variable in our app to remember whether we have been successfully registered. Our token can change with time, and we'll know when it happens with the onRefreshToken() callback. The token needs to be sent to our server:

@Override
public void onTokenRefresh() {
  //Get new token from Instance ID with the code above
  //Send new token to our Server
}

Once this is done, we need to create a GCMListener and add some permissions to the Android manifest:

<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
  android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />

<application ...>
  <receiver
    android:name="com.google.android.gms.gcm.GcmReceiver"
    android:exported="true"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
      <action android:name="com.google.android.c2dm.intent.RECEIVE" />
      <category android:name="com.example.gcm" />
    </intent-filter>
  </receiver>
  <service
    android:name="com.example.MyGcmListenerService"
    android:exported="false" >
    <intent-filter>
      <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
  </service>
  <service
    android:name="com.example.MyInstanceIDListenerService"
    android:exported="false">
    <intent-filter>
      <action android:name="com.google.android.gms.iid.InstanceID"/>
    </intent-filter>
  </service>
</application>

</manifest>

GCMListener will contain the onMessageReceived method, which will be called when we receive any message.

This is all we need from the client side; for the server side, we won't go into details in this book because it totally depends on the technology and the language chosen. There are different code snippets and scripts to send the notifications for Python, Grails, Java, and so on, which are easy to find on the Web.

We don't really need a server to send a notification because we can communicate directly with GCM. All we need to do is send a POST request to https://gcm-http.googleapis.com/gcm/send. This can easily be done using any online POST-sending service, such as http://hurl.it or Postman, a Google Chrome extension used to send network requests. This is how our request needs to look:

Content-Type:application/json
Authorization:key="SERVER_API_LEY"
{
  "to" : "RECEIVER_TOKEN"
  "data" : {
    "text":"Testing GCM"
  },
}
Sending and receiving notifications using GCM

Continuing with MasteringAndroidApp, we will implement push notifications with Parse.

Push notifications with Parse

For our example, we will stick to Parse. The main reason is that we don't need to worry about the server side, and we don't have to create an app in the Google developer console with this solution. Another good reason is that it has a nice built-in control panel to send this notification, and we can target different users if we have been tracking users with different parameters in advance.

Push notifications with Parse

With Parse, we don't need to create a GCM listener. Instead, it uses a service that is already included in the Parse library, and we just need to register a subscriber for this service. All we need to do is add the permissions and receivers to our app, and we are ready to go:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:protectionLevel="signature" android:name="com.packtub.masteringandroidapp.permission.C2D_MESSAGE" />
<uses-permission android:name="com.packtpub.masteringandroidapp.permission.C2D_MESSAGE" />

Ensure that the last two permissions match your package name. The receivers need to go inside the application tag:

<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
    <action android:name="android.intent.action.USER_PRESENT" />
  </intent-filter>
</receiver>

<receiver android:name="com.parse.ParsePushBroadcastReceiver"
  android:exported="false">
  <intent-filter>
    <action android:name="com.parse.push.intent.RECEIVE" />
    <action android:name="com.parse.push.intent.DELETE" />
    <action android:name="com.parse.push.intent.OPEN" />
  </intent-filter>
</receiver>

<receiver android:name="com.parse.GcmBroadcastReceiver"
  android:permission="com.google.android.c2dm.permission.SEND">
  <intent-filter>
    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
    <category android:name="com.packtpub.masteringandroidapp" />
  </intent-filter>
</receiver>

</application>

To listen for notifications, we can register a subscriber in the OnCreate method of our Application class:

ParsePush.subscribeInBackground("", new SaveCallback() {
  @Override
  public void done(com.parse.ParseException e) {
    if (e == null) {
      Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
    } else {
      Log.e("com.parse.push", "failed to subscribe for push", e);
      }
  }
});

Now, it's ready. Simply go to the Parse web, select the Push tab, and click on + Send a push. You can specify the audience, if you want to send it immediately or with a delay, and other parameters. It will keep a track of the push sent and indicate the people it was sent to.

Push notifications with Parse

If you see 1 in the Pushes Sent column and then take a look at the notification in your device, all is correct. The notification in your device should look as follows:

Push notifications with Parse

Using NotificationCompat

At the moment, we can see the default notification, which is created by the Parse receiver. However, we can set our own receiver and create nicer notifications with NotificationCompat. This component was introduced in the support v4 library, displaying notifications with the latest features in Android L and M as well as in previous versions until API 4.

In a few words, what we need to do is create a notification with the help of NotificationCompat.Builder and pass this notification to the system with NotificationManager.notify():

public class MyNotificationReceiver  extends BroadcastReceiver {
  
  @Override
  public void onReceive(Context context, Intent intent) {
    Notification notification = new NotificationCompat.Builder(context)
    .setContentTitle("Title")
    .setContentText("Text")
    .setSmallIcon(R.drawable.ic_launcher)
    .build();
    NotificationManagerCompat.from(context).notify(1231,notification);
  }
  
}

This will show our notification. The title, text, and icon are mandatory; if we don't add these three properties, the notification won't be shown. To start using our custom receiver, we need to specify in the manifest the register that we want to use, instead of the Parse push receiver:

receiver android:name="com.packtpub.masteringandroidapp.MyNotificationReceiver" android:exported="false">
  <intent-filter>
    <action android:name="com.parse.push.intent.RECEIVE" />
    <action android:name="com.parse.push.intent.DELETE" />
    <action android:name="com.parse.push.intent.OPEN" />
  </intent-filter>
</receiver>

We discussed how to show custom notifications with NotificationCompat. Notifications have their own design guidelines, and they are an important part of material design. It is recommended to have a look at these guidelines and keep them in mind while using this component in your app.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset