Introduction

In this post I’ll show a sample Android application built with Couchbase Lite that uses an Urban Airship push notification to trigger synchronizing data from the cloud to a mobile device. Here “the cloud” will be a Sync Gateway instance setup in a test configuration. (Couchbase Lite and Sync Gateway are both part of the Couchbase Mobile stack. You can read about Couchbase Mobile here.)

Background

Couchbase Mobile synchronizes data using unidirectional replications. You can set replications to run and end immediately once the local data is up-to-date (“one-shot”), or to listen indefinitely for new changes (“continuous”).

There are a few reasons you might want to use a service like Urban Airship to trigger synchronization instead of setting up a continous replication. For example, a continuous “pull” replication (one that retrieves data from the cloud) needs to keep a network connection open. An open connection will necessarily cause some amount of drain on the device battery, even while inactive. Ideally, an application would only open a connection when there exists changes to transfer.

Beyond that, push notification services like Urban Airship typically have a number of advanced features for addressing groups of devices. UA can give you great flexibility in managing when operations happen. Furthermore, if your app already uses a push service, that already requires its own open network connection. It makes sense to use that to trigger Couchbase Lite instead of doubling up the networking.

This example will show how to integrate Urban Airship. I’ll walk through all the necessary pieces, so you can build a fully working application.

What you’ll need

  • An Urban Airship account
  • A Firebase account (requires a Google Login account)
  • Android Studio or the equivalent

Note: You can read about setting up Urban Airship in this blog post.

The Application

Here’s a look at the application in action. The upper part of the image shows the app running. The lower part shows a push notification sent from the command line. When the app receives the push notification, it puts up a progress spinner, fires off a one-shot pull replication, then displays the document changes received in a text view.

To understand this example, we’ll take a look at four classes, some of the “glue” that brings them together, and show how to test the results.

Classes Required by Urban Airship

To use Urban Airship (UA), we need to implement two classes, a subclass of Autopilot, and a subclass of AirshipReceiver.

Autopilot

UA has to be initialized before use. You can do that in two ways, either call takeOff in the application’s onCreate method or by creating a subclass of Autopilot. I chose to do the latter. As we’ll see, UA has an interesting way of automatically using our subclass.

The class is simple. I don’t want to display anything in the notification bar. I use this class to turn off user notifications, and that’s all.

Here’s the full listing of CBAutoPilot.java.

To use this class, UA employs a technique unique to Android. You indicate which class to use with an entry in your Android manifest file. For my case, the entry looks like this (placed inside the application section):

This is where a bit of Android magic happens. UA includes a Content Provider class to automate the initilization. Content Providers are guaranteed to get instantiated before the application’s onCreate method gets called. UA uses that to include code to read this meta-data entry, instantiate the subclass, and call the onAirshipReady method.

AirshipReceiver

With UA initialized and ready to go, we need to provide the hooks to capture and process notifications. To do that, implement a subclass of AirshipReceiver. Again, the class is straightforward.

Here’s the full listing of CBAirshipReceiver.java.

When we get to testing the app, we’ll see how UA lets you set the alert text. I used that here provide a few different remote operations. An alert can start and stop replications. I also included the ability, by sending “reset”, to delete the database. I did that because once you replicate the data, it’s persistent on the device. Shutting down the app doesn’t reset the local database. Rather than always having to add new documents through Sync Gateway to show replication working, I added the ability to wipe the device database and start over.

You’ll notice a few other overridden methods above. Those methods are all declared abstract in the AirshipReceiver class, so we have to include at least a minimal implementation. It turns out, though, that we need to know the device channel ID to send it a message. This channel ID changes often. In a future post, I’ll show how I register the ID so a server-side application can send to the device. For now, it’s useful to log the ID so we can extract it and use it in testing.

The Application Classes

The hooks above get UA up and running, trap notifications, and trigger actions based on their contents. Now let’s take a look at the application itself.

The app consists of one Activity set up so we can see the contents of documents as they get pulled. The other class wraps some of the Couchbase Lite functionality in a helper.

The Main Activity

In the main activity, I want to show a progress bar while replications happen, then display the set of documents sent.

Here’s the full listing of MainActivity.java

The core of the code here consists of the two change listeners, one for the database, and one for replications. Each listener interface defines a single method changed.

