{"id":2515,"date":"2017-04-23T16:14:25","date_gmt":"2017-04-23T23:14:25","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2515"},"modified":"2024-01-12T12:26:11","modified_gmt":"2024-01-12T20:26:11","slug":"getting-started-with-urban-airship-push-notifications","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/","title":{"rendered":"Getting Started with Urban Airship Push Notifications"},"content":{"rendered":"<p style=\"text-align: center\"><img decoding=\"async\" style=\"max-width: 30% ! important\" src=\"\/wp-content\/original-assets\/2017\/january\/getting-started-with-urban-airship-push-notifications\/urban-airship-logo-blue.png\" alt=\"Urban Airship Logo\" align=\"middle\" \/><\/p>\n<p><a href=\"https:\/\/www.urbanairship.com\/\">Urban Airship<\/a> is a popular messaging and notification service. <span style=\"font-weight: 400\">\u00a0In part 1 of this post we&#8217;ll look at how to set up Urban Airship push notifications. In part 2 of the post we\u2019ll use these notifications to<\/span> trigger replications in <a href=\"https:\/\/www.couchbase.com\/developers\/mobile\/?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">Couchbase Mobile<\/a>.<\/p>\n<h2>What you&#8217;ll need<\/h2>\n<p>You can use Urban Airship (UA) for free. (See the UA web site for current pricing details.) You do have to register an account.<\/p>\n<ul>\n<li>An Urban Airship account<\/li>\n<li>A Firebase account (requires a Google Login account)<\/li>\n<li>Android Studio (or Xcode)<\/li>\n<\/ul>\n<h2>Part 1 &#8211; Setting up Urban Airship<\/h2>\n<p>Bring up an existing Android or iOS project in your IDE (or create a new one). Here I&#8217;ll illustrate using Android.<\/p>\n<p>Sign in to your UA account. Navigate to the New App page. Fill in your app name. Select the platforms you want to use. (We&#8217;ll pick Android and iOS for this example.) Hitting &#8220;Save&#8221; will take you to the quickstart quide. \u00a0(If you&#8217;ve already gone through the quickstart and need a refresher on the setup, you can find the steps for Android\u00a0<a href=\"https:\/\/docs.urbanairship.com\/platform\/android\/\">here<\/a>\u00a0and for iOS <a href=\"https:\/\/docs.urbanairship.com\/platform\/ios\/\">here<\/a>.)<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" style=\"max-width: 70% ! important\" src=\"\/wp-content\/original-assets\/2017\/january\/getting-started-with-urban-airship-push-notifications\/urban-airship---new-app.png\" alt=\"Urban Airship New Application Dialog\" align=\"middle\" \/><\/p>\n<h3>UA quickstart<\/h3>\n<p>Here you&#8217;re offered a tab for each platform selected. As mentioned, we&#8217;ll focus on building for Android this time.<\/p>\n<p>Follow the Urban Airship quickstart steps. I have a few tips for issues I encountered.<\/p>\n<h4>Steps 1 &amp; 2 of Urban Airship quickstart<\/h4>\n<p>The UA guide refers to the project&#8217;s build.gradle script, but then shows modifying the module build.gradle script. I added the UA repository to my project&#8217;s gradle script, and the UA dependency to the module gradle script. That worked fine.<\/p>\n<p>Look for the applicationID in the module gradle script.<\/p>\n<h4>Step 5 of Urban Airship quickstart<\/h4>\n<p>To create your own Application class, right click in the app area of the Project navigation pane and pick New &gt; Java Class. In the popup, set the class name. Then for the Superclass enter android.app.Application.<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" style=\"max-width: 50% ! important\" src=\"\/wp-content\/original-assets\/2017\/january\/getting-started-with-urban-airship-push-notifications\/screen-shot-2017-01-28-at-3.37.30-pm.png\" alt=\"Creating an Application subclass\" align=\"middle\" \/><\/p>\n<p>Don&#8217;t forget to update your manifest file. You can use the fully qualified name of your class, or the short form that UA shows. The fully qualified form looks like this:<\/p>\n<pre class=\"lang:default decode:true \">    &lt;application\r\n        android:name=\"com.couchbase.cblite.android.cbpushsync.MyApplication\"<\/pre>\n<h4>Step 6 of Urban Airship quickstart<\/h4>\n<p>UA uses Firebase Cloud Messaging (FCM). Step six has a link to further documentation by UA. This new page has detailed instructions on creating an API key for your app.<\/p>\n<p>The instructions on that page under the heading &#8216;Configure FCM\/GCM Service with Urban Airship&#8217; are a little out of date. You&#8217;ll find the area to enter your Api Key and Package at the end of the quickstart guide now, instead of where the docs say to look.<\/p>\n<p>In one place, the UA docs refer to the &#8220;Google API Project Number&#8221;. This is what FCM calls your Sender ID.<\/p>\n<h2>Testing<\/h2>\n<p>The quickstart ends with a testing area, without much instruction. If you look back at the code included in your Application subclass, you&#8217;ll see it&#8217;s enabling user notifications. To test, build your app and install it on an emulator or device. (I tried both and they worked fine.)<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" style=\"max-width: 70% ! important\" src=\"\/wp-content\/original-assets\/2017\/january\/getting-started-with-urban-airship-push-notifications\/screen-shot-2017-01-28-at-4.15.18-pm.png\" alt=\"Urban Airship Test Panel\" align=\"middle\" \/><\/p>\n<p>Enter something into the text field and click &#8220;Send Test&#8221;. You should see an icon show up in the Android notification area. Oddly, this doesn&#8217;t include the text entered into the test area.<\/p>\n<p>For troubleshooting UA directs you to an obscure &#8220;Error Console&#8221; link in the lower right corner of the documentation page. The link just brought me back to the quickstart guide, unfortunately.<\/p>\n<h2>Wrapping up part 1<\/h2>\n<p><span style=\"font-weight: 400\">As you saw in the preceding steps, setting up Urban Airship was pretty quick. The quickstart shows how to send an alert notification. To trigger data sync in a Couchbase Lite client, we&#8217;ll want to send a silent alert instead, part 2 of this post will cover that.<\/span><\/p>\n<h2>Part 2 &#8211; Triggering Data Synchronization from the Cloud<\/h2>\n<p><span style=\"font-weight: 400\">In part 1 of this post you setup Urban Airship, in part 2 I will show<\/span> a sample Android application built with <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/current\/guides\/couchbase-lite\/index.html?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">Couchbase Lite<\/a> that uses an Urban Airship push notification to trigger synchronizing data from the cloud to a mobile device. Here &#8220;the cloud&#8221; will be a <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/current\/guides\/sync-gateway\/index.html?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">Sync Gateway<\/a> 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 <a href=\"https:\/\/www.couchbase.com\/developers\/mobile\/?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">here<\/a>.)<\/p>\n<h2>Background<\/h2>\n<p>Couchbase Mobile synchronizes data using unidirectional replications. You can set replications to run and end immediately once the local data is up-to-date (&#8220;one-shot&#8221;), or to listen indefinitely for new changes (&#8220;continuous&#8221;).<\/p>\n<p>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 &#8220;pull&#8221; 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.<\/p>\n<p>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.<\/p>\n<p>This example will show how to integrate Urban Airship. I&#8217;ll walk through all the necessary pieces, so you can build a fully working application.<\/p>\n<h2>The Application<\/h2>\n<p>Here&#8217;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.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3417\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/04\/CBPushSync.gif\" alt=\"\" width=\"366\" height=\"544\" \/>To understand this example, we&#8217;ll take a look at four classes, some of the &#8220;glue&#8221; that brings them together, and show how to test the results.<\/p>\n<h2>Classes Required by Urban Airship<\/h2>\n<p>To use Urban Airship (UA), we need to implement two classes, a subclass of Autopilot, and a subclass of AirshipReceiver.<\/p>\n<h3>Autopilot<\/h3>\n<p>UA has to be initialized before use. You can do that in two ways, either call <code>takeOff<\/code> in the application\u2019s <code>onCreate<\/code> method or by creating a subclass of Autopilot. I chose to do the latter. As we&#8217;ll see, UA has an interesting way of automatically using our subclass.<\/p>\n<p>The class is simple. I don&#8217;t want to display anything in the notification bar. I use this class to turn off user notifications, and that&#8217;s all.<\/p>\n<p>Here&#8217;s the full listing of CBAutoPilot.java.<\/p>\n<pre class=\"lang:java decode:true \">package com.couchbase.cblite.android.cbpushsync;\r\n\r\nimport com.urbanairship.Autopilot;\r\nimport com.urbanairship.UAirship;\r\n\r\npublic class CBAutoPilot extends Autopilot {\r\n    @Override\r\n    public void onAirshipReady(UAirship airship) {\r\n        airship.getPushManager().setUserNotificationsEnabled(false);\r\n    }\r\n}<\/pre>\n<p>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 <code>application<\/code> section):<\/p>\n<pre class=\"lang:default decode:true \">        &lt;meta-data android:name=\"com.urbanairship.autopilot\"\r\n            android:value=\"com.couchbase.cblite.android.cbpushsync.CBAutoPilot\"\/&gt;\r\n<\/pre>\n<p>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&#8217;s <code>onCreate<\/code> method gets called. UA uses that to include code to read this meta-data entry, instantiate the subclass, and call the <code>onAirshipReady<\/code> method.<\/p>\n<h3>AirshipReceiver<\/h3>\n<p>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.<\/p>\n<p>Here&#8217;s the full listing of CBAirshipReceiver.java.<\/p>\n<pre class=\"lang:java decode:true \">package com.couchbase.cblite.android.cbpushsync;\r\n\r\nimport android.content.Context;\r\nimport android.support.annotation.NonNull;\r\nimport android.util.Log;\r\n\r\nimport com.urbanairship.AirshipReceiver;\r\nimport com.urbanairship.push.PushMessage;\r\n\r\npublic class CBAirshipReceiver extends AirshipReceiver {\r\n    private static final String TAG = \"CBAirshipReceiver\";\r\n\r\n    @Override\r\n    protected void onPushReceived(Context context, PushMessage message, boolean notificationPosted) {\r\n        Log.i(TAG, \"Received push message. Alert: \" + message.getAlert() + \". posted notification: \" + notificationPosted);\r\n\r\n        switch(message.getAlert()) {\r\n            case \"start\":\r\n                CBLHelper.getInstance().startReplication();\r\n                break;\r\n            case \"stop\":\r\n                CBLHelper.getInstance().stopReplication();\r\n                break;\r\n            case \"reset\":\r\n                CBLHelper.getInstance().reset();\r\n                break;\r\n            default:\r\n                break;\r\n        }\r\n    }\r\n\r\n    @Override\r\n    protected void onChannelCreated(@NonNull Context context, @NonNull String channelId) {\r\n        Log.i(TAG, \"Channel created. Channel Id:\" + channelId + \".\");\r\n    }\r\n\r\n    @Override\r\n    protected void onChannelUpdated(@NonNull Context context, @NonNull String channelId) {\r\n        Log.i(TAG, \"Channel updated. Channel Id:\" + channelId + \".\");\r\n    }\r\n\r\n    @Override\r\n    protected void onChannelRegistrationFailed(Context context) {\r\n        Log.i(TAG, \"Channel registration failed.\");\r\n    }\r\n}\r\n<\/pre>\n<p>When we get to testing the app, we&#8217;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 &#8220;reset&#8221;, to delete the database. I did that because once you replicate the data, it&#8217;s persistent on the device. Shutting down the app doesn&#8217;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.<\/p>\n<p>You&#8217;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&#8217;ll show how I register the ID so a server-side application can send to the device. For now, it&#8217;s useful to log the ID so we can extract it and use it in testing.<\/p>\n<h2>The Application Classes<\/h2>\n<p>The hooks above get UA up and running, trap notifications, and trigger actions based on their contents. Now let&#8217;s take a look at the application itself.<\/p>\n<p>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.<\/p>\n<h3>The Main Activity<\/h3>\n<p>In the main activity, I want to show a progress bar while replications happen, then display the set of documents sent.<\/p>\n<p>Here&#8217;s the full listing of MainActivity.java<\/p>\n<pre class=\"lang:java decode:true \">package com.couchbase.cblite.android.cbpushsync;\r\n\r\nimport android.os.Bundle;\r\nimport android.support.v7.app.AppCompatActivity;\r\nimport android.support.v7.widget.Toolbar;\r\nimport android.util.Log;\r\nimport android.view.View;\r\nimport android.widget.ProgressBar;\r\nimport android.widget.TextView;\r\n\r\nimport com.couchbase.lite.Database;\r\nimport com.couchbase.lite.Document;\r\nimport com.couchbase.lite.DocumentChange;\r\nimport com.couchbase.lite.replicator.Replication;\r\nimport com.couchbase.lite.replicator.ReplicationState;\r\nimport com.fasterxml.jackson.databind.ObjectMapper;\r\n\r\nimport java.io.IOException;\r\n\r\npublic class MainActivity extends AppCompatActivity {\r\n    private static String TAG = MainActivity.class.getSimpleName();\r\n    private static final ObjectMapper mapper = new ObjectMapper();\r\n\r\n    private CBLHelper cblHelper = CBLHelper.getInstance();\r\n    private TextView documentView;\r\n    private ProgressBar progressBar;\r\n\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);\r\n        setSupportActionBar(toolbar);\r\n\r\n        documentView = (TextView) findViewById(R.id.documentView);\r\n        progressBar = (ProgressBar) findViewById(R.id.progressBar);\r\n\r\n        cblHelper.initialize(\r\n            new Database.ChangeListener() {\r\n                @Override\r\n                public void changed(Database.ChangeEvent event) {\r\n                    Log.i(TAG, \"Database change called: count - \" + event.getChanges().size());\r\n\r\n                    if (!event.isExternal()) {\r\n                        return;\r\n                    }\r\n\r\n                    String json = \"\";\r\n\r\n                    for (final DocumentChange change : event.getChanges()) {\r\n                        if (!change.isCurrentRevision()) {\r\n                            continue;\r\n                        }\r\n\r\n                        Document changedDoc = cblHelper.getExistingDocument(change.getDocumentId());\r\n\r\n                        if (changedDoc == null) continue;\r\n\r\n                        try {\r\n                            json += mapper.writeValueAsString(changedDoc.getProperties());\r\n                        } catch (IOException e) {\r\n                            e.printStackTrace();\r\n                        }\r\n                    }\r\n\r\n                    final String text = json;\r\n\r\n                    runOnUiThread(new Runnable() {\r\n                        @Override\r\n                        public void run() {\r\n                            documentView.setText(text);\r\n                        }\r\n                    });\r\n                }\r\n            },\r\n            new Replication.ChangeListener() {\r\n                @Override\r\n                public void changed(Replication.ChangeEvent event) {\r\n                    Log.i(TAG, \"Replication change called: \" + event.toString());\r\n\r\n                    if (event.getError() != null) return;\r\n\r\n                    if (event.getTransition() == null) return;\r\n\r\n                    ReplicationState dest = event.getTransition().getDestination();\r\n\r\n                    final int replicationProgress =\r\n                            ((dest == ReplicationState.STOPPING ||\r\n                              dest == ReplicationState.STOPPED) ?\r\n                                    View.INVISIBLE : View.VISIBLE);\r\n\r\n                    runOnUiThread(new Runnable() {\r\n                        @Override\r\n                        public void run() {\r\n                            progressBar.setVisibility(replicationProgress);\r\n                        }\r\n                    });\r\n                }\r\n            }\r\n        );\r\n    }\r\n}<\/pre>\n<p>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 <code>changed<\/code>.<\/p>\n<p>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 <code>runOnUiThread<\/code> method of the Activity.<\/p>\n<p>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 <a href=\"https:\/\/www.couchbase.com\/blog\/determining-status-replication-couchbase-lite\/\">here<\/a>.<\/p>\n<h3>The Database Helper Class<\/h3>\n<p>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.<\/p>\n<p>Here&#8217;s the full listing of CBLHelper.java.<\/p>\n<pre class=\"lang:java decode:true \">package com.couchbase.cblite.android.cbpushsync;\r\n\r\nimport android.content.ContentProvider;\r\nimport android.content.ContentValues;\r\nimport android.database.Cursor;\r\nimport android.net.Uri;\r\nimport android.os.Handler;\r\nimport android.os.Looper;\r\nimport android.support.annotation.NonNull;\r\nimport android.support.annotation.Nullable;\r\nimport android.util.Log;\r\n\r\nimport com.couchbase.lite.CouchbaseLiteException;\r\nimport com.couchbase.lite.Database;\r\nimport com.couchbase.lite.Document;\r\nimport com.couchbase.lite.Manager;\r\nimport com.couchbase.lite.android.AndroidContext;\r\nimport com.couchbase.lite.replicator.Replication;\r\n\r\nimport java.io.IOException;\r\nimport java.net.URL;\r\n\r\npublic class CBLHelper extends ContentProvider {\r\n    public static final String TAG = \"Push Sync\";\r\n\r\n    private static String DB = \"db\";\r\n    \/\/private static String syncGateway = \"https:\/\/localhost:4984\";\r\n    private static String syncGateway = \"https:\/\/10.0.2.2:4984\";\r\n    private static URL syncGatewayURL;\r\n\r\n    private Manager manager;\r\n    private Database database;\r\n    private Replication puller;\r\n\r\n    private Database.ChangeListener databaseChangeListener;\r\n    private Replication.ChangeListener replicationChangeListener;\r\n\r\n    private static CBLHelper instance;\r\n\r\n    public static CBLHelper getInstance() { return instance; }\r\n\r\n    @Override\r\n    public boolean onCreate() {\r\n        instance = this;\r\n\r\n        enableLogging();\r\n\r\n        try {\r\n            syncGatewayURL = new URL(syncGateway + \"\/\" + DB);\r\n            manager = new Manager(new AndroidContext(getContext()), Manager.DEFAULT_OPTIONS);\r\n        } catch (IOException ex) {\r\n            ex.printStackTrace();\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    public void closeDatabase() {\r\n        database.close();\r\n    }\r\n\r\n    public void startReplication() {\r\n        puller.start();\r\n    }\r\n\r\n    public void stopReplication() { puller.stop(); }\r\n\r\n    public void reset() {\r\n        stopReplication();\r\n\r\n        try {\r\n            database.delete();\r\n        } catch (CouchbaseLiteException ex) {\r\n            ex.printStackTrace();\r\n        }\r\n\r\n        initialize(databaseChangeListener, replicationChangeListener);\r\n    }\r\n\r\n    public void initialize(Database.ChangeListener dbl, Replication.ChangeListener rl) {\r\n        try {\r\n            database = manager.getDatabase(DB);\r\n        } catch (CouchbaseLiteException ex) {\r\n            ex.printStackTrace();\r\n        }\r\n\r\n        database.addChangeListener(dbl);\r\n        databaseChangeListener = dbl;\r\n\r\n        puller = database.createPullReplication(syncGatewayURL);\r\n        puller.addChangeListener(rl);\r\n        replicationChangeListener = rl;\r\n    }\r\n\r\n    public Document getExistingDocument(String documentID) {\r\n        return database.getExistingDocument(documentID);\r\n    }\r\n\r\n    \/\/ Logging\r\n\r\n    private void enableLogging() {\r\n        Manager.enableLogging(TAG, Log.VERBOSE);\r\n        Manager.enableLogging(com.couchbase.lite.util.Log.TAG, Log.VERBOSE);\r\n        Manager.enableLogging(com.couchbase.lite.util.Log.TAG_SYNC_ASYNC_TASK, Log.VERBOSE);\r\n        Manager.enableLogging(com.couchbase.lite.util.Log.TAG_SYNC, Log.VERBOSE);\r\n        Manager.enableLogging(com.couchbase.lite.util.Log.TAG_QUERY, Log.VERBOSE);\r\n        Manager.enableLogging(com.couchbase.lite.util.Log.TAG_VIEW, Log.VERBOSE);\r\n        Manager.enableLogging(com.couchbase.lite.util.Log.TAG_DATABASE, Log.VERBOSE);\r\n    }\r\n\r\n    \/\/ Helper function to dispatch on UI thread\r\n    private void runOnUiThread(Runnable runnable) {\r\n        new Handler(Looper.getMainLooper()).post(runnable);\r\n    }\r\n\r\n    \/\/ Required overrides\r\n\r\n    @Nullable\r\n    @Override\r\n    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {\r\n        return null;\r\n    }\r\n\r\n    @Nullable\r\n    @Override\r\n    public String getType(@NonNull Uri uri) {\r\n        return null;\r\n    }\r\n\r\n    @Nullable\r\n    @Override\r\n    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {\r\n        return null;\r\n    }\r\n\r\n    @Override\r\n    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {\r\n        return 0;\r\n    }\r\n\r\n    @Override\r\n    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {\r\n        return 0;\r\n    }\r\n}\r\n<\/pre>\n<p>You can see this class just forms a thin wrapper. We retain an instance of the class during <code>onCreate<\/code> which becomes our singleton. Some other basic setup happens, like enabling logging and creating a database manager. I wrote an <code>initialize<\/code> 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.<\/p>\n<p>A content provider has several mandatory methods to implement. We need to provide stubs for those, which you see in the last five methods.<\/p>\n<h2>The Android Manifest<\/h2>\n<p>Finally, just to show how this ties together and the various parts get exposed, I&#8217;ve included the Android manifest file for the project.<\/p>\n<p>Here&#8217;s the complete listing of AndroidManifest.xml.<\/p>\n<pre class=\"lang:default decode:true\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n&lt;manifest xmlns:android=\"https:\/\/schemas.android.com\/apk\/res\/android\"\r\n    package=\"com.couchbase.cblite.android.cbpushsync\"&gt;\r\n\r\n    &lt;application\r\n        android:allowBackup=\"true\"\r\n        android:icon=\"@mipmap\/ic_launcher\"\r\n        android:label=\"@string\/app_name\"\r\n        android:supportsRtl=\"true\"\r\n        android:theme=\"@style\/AppTheme\"&gt;\r\n        &lt;meta-data android:name=\"com.urbanairship.autopilot\"\r\n            android:value=\"com.couchbase.cblite.android.cbpushsync.CBAutoPilot\"\/&gt;\r\n        &lt;activity\r\n            android:name=\".MainActivity\"\r\n            android:label=\"@string\/app_name\"\r\n            android:theme=\"@style\/AppTheme.NoActionBar\"&gt;\r\n            &lt;intent-filter&gt;\r\n                &lt;action android:name=\"android.intent.action.MAIN\" \/&gt;\r\n\r\n                &lt;category android:name=\"android.intent.category.LAUNCHER\" \/&gt;\r\n            &lt;\/intent-filter&gt;\r\n        &lt;\/activity&gt;\r\n        &lt;receiver android:name=\".CBAirshipReceiver\"\r\n            android:exported=\"false\"&gt;\r\n\r\n            &lt;intent-filter&gt;\r\n                &lt;action android:name=\"com.urbanairship.push.CHANNEL_UPDATED\" \/&gt;\r\n                &lt;action android:name=\"com.urbanairship.push.OPENED\" \/&gt;\r\n                &lt;action android:name=\"com.urbanairship.push.RECEIVED\" \/&gt;\r\n                &lt;action android:name=\"com.urbanairship.push.DISMISSED\" \/&gt;\r\n\r\n                &lt;category android:name=\"${applicationId}\" \/&gt;\r\n            &lt;\/intent-filter&gt;\r\n        &lt;\/receiver&gt;\r\n        &lt;provider\r\n            android:authorities=\"${applicationId}.dbhelper\"\r\n            android:exported=\"false\"\r\n            android:enabled=\"true\"\r\n            android:name=\".CBLHelper\" \/&gt;\r\n    &lt;\/application&gt;\r\n\r\n&lt;\/manifest&gt;<\/pre>\n<p>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&#8217;ll find the entries for the Content Provider that bootstraps the library.<\/p>\n<h2>Sync Gateway<\/h2>\n<p>To try the app out, I used Sync Gateway with the built-in walrus database. Walrus is an <a href=\"https:\/\/www.couchbase.com\/resources\/concepts\/in-memory-database\/\">in-memory database<\/a> usually used just for testing. This saves the trouble of setting up a back-end Couchbase Server instance.<\/p>\n<p>Here&#8217;s the complete listing of the Sync Gateway configuration file.<\/p>\n<pre class=\"lang:default decode:true \">{\r\n  \"log\": [\"HTTP+\"],\r\n  \"adminInterface\": \"127.0.0.1:4985\",\r\n  \"interface\": \"127.0.0.1:4984\",\r\n  \"CORS\": {\r\n    \"origin\":[\"*\"],\r\n    \"loginorigin\":[\"*\"],\r\n    \"headers\":[\"Content-Type\"],\r\n    \"maxAge\": 1728000\r\n  },\r\n  \"databases\": {\r\n    \"db\": {\r\n      \"server\": \"walrus:\",\r\n      \"users\": { \"GUEST\": {\"disabled\": false, \"admin_channels\": [\"*\"] } }\r\n    }\r\n  }\r\n}<\/pre>\n<p>This tells Sync Gateway to listen only on the <code>localhost<\/code> interface, accept any cross origin requests, and enables the special GUEST with access to all channels. It&#8217;s a pretty good general purpose configuration to start with to make sure everything&#8217;s working.<\/p>\n<p>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&#8217;s <code>localhost<\/code>. If you use a different emulator (Genymotion is another popular one), be sure to look up what IP address to use, since they differ.<\/p>\n<p>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 <a href=\"https:\/\/www.couchbase.com\/blog\/getting-comfortable-couchbase-mobile-installing-sync-gateway\/\">blog series<\/a>.<\/p>\n<h2>Testing<\/h2>\n<p>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.<\/p>\n<p>To get something interesting prepared, I first add a document to Sync Gateway. Here&#8217;s a shell command to do that.<\/p>\n<pre class=\"lang:sh decode:true\">$ curl -X PUT -H 'Content-Type: application\/json' -H 'Accept: application\/json' -d '{ \"test\" : \"UA\", \"channels\": \"public\" }' https:\/\/localhost:4984\/db\/doc\r\n<\/pre>\n<p>(Read more about this <a href=\"https:\/\/www.couchbase.com\/blog\/getting-comfortable-with-couchbase-mobile-sync-gateway-via-the-command-line\/\">here<\/a>).<\/p>\n<p>With a new document in the database on Sync Gateway, and the app up and running, all that&#8217;s left is to trigger a pull replication to see the action.<\/p>\n<p>Here&#8217;s the <code>curl<\/code> command to send a &#8220;start&#8221; signal. Recall I pull the value from the &#8220;alert&#8221; part of the notification to trigger actions.<\/p>\n<pre class=\"lang:sh decode:true \">$ curl https:\/\/go.urbanairship.com\/api\/push -u 'appKey:appMasterSecret' -X POST -H 'Content-Type: application\/json' -H 'Accept: application\/vnd.urbanairship+json; version=3;' -d '{ \"audience\": { \"android_channel\": \"3110bc81-1c7b-4ef8-a7a3-7c56aab19f08\" }, \"notification\" : { \"alert\": \"start\" }, \"device_types\": \"all\" }'<\/pre>\n<p>You&#8217;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 &#8220;android_channel&#8221;. That changes fairly regularly. Unfortunately UA doesn&#8217;t do much to indicate this. If you find push notifications don&#8217;t seem to be having any effect, check the channel value.<\/p>\n<p>After posting to UA, you should see a response like this.<\/p>\n<pre class=\"lang:default decode:true\">{\"ok\":true,\"operation_id\":\"2a6c0edf-e5d0-4b4d-b762-ad5c4478c291\",\"push_ids\":[\"1951019a-2b7f-4f1b-8888-e87047a1feec\"],\"message_ids\":[],\"content_urls\":[]}<\/pre>\n<p>And, finally, to reset to a blank database to try again, you can post this.<\/p>\n<pre class=\"lang:sh decode:true \">$ curl https:\/\/go.urbanairship.com\/api\/push -u 'appKey:appMasterSecret' -X POST -H 'Content-Type: application\/json' -H 'Accept: application\/vnd.urbanairship+json; version=3;' -d '{ \"audience\": { \"android_channel\": \"3110bc81-1c7b-4ef8-a7a3-7c56aab19f08\" }, \"notification\" : { \"alert\": \"reset\" }, \"device_types\": \"all\" }'\r\n<\/pre>\n<h2>Conclusion<\/h2>\n<p>That&#8217;s it for getting our Android app prepared to perform replications based on push notifications. Be sure and check out <a href=\"https:\/\/www.couchbase.com\/blog\/node-js-swagger-monitor-document-changes-couchbase-mobile\/\">this post<\/a> on monitoring the Sync Gateway changes feed.<\/p>\n<h2>Postscript<\/h2>\n<p>Download Couchbase and Sync Gateway <a href=\"https:\/\/www.couchbase.com\/downloads\/\">here<\/a>. See our <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/current\/guides\/couchbase-lite\/index.html?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">documentation<\/a> for how to add Couchbase Lite to a project.<\/p>\n<p>Check out more resources on our <a href=\"https:\/\/www.couchbase.com\/developers\/community\/?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">developer portal<\/a> and follow us on Twitter <a href=\"https:\/\/twitter.com\/CouchbaseDev\">@CouchbaseDev<\/a>.<\/p>\n<p>You can post questions on our <a href=\"https:\/\/www.couchbase.com\/forums\/?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">forums<\/a>. And we actively participate on <a href=\"https:\/\/stackoverflow.com\/questions\/tagged\/couchbase\">Stack Overflow<\/a>.<\/p>\n<p>Hit me up on Twitter with any questions, comments, topics you&#8217;d like to see, etc. <a href=\"https:\/\/twitter.com\/HodGreeley\">@HodGreeley<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Urban Airship is a popular messaging and notification service. \u00a0In part 1 of this post we&#8217;ll look at how to set up Urban Airship push notifications. In part 2 of the post we\u2019ll use these notifications to trigger replications in [&hellip;]<\/p>\n","protected":false},"author":73,"featured_media":10144,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1810],"tags":[],"ppma_author":[9042],"class_list":["post-2515","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-mobile"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Urban Airship Push Notifications: What You Need to Start<\/title>\n<meta name=\"description\" content=\"Look at this blog post to see how to set up Urban Airship push notifications and how to use these notifications to trigger replications in Couchbase Mobile.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Getting Started with Urban Airship Push Notifications\" \/>\n<meta property=\"og:description\" content=\"Look at this blog post to see how to set up Urban Airship push notifications and how to use these notifications to trigger replications in Couchbase Mobile.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-04-23T23:14:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-01-12T20:26:11+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/04\/big-data-2001190_1280.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Hod Greeley, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@HodGreeley\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Hod Greeley, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/\"},\"author\":{\"name\":\"Hod Greeley, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/9b62593c8a13531e53d52fcd5aabbca4\"},\"headline\":\"Getting Started with Urban Airship Push Notifications\",\"datePublished\":\"2017-04-23T23:14:25+00:00\",\"dateModified\":\"2024-01-12T20:26:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/\"},\"wordCount\":2410,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/04\/big-data-2001190_1280.jpg\",\"articleSection\":[\"Couchbase Mobile\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/\",\"name\":\"Urban Airship Push Notifications: What You Need to Start\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/04\/big-data-2001190_1280.jpg\",\"datePublished\":\"2017-04-23T23:14:25+00:00\",\"dateModified\":\"2024-01-12T20:26:11+00:00\",\"description\":\"Look at this blog post to see how to set up Urban Airship push notifications and how to use these notifications to trigger replications in Couchbase Mobile.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/04\/big-data-2001190_1280.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/04\/big-data-2001190_1280.jpg\",\"width\":1280,\"height\":720,\"caption\":\"Urban Airship with Couchbase\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Getting Started with Urban Airship Push Notifications\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/9b62593c8a13531e53d52fcd5aabbca4\",\"name\":\"Hod Greeley, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/21eb69cb5d4a401fb23b149e4f4e9e87\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/52d0018695c0ced0d1c68cf64a6195c81dbac03dce5983f98eb209e7c84350df?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/52d0018695c0ced0d1c68cf64a6195c81dbac03dce5983f98eb209e7c84350df?s=96&d=mm&r=g\",\"caption\":\"Hod Greeley, Developer Advocate, Couchbase\"},\"description\":\"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.\",\"sameAs\":[\"https:\/\/hod.greeley.org\/blog\",\"https:\/\/x.com\/HodGreeley\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/hod-greeley\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Urban Airship Push Notifications: What You Need to Start","description":"Look at this blog post to see how to set up Urban Airship push notifications and how to use these notifications to trigger replications in Couchbase Mobile.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/","og_locale":"en_US","og_type":"article","og_title":"Getting Started with Urban Airship Push Notifications","og_description":"Look at this blog post to see how to set up Urban Airship push notifications and how to use these notifications to trigger replications in Couchbase Mobile.","og_url":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/","og_site_name":"The Couchbase Blog","article_published_time":"2017-04-23T23:14:25+00:00","article_modified_time":"2024-01-12T20:26:11+00:00","og_image":[{"width":1280,"height":720,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/04\/big-data-2001190_1280.jpg","type":"image\/jpeg"}],"author":"Hod Greeley, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@HodGreeley","twitter_misc":{"Written by":"Hod Greeley, Developer Advocate, Couchbase","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/"},"author":{"name":"Hod Greeley, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/9b62593c8a13531e53d52fcd5aabbca4"},"headline":"Getting Started with Urban Airship Push Notifications","datePublished":"2017-04-23T23:14:25+00:00","dateModified":"2024-01-12T20:26:11+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/"},"wordCount":2410,"commentCount":1,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/04\/big-data-2001190_1280.jpg","articleSection":["Couchbase Mobile"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/","url":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/","name":"Urban Airship Push Notifications: What You Need to Start","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/04\/big-data-2001190_1280.jpg","datePublished":"2017-04-23T23:14:25+00:00","dateModified":"2024-01-12T20:26:11+00:00","description":"Look at this blog post to see how to set up Urban Airship push notifications and how to use these notifications to trigger replications in Couchbase Mobile.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/04\/big-data-2001190_1280.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/04\/big-data-2001190_1280.jpg","width":1280,"height":720,"caption":"Urban Airship with Couchbase"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-urban-airship-push-notifications\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Getting Started with Urban Airship Push Notifications"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/9b62593c8a13531e53d52fcd5aabbca4","name":"Hod Greeley, Developer Advocate, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/21eb69cb5d4a401fb23b149e4f4e9e87","url":"https:\/\/secure.gravatar.com\/avatar\/52d0018695c0ced0d1c68cf64a6195c81dbac03dce5983f98eb209e7c84350df?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/52d0018695c0ced0d1c68cf64a6195c81dbac03dce5983f98eb209e7c84350df?s=96&d=mm&r=g","caption":"Hod Greeley, Developer Advocate, Couchbase"},"description":"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.","sameAs":["https:\/\/hod.greeley.org\/blog","https:\/\/x.com\/HodGreeley"],"url":"https:\/\/www.couchbase.com\/blog\/author\/hod-greeley\/"}]}},"authors":[{"term_id":9042,"user_id":73,"is_guest":0,"slug":"hod-greeley","display_name":"Hod Greeley, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/52d0018695c0ced0d1c68cf64a6195c81dbac03dce5983f98eb209e7c84350df?s=96&d=mm&r=g","author_category":"","last_name":"Greeley","first_name":"Hod","job_title":"","user_url":"https:\/\/hod.greeley.org\/blog","description":"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."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2515","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/73"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=2515"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2515\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/10144"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=2515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=2515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=2515"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=2515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}