Google Play Game Services

Cloud Save in Android

This guide shows you how to save and load a user's application state using the Cloud Save service (also known as the "app state service") in an Android application.

Understanding Cloud Save

If you haven't already done so, you might find it helpful to review the Cloud Save guide to familiarize yourself with the concepts behind saving a user's application state using this service.

Setting Up

In order to use the Cloud Save service, follow the instructions for installing and setting up your app to use Google Play services in the Setup Google Play Services SDK guide.

Initializing the client

Before making calls to the Cloud Save service, your app must initialize an GoogleApiClient object and establish a connection to the Google Play servers. For an example of how to implement the connection flow, see the BaseGameActivity and GameHelper classes provided in the Android code samples for the Play Games services SDK.

Updating the manifest

To enable use of the Cloud Save service in your app, update your app's AndroidManifest.xml by adding the following meta-data tag:

<manifest ...>
    <application ...>
        <meta-data android:name="com.google.android.gms.appstate.APP_ID"
        android:value="@string/app_id" />

        ...
    </application>
</manifest>

Make sure you set the app_id in /resource/values.xml to the value provided by the Android developer console. For more information about obtaining a Client ID for your app, see Setting Up Play Games Services.

Saving data

To save the user's application state information to the cloud, call the update() method specifying the data slot and the application state data to be stored:

byte[] my_app_state = ... ;
if (mSignedIn) {
    AppStateManager.update(getApiClient(), key, my_app_state);
}

In the update() method, the first parameter is a reference to the GoogleApiClient, the second parameter specifies the data location in which to save the application state data, and the third parameter is a byte array with data that can be up to 256 kilobytes in size.

If the user does not have an Internet connection when your app calls update(), the state data is stored locally, and then synced with Google's servers in the background when a connection is available. If a conflict occurs during a background update, your app is notified the next time it requests a load.

Loading data

To retrieve and load application state information from the cloud, call the load() method:

AppStateManager.load(getApiClient(), key);

Handling results

On the Android platform, read and write operations your app makes to the Cloud Save service are performed asynchronously. The results of data operations are returned as objects implementing the PendingResult interface. To retrieve the operation results, your app can register a callback by calling the setResultCallback(). After the Cloud Save service receives a read or write operation request from your app, the service calls the onResult() method in your callback and passes it a StateResult object.

Your app can check if there is a conflict between the local data and the data stored in the cloud, by calling getConflictResult(). If the call returns a non-null StateConflictResult object, there is a data conflict which your app needs to resolve. After applying an appropriate data resolution strategy, your app should call resolve() to upload the consolidated data. For more information about handling data conflicts, see Resolving data conflicts.

Your app can also check if a data upload operation was successful, by calling getLoadedResult(). If the call returns a non-null StateLoadedResult object, the data was uploaded successfully and did not result in any conflicts.

The following snippet shows how your app might call load() to save data to the cloud:

AppStateManager.load(getApiClient(), OUR_STATE_KEY).setResultCallback(
    new ResultCallback<AppStateManager.StateResult>() {

    @Override
    public void onResult(AppStateManager.StateResult result) {
        AppStateManager.StateConflictResult conflictResult 
            = result.getConflictResult();
        AppStateManager.StateLoadedResult loadedResult 
            = result.getLoadedResult();
        if (loadedResult != null) {
            processStateLoaded(loadedResult);
        } else if (conflictResult != null) {
            processStateConflict(conflictResult);
        }
    }
}

Resolving data conflicts

If there is a conflict between the local state data and the state currently stored on the server, the Cloud Save service returns a non-null StateConflictResult to alert your app to the conflict. The result object includes both the data your app requested to be saved and the current version of the data that is saved on Google's servers. Your app must decide how to resolve the conflict by picking one of the provided data versions or merging the two data sets. Try to resolve data conflicts so that your users don't lose data that is important to them, such as game progress or recently bookmarked news articles. For general information on how to resolve data conflicts, see the Cloud Save guide.

Once you have a version of the data that resolves the conflict, your app should call the resolve() method and pass in the data that you want to save.

The following snippet shows how your app might resolve a data conflict when loading game progress data:

private void processStateConflict(AppStateManager.StateConflictResult 
    result) {

    // Need to resolve conflict between the two states.
    // In this example, we use the resolution strategy of taking the union 
    // of the two sets of cleared levels, which means preserving the 
    // maximum star rating of each cleared level:
    byte[] serverData = result.getServerData();
    byte[] localData = result.getLocalData();

    SaveGame localGame = new SaveGame(localData);
    SaveGame serverGame = new SaveGame(serverData);
    SaveGame resolvedGame = localGame.unionWith(serverGame);

    AppStateManager.resolve(getApiClient(), result.getStateKey(), 
        result.getResolvedVersion(), resolvedGame.toBytes());
}

To learn how to design a data structure for your cloud save data that supports a more robust conflict resolution strategy, see Resolving Cloud Save Conflicts.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.