The Document changes listener lets us track the actual document updates. A replication may change more than one document at a time. The change event returns a list of document IDs. Looping over the document IDs, we retrieve each document directly, translate the JSON contents into a string, and append it to the text to display. The change listeners are called on a background thread. To finish out, we need to manipulate the UI elements on the main thread. This is easily done with the runOnUiThread method of the Activity.

The other listener allows us to display a busy-wait spinner (indefinite progress bar) depending on the Replication state. You can read more about monitoring replication state here.

The Database Helper Class

I often wrap database functions in a helper class. Since we only need one instance of the helper, I use a singleton pattern. Just like UA, I want the helper available before the main application starts. I use the same technique of putting the code in a Content Provider.

Here’s the full listing of CBLHelper.java.

You can see this class just forms a thin wrapper. We retain an instance of the class during onCreate which becomes our singleton. Some other basic setup happens, like enabling logging and creating a database manager. I wrote an initialize method used to actually open the database, prepare the pull replication, and attach the two change listeners. Recall this is called from our Activity class. (Note: You can have more than one change listener for each type. Couchbase keeps a list of all added listeners, not just the latest one.) The other database methods just provide simple shortcuts.

A content provider has several mandatory methods to implement. We need to provide stubs for those, which you see in the last five methods.

The Android Manifest

Finally, just to show how this ties together and the various parts get exposed, I’ve included the Android manifest file for the project.

Here’s the complete listing of AndroidManifest.xml.

The UA library comes with its own manifest file. The Android build system integrates all the different manifest files to create the final one. The UA library manifest file is where you’ll find the entries for the Content Provider that bootstraps the library.

Sync Gateway

To try the app out, I used Sync Gateway with the built-in walrus database. Walrus is an in-memory database usually used just for testing. This saves the trouble of setting up a back-end Couchbase Server instance.

Here’s the complete listing of the Sync Gateway configuration file.

This tells Sync Gateway to listen only on the localhost interface, accept any cross origin requests, and enables the special GUEST with access to all channels. It’s a pretty good general purpose configuration to start with to make sure everything’s working.

You might have noticed we use 10.0.2.2 as the IP address for Sync Gateway in the Android app. The standard emulator that comes with Android Studio maps this automatically to the hosting machine’s localhost. If you use a different emulator (Genymotion is another popular one), be sure to look up what IP address to use, since they differ.

If you want to learn more about setting up Sync Gateway on your development machine, or how to work with it from the command line, take a look at this blog series.

Testing

To test everything and record the animation shown at the beginning of the blog, I run both the Android emulator and Sync Gateway on one machine. I then post push notifications to UA through their REST API.

To get something interesting prepared, I first add a document to Sync Gateway. Here’s a shell command to do that.

(Read more about this here).

With a new document in the database on Sync Gateway, and the app up and running, all that’s left is to trigger a pull replication to see the action.

Here’s the curl command to send a “start” signal. Recall I pull the value from the “alert” part of the notification to trigger actions.

You’ll need to provide your own application key and application master secret above. You also need to look at the log files to see the channel value to enter for “android_channel”. That changes fairly regularly. Unfortunately UA doesn’t do much to indicate this. If you find push notifications don’t seem to be having any effect, check the channel value.

After posting to UA, you should see a response like this.

And, finally, to reset to a blank database to try again, you can post this.

Conclusion

That’s it for getting our Android app prepared to perform replications based on push notifications. Be sure and check out this post on monitoring the Sync Gateway changes feed. I’ll be writing another post to show a more sophisticated version, combining monitoring the changes feed with triggering client actions soon.

Postscript

Download Couchbase and Sync Gateway here. See our documentation for how to add Couchbase Lite to a project.

Check out more resources on our developer portal and follow us on Twitter @CouchbaseDev.

You can post questions on our forums. And we actively participate on Stack Overflow.

Hit me up on Twitter with any questions, comments, topics you’d like to see, etc. @HodGreeley.

Posted by Hod Greeley, Developer Advocate, Couchbase

Hod Greeley is a Developer Advocate for Couchbase, living in Silicon Valley. He has over two decades of experience as a software engineer and engineering manager. He has worked in a variety of software fields, including computational physics and chemistry, computer and network security, finance, and mobile. Prior to joining Couchbase in 2016, Hod led developer relations for mobile at Samsung. Hod holds a Ph.D. in chemical physics from Columbia University.

Leave a reply