Search code examples
ioscordovabackupstorageicloud

Cordova automatically sync data between several IOS devices using iCloud


I have built an universal hybrid app for IOS devices using Cordova. In this app, some data (like score, level progression, settings, preferences, etc) are saved locally using the JavaScript object LocalStorage. By this way, when the user quit the app and open it later, everything is like before (as in almost all games :)

What I'm trying to do is to automatic sync this LocalObject (containing all data) with the other IOS devices of the user without forcing him to be connected to Game Center or any other account (except iCloud of course).

Example: user starts to play on iPhone then later, at home, he wants to continue on his iPad.

So I read the Cordova documentation and I understood I have to set the BackupWebStorage value to "cloud" in the config.xml file to store the data in the cloud then get it automatically from other devices...

<platform name="ios">
    <preference name="BackupWebStorage" value="cloud"/>
</platform>

After that step, I published my app through the TestFlight and I installed it both on my iPhone and iPad... But unfortunately, it doesn't work... The LocalObject doesn't sync automatically via iCloud.

I did some research on the web about this question and I found nothing clear. I found tones of examples for syncing data between an app and a server (which I know how to do) but nothing about my question...

Could you advise me some technics? May be a demo link? An examples?

I'm pretty sure what I want to do is possible because I have some app installed on my IOS devices working as I explained. For example, when I play with the famous Alto's Adventure, If I switch between my IOS devices during the game, all my progression is immediately and automatically sync between my devices. However, I'm not connected to the Game Center or any other account...

So? How does this work? Thanks!


Solution

  • I found a way to sync data between iOS devices connected to a same iCloud account in a Cordova project. Let see how it works:

    1 - Cordova config.xml

    In your config.xml file, you ave to set the preference parameter BackupWebStorage to right value. Choose "cloud":

    <platform name="ios">
         <preference name="BackupWebStorage" value="cloud"/>
    </platform>
    

    2 - Xcode capabilities settings

    Open your /platforms/ios/myProjectName.xcodeproj file in Xcode. In the capabilities tab, you have to switch on the iCloud parameter. Then you can choose the way you want to sync data between Apple devices.

    • Key-Value storage
    • iCloud Documents
    • CloudKit

    In my case, I just need to sync datas as key-value storage such as {"playerID":"123456"}.

    Xcode Capabilities tab - iCloud key-value Storage

    3 - Add icloudkv plugin to sync key-value datas

    Then you have to add a plugin to your Cordova project to be able to sync datas. I used the cordova-plugin-icloudkv which works well for my needs. You can add it using CLI (Terminal on Mac OSX):

    $ cordova plugin add cordova-plugin-icloudkv
    

    Once is done, you can start adding JavaScript code to your project. Right after the device.ready() function has been called, you have to call this function only once:

    iCloudKV.sync(syncSuccess, syncError);
    
    function syncSuccess(_dictionary){
        // You can retrieve into the _dictionary object datas saved in the cloud.
        // Example with datas I have saved:
        var playerID = _dictionary['playerID'];
        var deviceUUID = _dictionary['deviceUUID'];
    }
    

    You don't have to call this function again later, you only need to initialized it once at the beginning. After the syncSuccess() function has been called and has returned "success" state, you can now save, get, and remove datas into this object like this:

     iCloudKV.save(_key, _val, saveSuccess);
     iCloudKV.load(_key, loadSuccess, loadError);
     iCloudKV.remove(_key, removeSuccess);
    

    Voilà!

    I think there is an important point to understand with this plugin. That was unclear for me at the beginning so let's discuss it:

    When you save or remove a key from the iCloudKV object, you are not dealing with the real iCloud in real time. The iCloudKV object is a local object (if I'm wrong please let me know), which will be checked and analyzed by the real iOS syncing datas process. The iOS syncing process manage the iCloudKV object by itself, you can't directly ask to iCloud to save this or remove this. You only talk with the iCloudKV object.

    For example when you save a key-value one your device1 using this plugin. This key-value is saved into the local iCloudKV object. You can't get it right after on the device2.

    When you quit the app on device1, the iOS syncing data process will check your iCloudKV object, then if needed, will sync it on the real iCloud account online. If you launch your app now on the device2 (connected to the same iCloud account), the iOS syncing process will sync your datas, then the iCloudKV object will be able to return them to you.

    By this way, you can't see changes between your device1 and your device2 in real time. First you have to wait the iOS syncing process does the job. I did lot of test before understanding this concept :)

    I hope this will help somebody. Thanks!