{"id":2008,"date":"2015-12-16T01:07:06","date_gmt":"2015-12-16T01:07:05","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2008"},"modified":"2019-04-14T04:56:28","modified_gmt":"2019-04-14T11:56:28","slug":"getting-started-with-react-native-android-and-couchbase-lite","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/","title":{"rendered":"Getting Started with React Native Android and Couchbase Lite"},"content":{"rendered":"<p><a href=\"https:\/\/facebook.github.io\/react-native\/\">React Native<\/a> enables you to build Android applications that look and feel native with only JavaScript. In this instance, React Native takes care of managing UI state and synchronizing it with the models. And luckily for us, we can use <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/get-started\/couchbase-lite-overview\/index.html\">Couchbase Lite<\/a> to add sync and persistence to a React Native app. In this tutorial, you will learn how to build a simple application to save documents and replicate them to <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/get-started\/sync-gateway-overview\/index.html\">Sync Gateway<\/a>. Here are the core concepts you will learn:<\/p>\n<ol>\n<li>Create a basic project with Couchbase Lite Android and Couchbase Lite Java Listener<\/li>\n<li>Integrating React Native in your project<\/li>\n<li>Adding Models and UI components with JavaScript<\/li>\n<li>Setting up Couchbase Sync Gateway<\/li>\n<\/ol>\n<p>Here\u2019s a sneak peek of what you are going to build:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3345\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2015\/12\/todolite-1.png\" alt=\"todolite\" width=\"1920\" height=\"1143\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/todolite-1.png 1920w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/todolite-1-300x179.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/todolite-1-1024x610.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/todolite-1-768x457.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/todolite-1-1536x914.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/todolite-1-20x12.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/todolite-1-1320x786.png 1320w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/p>\n<p>You can download the completed project from <a href=\"https:\/\/github.com\/couchbaselabs\/todolite-reactnative-android\">GitHub<\/a>.<\/p>\n<h2 id=\"toc_1\">Prerequisites<\/h2>\n<ul>\n<li>Node.js 4.0 or higher<\/li>\n<li><a href=\"https:\/\/developer.android.com\/sdk\/installing\/studio.html\">Android Studio<\/a> and an emulator<\/li>\n<\/ul>\n<h2 id=\"toc_2\">Getting Started<\/h2>\n<p>In this section, you will create a new Android Studio project from scratch and <a href=\"https:\/\/facebook.github.io\/react-native\/docs\/embedded-app-android.html#content\">integrate React Native<\/a> to it.<\/p>\n<h3 id=\"toc_3\">New Android Studio Project<\/h3>\n<p>Before you start writing some JavaScript you need to create a new Android Studio project with all the dependencies. Open Android Studio and from the welcome screen select <strong>New Project<\/strong>. In the New Project window, enter <strong>TodoLite ReactNative Android<\/strong> for the application name and <strong>todolite-reactnative-android<\/strong> for the folder name:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3347\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2015\/12\/newprojectandroidstudio.png\" alt=\"newprojectandroidstudio\" width=\"700\" height=\"466\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/newprojectandroidstudio.png 700w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/newprojectandroidstudio-300x200.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/newprojectandroidstudio-400x267.png 400w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/newprojectandroidstudio-450x300.png 450w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/newprojectandroidstudio-20x13.png 20w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Set the minimum required SDK to <a href=\"https:\/\/github.com\/facebook\/react-native#react-native\">API 16: Android 4.1 or later<\/a> and use the currently recommended Android API. After you fill in the fields, the New Project window should look something like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3348\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2015\/12\/api_16_android_jelly_bean.png\" alt=\"api_16_android_jelly_bean\" width=\"700\" height=\"466\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/api_16_android_jelly_bean.png 700w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/api_16_android_jelly_bean-300x200.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/api_16_android_jelly_bean-400x267.png 400w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/api_16_android_jelly_bean-450x300.png 450w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/api_16_android_jelly_bean-20x13.png 20w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Click Next, and choose the <strong>Blank Activity<\/strong> template:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3349\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2015\/12\/blank_activity.png\" alt=\" blank_activity\" width=\"700\" height=\"466\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity.png 700w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity-300x200.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity-400x267.png 400w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity-450x300.png 450w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity-20x13.png 20w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3349\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2015\/12\/blank_activity.png\" alt=\" blank_activity\" width=\"700\" height=\"466\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity.png 700w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity-300x200.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity-400x267.png 400w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity-450x300.png 450w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/blank_activity-20x13.png 20w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Click <strong>Finish<\/strong> and you should see the following in the project navigator:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3350\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2015\/12\/finish.png\" alt=\"finish\" width=\"600\" height=\"300\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/finish.png 600w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/finish-300x150.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/finish-20x10.png 20w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<h3 id=\"toc_4\">Bundling dependencies<\/h3>\n<p>Expand the app folder, and then open the <strong>build.gradle<\/strong> file. Make sure you open the one located in the <strong>app<\/strong> folder (also called the module) and add the following in the <strong>android<\/strong> section:<\/p>\n<pre><code class=\"language-none\">\/\/ workaround for \"duplicate files during packaging of APK\" issue\n\/\/ see https:\/\/groups.google.com\/d\/msg\/adt-dev\/bl5Rc4Szpzg\/wC8cylTWuIEJ\npackagingOptions {\n    exclude 'META-INF\/ASL2.0'\n    exclude 'META-INF\/LICENSE'\n    exclude 'META-INF\/NOTICE'\n}<\/code><\/pre>\n<p>Next, open <strong>build.gradle<\/strong> at the root (also referred to as the project level gradle file) and add a reference to the Couchbase Maven repository:<\/p>\n<pre><code class=\"language-none\">allprojects {\n    repositories {\n        jcenter()\n        maven {\n            url \"https:\/\/files.couchbase.com\/maven2\/\"\n        }\n    }\n}<\/code><\/pre>\n<p>Now, add the following lines to the top-level <strong>dependencies<\/strong> section:<\/p>\n<pre><code class=\"language-none\">dependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    testCompile 'junit:junit:4.12'\n    compile 'com.android.support:appcompat-v7:23.1.0'\n\n    compile 'com.couchbase.lite:couchbase-lite-android:1.1.0'\n    compile 'com.couchbase.lite:couchbase-lite-java-listener:1.1.0'\n    compile 'com.couchbase.lite:couchbase-lite-java-javascript:1.1.0'\n    compile 'com.facebook.react:react-native:0.13.0'\n}<\/code><\/pre>\n<p>In the Android Studio tool bar, click Sync Project with Gradle Files.<\/p>\n<h3 id=\"toc_5\">Setting up Couchbase Lite and the Listener<\/h3>\n<p>Open <strong>AndroidManifest.xml<\/strong> located in <strong>app\/src\/main<\/strong> and add the permissions:<\/p>\n<pre><code class=\"language-xml\">\n\n<\/code><\/pre>\n<h3 id=\"toc_6\">The React Native Android Activity<\/h3>\n<p>You need to add some native code in order to start the React Native runtime and get it to render something. Replace the content of <strong>MainActivity.java<\/strong> with the following and we\u2019ll explain what is going on next:<\/p>\n<pre><code class=\"language-java\">public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {\n    private ReactRootView mReactRootView;\n    private ReactInstanceManager mReactInstanceManager;\n\n    private final String TAG = \"TodoLite\";\n    private static final int DEFAULT_LISTEN_PORT = 5984;\n    private int listenPort;\n    private Credentials allowedCredentials;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\n        Log.d(TAG, \"onCreate method called\");\n\n        \/\/ 1\n        mReactRootView = new ReactRootView(this);\n        mReactInstanceManager = ReactInstanceManager.builder()\n                .setApplication(getApplication())\n                .setBundleAssetName(\"index.android.bundle\")\n                .setJSMainModuleName(\"index.android\")\n                .addPackage(new MainReactPackage())\n                .setUseDeveloperSupport(BuildConfig.DEBUG)\n                .setInitialLifecycleState(LifecycleState.RESUMED)\n                .build();\n        mReactRootView.startReactApplication(mReactInstanceManager, \"TodoLite-ReactNative-Android\", null);\n\n        setContentView(mReactRootView);\n        initCBLite();\n    }\n\n    private void initCBLite() {\n        try {\n\n            \/\/ 2\n            allowedCredentials = new Credentials(\"\", \"\");\n\n            \/\/ 3\n            View.setCompiler(new JavaScriptViewCompiler());\n\n            \/\/ 4\n            AndroidContext context = new AndroidContext(this);\n            Manager.enableLogging(Log.TAG, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_SYNC, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_QUERY, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_VIEW, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_CHANGE_TRACKER, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_BLOB_STORE, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_DATABASE, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_LISTENER, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_MULTI_STREAM_WRITER, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_REMOTE_REQUEST, Log.VERBOSE);\n            Manager.enableLogging(Log.TAG_ROUTER, Log.VERBOSE);\n            Manager manager = new Manager(context, Manager.DEFAULT_OPTIONS);\n\n            \/\/ 5\n            listenPort = startCBLListener(DEFAULT_LISTEN_PORT, manager, allowedCredentials);\n\n            Log.i(TAG, \"initCBLite() completed successfully with: \" + String.format(\n                    \"https:\/\/%s:%s@localhost:%d\/\",\n                    allowedCredentials.getLogin(),\n                    allowedCredentials.getPassword(),\n                    listenPort));\n\n        } catch (final Exception e) {\n            e.printStackTrace();\n        }\n\n    }\n\n    private int startCBLListener(int listenPort, Manager manager, Credentials allowedCredentials) {\n        LiteListener listener = new LiteListener(manager, listenPort, allowedCredentials);\n        int boundPort = listener.getListenPort();\n        Thread thread = new Thread(listener);\n        thread.start();\n        return boundPort;\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        if (mReactInstanceManager != null) {\n            mReactInstanceManager.onPause();\n        }\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        if (mReactInstanceManager != null) {\n            mReactInstanceManager.onResume(this);\n        }\n    }\n\n\n    @Override\n    public void onBackPressed() {\n        if (mReactInstanceManager != null) {\n            mReactInstanceManager.onBackPressed();\n        } else {\n            super.onBackPressed();\n        }\n    }\n\n    @Override\n    public boolean onKeyUp(int keyCode, KeyEvent event) {\n        if (keyCode == KeyEvent.KEYCODE_MENU &amp;&amp; mReactInstanceManager != null) {\n            mReactInstanceManager.showDevOptionsDialog();\n            return true;\n        }\n        return super.onKeyUp(keyCode, event);\n    }\n\n    @Override\n    public void invokeDefaultOnBackPressed() {\n        super.onBackPressed();\n    }\n}<\/code><\/pre>\n<p>A few things are happening here:<\/p>\n<ol>\n<li>You create an Activity that creates a <code>ReactRootView<\/code>, starts a React application inside it and sets it as the main content view. Next, you\u2019re calling the <code>initCBLite<\/code> method which does a few things.<\/li>\n<li>Here you define an empty name and password to be used by the Listener. This means that in theory, anyone could access your database. This is ok for this tutorial but in production you\u2019d replace the line with <code>new Credentials()<\/code>.<\/li>\n<li>Plug in the component to compile the JavaScript Views. We\u2019re not going to use Couchbase Views in this tutorial just yet but it might come in handy.<\/li>\n<li>Instantiate the <code>Manager<\/code> and enable logging.<\/li>\n<li>Start the Couchbase Listener passing in the port to listen on, the manager instance and secure credentials.<\/li>\n<\/ol>\n<p>That\u2019s all for the Android part, now you can turn your attention to JavaScript!<\/p>\n<h2 id=\"toc_7\">JavaScript Land<\/h2>\n<p>In your project\u2019s root folder, run:<\/p>\n<pre><code class=\"language-bash\">$ npm init\n$ npm install --save react-native\n$ curl -o .flowconfig https:\/\/raw.githubusercontent.com\/facebook\/react-native\/master\/.flowconfig<\/code><\/pre>\n<p>This creates a node module for your app and adds the react-native npm dependency. Now open the newly created <strong>package.json<\/strong> file and add this line inside of the <code>scripts<\/code> field:<\/p>\n<pre><code class=\"language-none\">\"start\": \"node_modules\/react-native\/packager\/packager.sh\"<\/code><\/pre>\n<h3 id=\"toc_8\">Hello World<\/h3>\n<p>Copy &amp; paste the following code to a new <strong>index.android.js<\/strong> file in your root folder:<\/p>\n<pre><code class=\"language-javascript\">\/**\n * Sample React Native App\n * https:\/\/github.com\/facebook\/react-native\n *\/\n'use strict';\n\nvar React = require('react-native');\nvar Home = require('.\/app\/components\/Home');\nvar {\n  AppRegistry,\n  StyleSheet,\n  Text,\n  View,\n  ToolbarAndroid\n} = React;\n\n\nvar styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: '#111111'\n  },\n  toolbar: {\n    backgroundColor: '#e9eaed',\n    height: 56,\n  }\n});\n\n\nvar TodoLite = React.createClass({\n  render: function() {\n    return (\n      \n        \n        \n        \n      \n    );\n  }\n});\n\nAppRegistry.registerComponent('TodoLite-ReactNative-Android', () =&gt; TodoLite);<\/code><\/pre>\n<h2 id=\"toc_9\">Build and Run!<\/h2>\n<p>To run your app, you first need to start the development server. To do this, simply run the following command in your root folder:<\/p>\n<pre><code class=\"language-none\">npm start<\/code><\/pre>\n<p><strong>NOTE:<\/strong> At the time of this writing, you may need to run <code>brew update &amp;&amp; brew reinstall watchman<\/code> to update watchman if you get the error <code>Error building DepdendencyGraph: TypeError: Cannot read property 'root' of null<\/code>.<\/p>\n<p>Now build and run your Android app in a new Terminal tab:<\/p>\n<pre><code class=\"language-none\">.\/gradlew installDebug<\/code><\/pre>\n<p>Open it in the Android simulator and you will see the following:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3351\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2015\/12\/helloworld.png\" alt=\"helloworld\" width=\"300\" height=\"533\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/helloworld.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/helloworld-169x300.png 169w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/helloworld-11x20.png 11w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Well done on getting the development environment up and running! React Native includes great features such live reload which make it much easier to iterate on the UI of the application, but first you must define the models and methods to persist documents to the Couchbase Lite database.<\/p>\n<h2 id=\"toc_10\">A Todo Application<\/h2>\n<h3 id=\"toc_11\">A Simple API<\/h3>\n<p>Create a new file <strong>app\/utils\/api.js<\/strong> and add the following:<\/p>\n<pre><code class=\"language-javascript\">var api = {\n  \n  \/\/ 1\n  localDatabaseUrl: 'https:\/\/localhost:5984',\n  \n  \/\/ 2\n  remoteDatabaseUrl: 'https:\/\/localhost:4984',\n \n  \/\/ 3\n  saveTodo(title){\n    return fetch(this.localDatabaseUrl + '\/todos', {\n      method: 'post',\n      headers: {\n        'Content-Type': 'application\/json'\n      },\n      body: JSON.stringify({\n        type: 'list',\n        title: title\n      })\n    }).then((res) =&gt; res.json());\n  },\n  \n  \/\/ 4\n  getTodos(){\n    return fetch(this.localDatabaseUrl + '\/todos\/_all_docs?include_docs=true').then((response) =&gt; {\n      if (response.status !== 200) {\n        return fetch(this.localDatabaseUrl + '\/todos', {\n          method: 'put',\n          headers: {\n            'Accept': 'application\/json',\n            'Content-Type': 'application\/json'\n          },\n          body: JSON.stringify({ok: true})\n        }).then((res) =&gt; res.json());\n      }\n      return response.json();\n    })\n  },\n\n  \/\/ 5\n  startSync(){\n    return fetch(this.localDatabaseUrl + '\/_replicate', {\n      method: 'post',\n      headers: {\n        'Content-Type': 'application\/json'\n      },\n      body: JSON.stringify({\n        source: 'todos',\n        target: this.remoteDatabaseUrl + '\/todos',\n        continuous: true\n      })\n    }).then((res) =&gt; res.json());\n  }\n  \n};\n\nmodule.exports = api;<\/code><\/pre>\n<p>Here is what you\u2019re doing:<\/p>\n<ol>\n<li>You declare the endpoint the Couchbase Listener is running on.<\/li>\n<li>The remote database is Sync Gateway in this case. This would be replaced with your Sync Gateway production instance.<\/li>\n<li>The method to persist a task document.<\/li>\n<li>Here, you\u2019re getting all the documents from Couchbase Lite.<\/li>\n<li>Start a push replication from the Couchbase Lite database to Sync Gateway. There could equally be a pull replication as well.<\/li>\n<\/ol>\n<p>With a basic API in place, you can now turn your attention to building the UI.<\/p>\n<h3 id=\"toc_12\">Building the UI<\/h3>\n<p>Create a new file in <strong>app\/components\/Home.js<\/strong> with the following:<\/p>\n<pre><code class=\"language-javascript\">var React = require('react-native');\nvar api = require('.\/..\/utils\/api');\n\nvar {\n  Text,\n  View,\n  StyleSheet,\n  ScrollView,\n  TextInput,\n  TouchableOpacity\n  } = React;\n\nvar styles = StyleSheet.create({\n    container: {\n        flex: 1\n    },\n    buttonText: {\n        fontSize: 18,\n        color: 'white',\n        alignSelf: 'center'\n    },\n    rowContainer: {\n        padding: 10\n    },\n    rowTitle: {\n        color: '#48BBEC',\n        fontSize: 16\n    },\n    rowContent: {\n        fontSize: 19\n    },\n\n    mainContainer: {\n        flex: 1,\n        padding: 30,\n        marginTop: 65,\n        flexDirection: 'column',\n        justifyContent: 'center',\n        backgroundColor: '#48BBEC'\n    },\n    searchInput: {\n        height: 50,\n        padding: 4,\n        marginRight: 5,\n        fontSize: 23,\n        borderWidth: 1,\n        borderColor: 'white',\n        borderRadius: 8,\n        color: 'white',\n        margin: 5\n    },\n    buttonText: {\n        fontSize: 18,\n        color: '#111',\n        alignSelf: 'center'\n    },\n    button: {\n        height: 45,\n        flexDirection: 'row',\n        backgroundColor: 'white',\n        borderColor: 'white',\n        borderWidth: 1,\n        borderRadius: 8,\n        marginBottom: 10,\n        marginTop: 10,\n        alignSelf: 'stretch',\n        justifyContent: 'center'\n    },\n});\n\nclass Home extends React.Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n            newTodo: '',\n            todos: []\n        };\n    }\n    componentWillMount() {\n        api.getTodos()\n          .then((res) =&gt; {\n              var todos = res.rows.map(function (row) {\n                  return row.doc;\n              });\n              this.setState({\n                  todos: todos\n              });\n          });\n    }\n    handleTodoChange(event) {\n        this.setState({\n            newTodo: event.nativeEvent.text\n        });\n    }\n    handleSave() {\n        api.saveTodo(this.state.newTodo)\n        .then((res) =&gt; {\n              api.getTodos()\n                .then((res) =&gt; {\n                    var todos = res.rows.map(function (row) {\n                        return row.doc;\n                    });\n                    this.refs.inputText.value = '';\n                    this.setState({\n                        todos: todos,\n                        newTodo: ''\n                    });\n                });\n          });\n    }\n    handleSync() {\n        api.startSync()\n          .then(function(res) {\n              console.log(res);\n          });\n    }\n    render() {\n        var lists = this.state.todos.map((item, index) =&gt; {\n            return (\n              \n                  \n                       {item.title} \n                  \n              \n            );\n        });\n        return (\n          \n              \n              \n                  Save\n              \n              \n                  Sync\n              \n              \n                  {lists}\n              \n          \n        );\n    }\n}\n\nHome.propTypes = {\n    lists: React.PropTypes.array.isRequired\n};\n\nmodule.exports = Home;<\/code><\/pre>\n<p>Don\u2019t get intimidated by the length of this code snippet. All we\u2019re doing here is declaring styles and using some built-in React Native UI components to display a text input, buttons and text labels. You can find the list of built-in UI components <a href=\"https:\/\/facebook.github.io\/react-native\/docs\/native-components-android.html#content\">here<\/a>.<\/p>\n<h3 id=\"toc_13\">Updating the Root Component<\/h3>\n<p>The final step before you can see your great work in action is to update <strong>index.android.js<\/strong> to load the <strong>Home<\/strong> component. Below the <code>require<\/code> statement to import <code>react-native<\/code>, add the following:<\/p>\n<pre><code class=\"language-javascript\">var Home = require('.\/app\/components\/Home');<\/code><\/pre>\n<p>Next, replace the return value of the <code>render<\/code> method with <code><\/code>. Use the <code>\u2318 + m<\/code> shortcut in Genymotion to reload the JavaScript and you should see a bright blue screen. That\u2019s good news!<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3352\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2015\/12\/savesync.png\" alt=\" savesync\" width=\"300\" height=\"533\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/savesync.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/savesync-169x300.png 169w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2015\/12\/savesync-11x20.png 11w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<h2 id=\"toc_14\">Replications with Couchbase Sync Gateway<\/h2>\n<p>Download Sync Gateway from the link below and unzip the file:<\/p>\n<blockquote><p>https:\/\/www.couchbase.com\/nosql-databases\/downloads<\/p><\/blockquote>\n<p>In a new file named <strong>sync-gateway-config.json<\/strong>, paste the following:<\/p>\n<pre><code class=\"language-javascript\">{\n  \"log\": [\"*\"],\n  \"databases\": {\n    \"todos\": {\n      \"server\": \"walrus:\",\n      \"users\": { \"GUEST\": { \"disabled\": false, \"admin_channels\": [\"*\"] } }\n    }\n  }\n}<\/code><\/pre>\n<p>And run Sync Gateway with this config file:<\/p>\n<pre><code class=\"language-javascript\">~\/Downloads\/couchbase-sync-gateway\/bin\/sync_gateway \/path\/to\/project\/sync-gateway-config.json<\/code><\/pre>\n<p>To make the Sync Gateway endpoint reachable inside of the Android VM emulator, you need to enable a port from the host to the VM. In Terminal, run the following:<\/p>\n<pre><code class=\"language-bash\">adb reverse tcp:4984 tcp:4984<\/code><\/pre>\n<p>Open the Admin UI to monitor the documents that were saved to Sync Gateway:<\/p>\n<blockquote><p>https:\/\/localhost:4985\/_admin\/<\/p><\/blockquote>\n<p>Try adding more task documents and notice how they get pushed to Sync Gateway automatically.<\/p>\n<h2 id=\"toc_15\">Where To Go From Here<\/h2>\n<p>Congratulations! You\u2019ve built your first React Native Android + Couchbase Lite application. You\u2019re now ready to add more components such as the following:<\/p>\n<ol>\n<li><a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/guides\/couchbase-lite\/native-api\/view\/index.html\">Couchbase Lite Views<\/a> to write custom queries<\/li>\n<li><a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.1.0\/develop\/references\/couchbase-lite\/rest-api\/authentication\/index.html\">User authentication<\/a> in a replication<\/li>\n<li><a href=\"https:\/\/jamiltz.github.io\/2015-10-23-continuously-deploy-couchbase-mobile-stack-with-docker-tutum\/\">Continuously deploying the Sync Gateway configuration file<\/a> and other components<\/li>\n<\/ol>\n<p>Watch out for a tutorial on debugging your React Native Android + Couchbase Lite application using Charles and Genymotion.<\/p>\n<p>Feel free to share your feedback, findings or ask any questions in the comments below or in the forums. Talk to you soon!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>React Native enables you to build Android applications that look and feel native with only JavaScript. In this instance, React Native takes care of managing UI state and synchronizing it with the models. And luckily for us, we can use [&hellip;]<\/p>\n","protected":false},"author":51,"featured_media":13873,"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":[9028],"class_list":["post-2008","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>React Native Android and Couchbase Lite - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Visit the post to learn how to build a simple application to save documents and replicate them to Sync Gateway. Also, check out the core concepts.\" \/>\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-react-native-android-and-couchbase-lite\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Getting Started with React Native Android and Couchbase Lite\" \/>\n<meta property=\"og:description\" content=\"Visit the post to learn how to build a simple application to save documents and replicate them to Sync Gateway. Also, check out the core concepts.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2015-12-16T01:07:05+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-04-14T11:56:28+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"James Nocentini, Technical Writer, Mobile, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"James Nocentini, Technical Writer, Mobile, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 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-react-native-android-and-couchbase-lite\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/\"},\"author\":{\"name\":\"James Nocentini, Technical Writer, Mobile, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6\"},\"headline\":\"Getting Started with React Native Android and Couchbase Lite\",\"datePublished\":\"2015-12-16T01:07:05+00:00\",\"dateModified\":\"2019-04-14T11:56:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/\"},\"wordCount\":1169,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Couchbase Mobile\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/\",\"name\":\"React Native Android and Couchbase Lite - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2015-12-16T01:07:05+00:00\",\"dateModified\":\"2019-04-14T11:56:28+00:00\",\"description\":\"Visit the post to learn how to build a simple application to save documents and replicate them to Sync Gateway. Also, check out the core concepts.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Getting Started with React Native Android and Couchbase Lite\"}]},{\"@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\/ec4dfbd349cb4a321fb6a92b71a9a7f6\",\"name\":\"James Nocentini, Technical Writer, Mobile, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/09977bdd14473dc23a125f2f74c3e816\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g\",\"caption\":\"James Nocentini, Technical Writer, Mobile, Couchbase\"},\"description\":\"James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for raywenderlich.com in his spare time.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/james-nocentini\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"React Native Android and Couchbase Lite - The Couchbase Blog","description":"Visit the post to learn how to build a simple application to save documents and replicate them to Sync Gateway. Also, check out the core concepts.","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-react-native-android-and-couchbase-lite\/","og_locale":"en_US","og_type":"article","og_title":"Getting Started with React Native Android and Couchbase Lite","og_description":"Visit the post to learn how to build a simple application to save documents and replicate them to Sync Gateway. Also, check out the core concepts.","og_url":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/","og_site_name":"The Couchbase Blog","article_published_time":"2015-12-16T01:07:05+00:00","article_modified_time":"2019-04-14T11:56:28+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"James Nocentini, Technical Writer, Mobile, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"James Nocentini, Technical Writer, Mobile, Couchbase","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/"},"author":{"name":"James Nocentini, Technical Writer, Mobile, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ec4dfbd349cb4a321fb6a92b71a9a7f6"},"headline":"Getting Started with React Native Android and Couchbase Lite","datePublished":"2015-12-16T01:07:05+00:00","dateModified":"2019-04-14T11:56:28+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/"},"wordCount":1169,"commentCount":1,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Couchbase Mobile"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/","url":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/","name":"React Native Android and Couchbase Lite - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2015-12-16T01:07:05+00:00","dateModified":"2019-04-14T11:56:28+00:00","description":"Visit the post to learn how to build a simple application to save documents and replicate them to Sync Gateway. Also, check out the core concepts.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/getting-started-with-react-native-android-and-couchbase-lite\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Getting Started with React Native Android and Couchbase Lite"}]},{"@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\/ec4dfbd349cb4a321fb6a92b71a9a7f6","name":"James Nocentini, Technical Writer, Mobile, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/09977bdd14473dc23a125f2f74c3e816","url":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","caption":"James Nocentini, Technical Writer, Mobile, Couchbase"},"description":"James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for raywenderlich.com in his spare time.","url":"https:\/\/www.couchbase.com\/blog\/author\/james-nocentini\/"}]}},"authors":[{"term_id":9028,"user_id":51,"is_guest":0,"slug":"james-nocentini","display_name":"James Nocentini, Technical Writer, Mobile, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/0aa80108e5c81e282d705199edae5a25f8ef92abf15cd64f8ff19837abcee09a?s=96&d=mm&r=g","author_category":"","last_name":"Nocentini","first_name":"James","job_title":"","user_url":"","description":"James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for raywenderlich.com in his spare time."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2008","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\/51"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=2008"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2008\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=2008"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=2008"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=2008"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=2008"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}