Syncing Data With Dropbox Using Ionic Framework

Storing or syncing data remotely is often a need in modern apps.  This generation is all about the cloud and how to be a part of it.  IonicFramework is a great way to make hybrid cross platform mobile Android and iOS applications, but how about sharing data between them?  Dropbox is one of a few cloud storage services that happens to have great APIs and documentation.

The following won’t necessarily show you the best way for syncing data in IonicFramework using Dropbox’s Datastore API, but it will show you how I did it with success.

These instruction will make use of Dropbox’s JavaScript SDK and Apache Cordova’s InAppBrowser plugin.  Because we are in an app environment rather than a web browser, we cannot use strictly the JavaScript SDK.

Let’s start by creating a new Ionic project and adding the Android and iOS platforms:

You must note that if you are not on a Mac computer, you cannot add and build for the iOS platform.  However, this tutorial will work for both platforms.

The next thing we want to do is install the InAppBrowser plugin:

At this point, I strongly recommend you become familiar with what our intentions are with this Dropbox API.  We are not using the Core Sync API because we have no intention of working with files.  Our plans are to work strictly with data and the Datastore API gives us an object based cloud storage option.  It does have restrictions in terms of storage space, but for saving app preferences or small pieces of data, there shouldn’t be any issues.

To use the API, you must register your application with Dropbox.  During this process, make sure to choose Datastore API.  Once created, make sure to list http://localhost/callback as your callback / redirect URI.  This is because we are using an app and not a website.  In all honesty, it doesn’t really matter what you list it as, but for this tutorial use what I said.

The final thing we need from the app page is the application key.  Make note of this because we are going to be using it with the JavaScript SDK.

With the Dropbox Datastore JavaScript SDK downloaded, place the JavaScript file in your www/js directory and include it in your index.html file like so:

Now even though we are going to be using the official JavaScript SDK, we still need to implement our own Oauth solution.  The Oauth solution bundled with the SDK won’t work because we need to launch in an external browser.  This is where the InAppBrowser plugin comes into play.

The above chunk of code closely resembles my previous article regarding Oauth with Ionic Framework.  Per the Dropbox documentation, we must use GET /1/oauth2/authorize as our endpoint with a few parameters.  This will initialize the process and once complete redirect you to your redirect uri.  When the InAppBrowser listener detects the redirect, we will start parsing what we see in the URL.  Specifically we are looking for the access token, token type, and uid.  If we find those, then the login was successful and we can start using the datastore features.

Lucky for us, the official JavaScript Datastore SDK can be used without issue after feeding it an access token.

Per the documentation, the first thing we want to do is get the default datastore and any tables we wish to use from our datastore manager.

With our table in hand, we can start querying or inserting data.

This is where things can stray from the official documentation.  The JavaScript SDK for datastores was never meant to sync with a local copy.  Or at least that is what the documentation has lead me to believe.  Since we wan’t our mobile applications to function with and without a network connection, we need to be able to store our data locally and only sync when possible.  I’ve accomplished this by following this strategy:

  1. Search for undocumented local records
  2. Push undocumented local records to Dropbox
  3. Pull all records from Dropbox and replace all local data

So in my strategy, I determine all undocumented local records to be records without a Dropbox record id.  Every record in Dropbox has an id, so it is safe to say anything without, is not yet on Dropbox.  Once I push all these records to Dropbox, we can now replace our local data with the remote data because the remote data is now potentially more up to date than local.

This is not the most efficient way to do business, but it is definitely an effective way.  If you were aiming for efficiency, you could always only pull remote records that don’t exist locally rather than all records.  You could also make use of the recordsChanged event listener.  Many different ways to handle synchronization between local and remote.

If you’re interested in following the way I did things for data sync, you can use the following AngularJS service that I made:

To use this service, add DropboxService as one of your dependencies and take note of the following methods:

My DropboxService is very dependent on having your window.localStorage object matching the Dropbox datastore table.  I suggest calling init and connect from your .run() method, while calling the others from a controller.  A simple example using the service can be seen below:

Just like this you can sync data (not files) across all your devices.  It is important to note, that if you plan to have people test or use your application with Dropbox support, you either need to add them as a test user in the Dropbox developer console or publish your Dropbox app to production, rather than keeping it in developer mode.

Nic Raboy

Nic is a skilled application developer who has released several native and hybrid mobile applications to iTunes and Google Play. He writes about his development experiences related to making web and mobile app development easier to understand and has experience in Android, Node.js, Apache Cordova, Java, NoSQL, SQL, GoLang, NativeScript, and Unity3D.

  • mark_ellul

    Great post! With the Dropbox datastore API, its a non centralised data store right? i.e. each end user will have access to their data, and will need to sign up to dropbox if they want to “sync” their data and none of that data will be shared to me the developer right? Also I noticed you didn’t store files, have you had any experience with the cordova/phonegap plugins with ionic that do the storage?

    • Hi Mark,

      You are correct. The Dropbox Datastore API is sandboxed to each users account making it impossible to use as centralized data storage. There are minor exceptions to this rule as the API does offer a way to share datastores to other accounts. It still doesn’t make it centralized and it still hides it from the developer. Only the account owner and Dropbox staff can see what is in it. If you want to hide the data from the Dropbox staff you can follow the AES tutorial I made and encrypt the data before syncing:

      https://www.thepolyglotdeveloper.com/2014/10/implement-aes-strength-encryption-javascript/

      Unfortunately, I have no experience with cloud file storage. I can only offer assistance with local file storage.

      I hope this helps 🙂

      Regards,

  • mark_ellul

    Hi Nic, Do you have a git repo with all this code from this tutorial in an app?

    • I don’t have an example on Github, but when I have time I’ll see about crafting one. Did you have a particular question?

      If something isn’t working correctly or you are having trouble understanding something, just leave a comment and I’ll respond to it as soon as I get a chance 🙂

      Regards,

      • mark_ellul

        Thanks for responding quickly. I am very new to ionic, so I am trying to get my head around where the DropboxService.js would sit? (www/js/ ??). Also, how I could create it as a utility class, such that I am not including the app name in the invocation….
        i.e
        myDropboxApp.service(“DropboxService”, function($q, $ionicLoading) {

        to
        [in a re-usable util class]
        var DropboxService = , function($q, $ionicLoading) {

        [in the app.js ? or in the controller]

        myApp.service(“DropboxService”, DropboxService);

        etc….

        I guess I need to understand the order of execution of files in a project to understand where would be the best place to load app wide code.

        I think I may need to run through an end to end tutorial. Any suggestions?

        • Hi Mark,

          DropboxService is just an AngularJS service. You can choose to include it however you want as long as you follow the AngularJS rules.

          myDropboxApp doesn’t necessarily represent an application name. It is the variable that represents your angular.module if that makes sense.

          You may want to do some reading on AngularJS services as a start. Come back to me after you feel you’re confident in how they work.

          Regards,

  • Harry setati

    5 stars Nic

  • Tasha Loiseau

    I love this article, I’ve referenced it a few times now. Just to mention though, I had one issue with a 404 error that you didn’t address here. It has to do with making sure that the cordova whitelist plugin is installed so that your application can access internet services. After adding your android platform, just be sure to remember to add

    ionic plugin add cordova-plugin-whitelist

    • Awesome!

      Keep in mind that Dropbox announced that their datastore service will be terminated in 2016.

      Best,