playgameservices / android-basic-samples

Google Play game services - Android samples
Apache License 2.0
972 stars 970 forks source link

IllegalStateException when try to save snapshot after conflict resolved #123

Closed maklaus closed 9 years ago

maklaus commented 9 years ago

Hi there!

I used CollectAllTheStars2 sample to save/load game progress in one snapshot and without UI.

My code for saving Snapshot is:

void saveSnapshot() {
        AsyncTask<Void, Void, Snapshots.OpenSnapshotResult> task =
            new AsyncTask<Void, Void, Snapshots.OpenSnapshotResult>() {
                @Override
                protected Snapshots.OpenSnapshotResult doInBackground(Void... params) {
                    Snapshots.OpenSnapshotResult result = Games.Snapshots.open(getApiClient(),
                            currentSaveName, true).await();
                    return result;
                }

                @Override
                protected void onPostExecute(Snapshots.OpenSnapshotResult result) {
                    Snapshot toWrite = processSnapshotOpenResult(result, 0);

                    if (toWrite != null) Log.i(TAG, writeSnapshot(toWrite));
                }
            };

        task.execute();
    }
Snapshot processSnapshotOpenResult(Snapshots.OpenSnapshotResult result, int retryCount){
        retryCount++;
        int status = result.getStatus().getStatusCode();

        Log.i(TAG, "Save Result status: " + status);

        if (status == GamesStatusCodes.STATUS_OK) {
            return result.getSnapshot();
        } else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE) {
            return result.getSnapshot();
        } else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONFLICT && retryCount < MAX_SNAPSHOT_RESOLVE_RETRIES) {
            Snapshot snapshot = result.getSnapshot();
            Snapshot conflictSnapshot = result.getConflictingSnapshot();

            // Resolve between conflicts by selecting the newest of the conflicting snapshots.
            Snapshot mResolvedSnapshot = snapshot;

            if (snapshot.getMetadata().getLastModifiedTimestamp() < conflictSnapshot.getMetadata().getLastModifiedTimestamp()) {
                mResolvedSnapshot = conflictSnapshot;
            }

            resolveSnapshotConflict(result.getConflictId(), retryCount, mResolvedSnapshot);
        }
        // Fail, return null.
        return null;
    }
private void resolveSnapshotConflict(final String conflictId, final int retryCount, final Snapshot resolvedSnapshot) {
        Log.i(TAG,"Resolving conflict retry count = " + retryCount);
        AsyncTask<Void, Void, Snapshots.OpenSnapshotResult> task =
                new AsyncTask<Void, Void, Snapshots.OpenSnapshotResult>() {
                    @Override
                    protected Snapshots.OpenSnapshotResult doInBackground(Void... voids) {
                        return Games.Snapshots
                                .resolveConflict(getApiClient(), conflictId, resolvedSnapshot)
                                .await();
                    }

                    @Override
                    protected void onPostExecute(Snapshots.OpenSnapshotResult openSnapshotResult) {
                        Snapshot snapshot = processSnapshotOpenResult(openSnapshotResult, retryCount);
                        Log.d(TAG,"resolved snapshot conflict - snapshot is " + snapshot);
                    }
                };

        task.execute();
    }
private String writeSnapshot(Snapshot snapshot) {
        // Set the data payload for the snapshot.
        snapshot.writeBytes(getCCUserDefaultJSON().getBytes());

        // Save the snapshot.
        SnapshotMetadataChange metadataChange = new SnapshotMetadataChange.Builder().build();
        Games.Snapshots.commitAndClose(getApiClient(), snapshot, metadataChange);
        return snapshot.toString();
    }

I call saveSnapshot() and works fine, except when STATUS_SNAPSHOT_CONFLICT happened.

This case I' getting an error

java.lang.IllegalStateException
com.google.android.gms.common.internal.o.a(Unknown Source)
com.google.android.gms.games.snapshot.SnapshotContents.a(Unknown Source)
com.google.android.gms.games.snapshot.SnapshotContents.writeBytes(Unknown Source)
com.google.android.gms.games.snapshot.SnapshotEntity.writeBytes(Unknown Source)
com.MyCompany.MyGame.writeSnapshot(MyGame.java:504)
com.MyCompany.MyGame.access$4(MyGame.java:502)
com.MyCompany.MyGame$5.onPostExecute(MyGame.java:680)
com.MyCompany.MyGame$5.onPostExecute(MyGame.java:1)
android.os.AsyncTask.finish(AsyncTask.java:631)
android.os.AsyncTask.access$600(AsyncTask.java:177)
android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
android.os.Handler.dispatchMessage(Handler.java:107)
android.os.Looper.loop(Looper.java:194)
android.app.ActivityThread.main(ActivityThread.java:5370)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:525)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
dalvik.system.NativeStart.main(Native Method)

Any suggestions?

claywilkinson commented 9 years ago

@maklaus Is this still happening for you? If so, can you let me know what version of Google Play Services you have and a new log?

maklaus commented 9 years ago

Nope, now all fine. Thanks!