Adding AirBop to Your App

Tutorial on how to add AirBop and Google Cloud Messaging to an Android app.

This article is a general overview of integrating Google Cloud Messaging into your Android app, registering your app with the AirBop servers, and responding to AirBop push notifications.

While there are some details specific to AirBop, the developer documentation for Google Cloud Messaging still applies. For an in-depth reference, visit Google's developer documentation for Google Cloud Messaging for Android.

The following items are required to work with AirBop's servers and discussed in this article:

  • Your Google Project Number (from Google's API console)
  • Your AirBop App Key
  • Your AirBop App Secret
  • Your Java Package Name

Note: If you haven't already, you'll first want to read the article Getting Started with AirBop which describes the steps needed to start using AirBop. To see how all of these bits and pieces fit together, refer to the AirBop-Client sample on GitHub.

Get the GCM jar

Using the Android SDK Manager, install Extras > Google Cloud Messaging for Android Library. This will create a series of gcm subdirectories in the SDK_ROOT/extras/google/ folder. The 'gcm.jar' file is located in the gcm-client/dist subdirectory.

Note: The Google Cloud Messaging for Android Library is only available in version 20 or higher of the SDK Manager.

Copy the GCM jar into your Application

Copy the gcm.jar file from the SDK's gcm-client/dist directory to your application's libs directory.

Min SDK Version

GCM requires Android 2.2 or later, which translates to Android SDK version 8. This means that you will need to set minSdkVersion to 8 or higher in your application manifest. In other words, you will need at least the following declaration (where xx denotes the target version for your application):

<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="xx"/>

Custom Permission for GCM Messages

Add a custom permission to your manifest so that your application will receive the appropriate GCM messages, replacing "my_app_package" with your package name:

<permission android:name="my_app_package.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="my_app_package.permission.C2D_MESSAGE" />

Note: The above permission is not required if you are targeting Android version 4.1 or above (minSdkVersion 16).

Additional GCM Permissions

Add the following GCM related permissions:

<!-- App receives GCM messages. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<!-- GCM connects to Google Services. -->
<uses-permission android:name="android.permission.INTERNET" /> 

<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />

<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

The GCM Broadcast Receiver

You need to declare a broadcast receiver to handle the 'RECEIVE' and 'REGISTRATION' intents sent by GCM. You can use the GCMBroadcastReceiver provided in the GCM library by adding this declaration to your manifest:

<receiver android:name="com.google.android.gcm.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="my_app_package" />
  </intent-filter>
</receiver>

The 'SEND' permission ensures that only intents sent by the GCM system framework are sent to the receiver.

Note: remember to replace my_app_package with your app's package name.

The GCM Intent Service

The GCM library assumes that you have a class named GCMIntentService with overridden methods to handle various GCM events.

The overridden methods will be called by the standard GCMBroadcastReceiver provided in the GCM library. Unless you're using a custom BroadcastReceiver, you need to declare this intent service in your application manifest.

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

To be compatible with GCMBroadcastReceiver, your GCMIntentService class must be a subclass of com.google.android.gcm.GCMBaseIntentService, and must contain a public constructor. The contents of this class will be discussed in the next section.

Example Manifest

The following is an example containing the excerpts described above:

<manifest package="com.airbop.sample.gcm" ...>

  <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16"/>
  <uses-permission android:name="android.permission.INTERNET" />
  <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.airbop.sample.gcm.permission.C2D_MESSAGE" 
        android:protectionLevel="signature" />
  <uses-permission android:name="com.airbop.sample.gcm.permission.C2D_MESSAGE" />

  <application ...>
    <receiver android:name="com.google.android.gcm.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.airbop.sample.gcm" />
      </intent-filter>
    </receiver>
    <service android:name=".GCMIntentService" />
  </application>
</manifest>

To register with GCM, your app just needs to call the following method and pass it your Google Project Number as a string:

GCMRegistrar.register(context, "<<your project number>>");

For example, if your project number was 827171612957 you could add the following code to your activity's onCreate() method to register the device with your GCM project:

// Verify that the device supports GCM
GCMRegistrar.checkDevice(this);

// Verify the application manifest contents - remove when ready to publish
GCMRegistrar.checkManifest(this);

// Check whether the device is already registered
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {

	final String googleProjectNumber = "827171612957";

    // Not registered yet, so register the device with GCM
    GCMRegistrar.register(this, googleProjectNumber); 
} else {
    Log.v(TAG, "Already registered");
}

onRegistered(Context context, String regId)

This method is called after the registration intent is received. The registration ID that was assigned to the device by GCM is passed as the second parameter.

The registration ID is what uniquely identifies the device on the GCM and AirBop servers.

At this point your application has registered with the GCM servers, but has not registered with AirBop. This is normally where you would send the registration information to the AirBop server and complete the registration process.

The following is an example of what your onRegistered method may look like:

@Override
protected void onRegistered(Context context, String registrationId) {
    // Now that we have the registration id from GCM, we have
    // everything we need to register with the AirBop servers
    registerWithAirBop(registrationId);
}

onUnregistered(Context context, String regId)

This method is called after the device has been unregistered from GCM. If the device is still registered on the AirBop servers, it will need to unregister from AirBop well.

The following is an example of what your onUnregistered method may look like:

@Override
protected void onUnregistered(Context context, String registrationId) {
    // If we are still registered with AirBop it is time to unregister
    if (GCMRegistrar.isRegisteredOnServer(context)) {
        unregisterFromAirBop(context, registrationId);
    } else {
        // We are not registered so there's nothing to do
    }
}

onMessage(Context context, Intent intent)

This method is called when a message is sent from the AirBop server to GCM, and delivered to the device. The contents of the message are passed as extras in the intent.

AirBop's server console allows you to use either a predefined message format, or custom JSON for the data passed in the message.

When using AirBop's standard message format, the intent extras are defined as the following string values:

  • title - The title of the message sent from the AirBop server.
  • message - The message text sent from the AirBop server.
  • url - An optional URL associated with the message.

Below is an example of how to access the standard extras from the intent:

Bundle bundle = intent.getExtras();
        
if (bundle != null) {
    String title = bundle.getString("title");
    String message = bundle.getString("message");
    String url = bundle.getString("url");
    if ((title != null) && (message != null)) {
        // Do something with the message data, such as call a function to show a notification
        generateNotification(context, title, message, url);
    }
}

Here is an example of what the JSON data looks like for a standard message:

{
    "title": "Half Pint Special",
    "message": "Humulous Ludicrous is on tap today only!",
    "url": "http://www.somebeerpagesomewhere.com"
}

If you choose to send custom JSON data instead, all of the key-value pairs in the intent extras are up to you.

Here is an example of custom JSON data entered in AirBop's server console:

{
    "team1": "FC Bayern Munich",
    "team2": "Manchester City F.C.",
    "score1": 2,
    "score2": 0
}

onError(Context context, String errorId)

This method is called when an error is returned by GCM when the device tries to register or unregister. This allows you to evaluate any problems that are encountered.

onRecoverableError(Context context, String errorId)

This method is called when a device tries to register or unregister, but the GCM servers are unavailable. The GCM library will automatically retry unless this optional method is overridden and returns false.

Generally you should only override this method if you want to display the message or cancel any further attempts.

Registering with the AirBop servers can be accomplished by posting the correct information to the following URL:

http://www.airbop.com/api/v1/register

Required Headers

When registering or unregistering with the AirBop servers the following headers are required:

  • x-app-key
    Your AirBop App Key, which is generated automatically by AirBop when you create a new app. It is shown in the AirBop Dashboard on the Info and Edit tabs.
  • x-timestamp
    The timestamp of the message. Sent as the number of seconds since the Epoch, January 1, 1970 00:00 UTC.
  • x-signature
    An SHA-256 hash constructed exactly as follows:

    "POST" + request_uri + AIRBOP_APP_KEY + timestamp + request.body + AIRBOP_APP_SECRET
    
    An example implementation of this can be found in the AirBop-Client sample.
  • Content-Type
    This header controls which format the AirBop servers will expect the body to be in. It can be either:

    application/json
    
    or:

    application/x-www-form-urlencoded
    

Parameters

The GCM registration ID must be sent to AirBop in order to register the device with the AirBop servers. This information is sent to AirBop in the request body, along with several optional parameters.

The content type passed to the AirBop server controls what format the body is expected in. The preferred method is JSON (application/json).

Examples of how to construct the request body and post to the AirBop servers can be found in the AirBop-Client sample.

The following registration parameters are supported:

reg

The registration ID received from the GCM servers, as described in the GCM Architectural Overview. This will be used to uniquely identify the device on the GCM and AirBop servers.

country (optional)

The ISO 3166-1 alpha-2 country code. This must be exactly two characters or it will be ignored.

label (optional)

A 50 character string that can be used to 'tag' or 'group' devices. You will be able to target devices based on this value when you send your message from the AirBop servers.

For example, if you wanted to differentiate device registrations from tablets vs. phones you could label them with either "phone" or "tablet" as appropriate. Then you would be able to target each group separately when sending push notifications.

lat (optional)

The latitude value of the device. Stored as a float and accurate to one city block.

long (optional)

The longitude value of the device. Stored as a float and accurate to one city block.

lang (optional)

ISO639-1 language code.

state (optional)

The two character state or province code from the USA or Canada. This must be exactly two characters or it will be ignored.

If the location data is not sent, the server will attempt to fill in any missing data by performing an IP lookup on the device that posted the data. The location data that the AirBop server gets using this method will be quite accurate (99.5% at a country level and 90% at a state level), so you only need to provide your own data if you need greater accuracy, or want to provide a different location.

An Example Body

Here is an example of a JSON registration body as generated by the AirBop-Client sample:

{
    "country":"CA",
    "label":"AirBop Sample",
    "lang":"en",
    "lat":"49.897884",
    "long":"-97.1351",
    "reg":"XXXXXXXXXXXXXXXXXX",
    "state":"MB"
}

AirBop Response Codes

Please see the Server Response Codes knowledge base article for more information about possible response codes from the AirBop server.

Unregistering from the AirBop servers can be accomplished by posting the correct information to the following URL:

http://www.airbop.com/api/v1/unregister

Required Headers

When unregistering from the AirBop servers, the same headers used when registering are required:

  • x-app-key
  • x-timestamp
  • x-signature
  • Content-Type

Parameters

The GCM registration ID must be sent to AirBop in order to unregister the device from the AirBop servers. This is the only information that needs to be sent in the request body to AirBop.

As with registration, the content type passed to the AirBop server controls what format the body is expected in, and the preferred method is JSON (application/json).

Examples of how to construct the request body and post to the AirBop servers can be found in the AirBop-Client sample.

The following unregistration parameter is required:

reg

The registration ID received from the GCM servers, as described in the GCM Architectural Overview. This will be used to uniquely identify the device on the GCM and AirBop servers.

An Example Body

Here is an example of a JSON unregistration body as generated by the AirBop-Client sample:

{
    "reg":"XXXXXXXXXXXXXXXXXX"
}

The above article is a simplified overview of what's involved in integrating AirBop and Google Cloud Messaging into your Android application. For an in-depth discussion of GCM, you can reference the following articles in Google's developer documentation:

AirBop also provides a sample project which contains some helpful utility methods, and an example of best practices. You can use this both as an initial test of the service and as a future reference when implementing messaging in your own Android application. You can download the source code for the AirBop-Client sample app from GitHub.

Head back to the tutorials page for more information and walkthroughs - or just go ahead and sign up now to add AirBop to your Android app. It's free to get started and there's no obligation.

More Tutorials   Sign Up Now