Search code examples
androiddatabasesynchronizationcloudandroid-contentprovider

Android synching data between users


I have an android app that maintains a local SQLite database of different geographic locations.

Now I would like to connect that database to the "cloud" to accomplish the following:

  • an initial download of everything, when the app is first installed (or on request)

  • new locations that have been added locally should be uploaded to the cloud (automatically)

  • the online database should be checked occasionally for new online entries, and downloaded to the local database.

I have a number of problems in accomplishing this.

The first is simply how to do it. I think it involves contentProviders and syncProviders, but I'm not exactly sure how. Do I need to duplicate my SQLite database in a contentProvider, or have I made a mistake in the underlying design to use a database directly, instead of through a custom content Provider?

Secondly, the location records cannot simply be copied up and down from the online database, since they will have conflicting ID numbers. I have several relational tables, such as "tags" which relate a tag-id to a location-id. My tag-ids will not necessarily match another users tag-ids. Same with location ids. So there will need to be some logic involved in the transfer. Where / how should this be properly handled? Is that the role of a contentResolver? (not sure what that is really)

Thirdly, what happens in the case where 2 users add the same location at the same time (perhaps with differing descriptions and details)? Is there a best-practice for merging these records?

Finally, what is the simplest way to build / host the online component? This part is all new to me. Can I just put the master database in a public dropbox folder, or do I need to build a custom php web-app from scratch? Or is there a pre-packaged solution that would make this part easier?


Solution

  • You should definitely use ContentProvider and SyncAdapters. You should:

    • Wrap your database functionality with the ContentProvider interface
    • Setup a SyncService matching the authority of the ContentProvider
    • In your SyncAdapter specialization, you will override onPerformSync()
    • Use SharedPreferences storage to keep track of your sync parameters e.g. lastSync time, etc.

      final SharedPreferences syncMeta =
                          mContext.getSharedPreferences("sync:" + account.name, 0);
      long lastSyncTime = syncMeta.getLong(LAST_SYNC, 0);
      long lastServerSyncTime = syncMeta.getLong(SERVER_LAST_SYNC, 0);
      
    • This can easily tell you if its the first sync and you can do the initial handling here

    • You will write your algorithm here for sync i.e one way/two way.
    • I find it useful to record timestamps and server database ID in your Android records to help with sync. This can help you with your merge strategy.
    • Use the ContentProvider here for DB operations. ContentProviders provide a uniform way of accessing your data from your app as well as sync adapters. They will notify the system of updates so that the framework and schedule sync. They can also be helpful as public interfaces of your data to other apps should you choose to do so.

    • Also, by using SyncService you are saving battery. The system will use network tickles to kick of sync operations and its best if they are batched together for all apps instead of each app waking up the system

    Finally,

    There are two samples you should look at. They pretty much cover everything I explained

    1. JumpNote - http://code.google.com/p/jumpnote/source/browse/
    2. SampleSyncAdapter - http://developer.android.com/resources/samples/SampleSyncAdapter/index.html

    Both these apps use Google App Engine for the cloud component. Its easy to get started with, so definitely explore that options.