Android Google Saved Games意外冲突

时间:2016-07-13 20:48:28

标签: android google-play-games

在我的游戏中,我有游戏币,我想将其价值保存到云端。我决定使用Google Saved Games API。一切都很好但是当我将数据保存到快照然后再次启动时读取它时,即使我在同一台设备上,我也会遇到冲突。现在我在每次改变后都保存货币的状态,所以当玩家花钱或获得一些“硬币”时。我认为这可能是非常频繁的,服务无法处理它,因为当我离线(没有连接到网络)时,一切都很好,但是当我在线(连接到Wi-Fi)工作时快照速度较慢,正如我所说,我与上次保存的数据以及我保存的先前数据发生冲突(我正在记录所有值......)。有时我甚至会遇到5次冲突。我有3个功能可以使用Saved Games。一个用于读取数据,一个用于保存数据,一个用于检查冲突:

阅读数据:

private void readSavedGame(final String snapshotName) {
    AsyncTask<Void, Void, Boolean> readingTask = new AsyncTask<Void, Void, Boolean>() {
        @Override
        protected Boolean doInBackground(Void... params) {
            Snapshots.OpenSnapshotResult result = Games.Snapshots.open(mGoogleApiClient, snapshotName, false).await();

            Snapshot snapshot = processSnapshotOpenResult(result, 0);

            if(snapshot != null) {
                try {
                    updateGameData(snapshot.getSnapshotContents().readFully());
                    Log.d(TAG, "Updating game: "+String.valueOf(coins)+"...");
                    return true;
                } catch (IOException e) {
                    Log.d(TAG, "Error: " + e.getMessage());
                }
            }

            return false;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);

            if(result) Log.d(TAG, "Game state read successfully...");
            else Log.d(TAG, "Error while reading game state...");

            updateUi();
        }
    };

    readingTask.execute();
}

保存数据:

private void writeSavedGame(final String snapshotName, final byte[] data) {
    AsyncTask<Void, Void, Boolean> updateTask = new AsyncTask<Void, Void, Boolean>() {
        @Override
        protected Boolean doInBackground(Void... params) {
            Snapshots.OpenSnapshotResult result = Games.Snapshots.open(
                    mGoogleApiClient, snapshotName, false).await();

            Snapshot snapshot = processSnapshotOpenResult(result, 0);

            if(snapshot != null) {
                snapshot.getSnapshotContents().writeBytes(getGameData());
                Log.d(TAG, "Saving: "+String.valueOf(coins)+"...");

                Snapshots.CommitSnapshotResult commitSnapshotResult = Games.Snapshots.commitAndClose(mGoogleApiClient, snapshot, SnapshotMetadataChange.EMPTY_CHANGE).await();

                if(commitSnapshotResult.getStatus().isSuccess()) return true;
            }

            return false;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            if (result) Log.d(TAG, "Game was saved successfully....");
            else Log.d(TAG, "Error while saving game state...");
        }
    };

    updateTask.execute();
}

检查冲突或处理 OpenSnapshotResult

Snapshot processSnapshotOpenResult(Snapshots.OpenSnapshotResult result, int retryCount) {
    Snapshot mResolvedSnapshot = null;
    retryCount++;

    int status = result.getStatus().getStatusCode();
    Log.i(TAG, "Save Result status: " + status);

    if (status == GamesStatusCodes.STATUS_OK) {
        Log.d(TAG, "No conflict, SNAPSHOT is OK");
        return result.getSnapshot();
    } else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE) {
        return result.getSnapshot();
    }
    else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONFLICT) {
        Log.d(TAG, "Conflict: "+String.valueOf(retryCount));

        Snapshot snapshot = result.getSnapshot();
        Snapshot conflictSnapshot = result.getConflictingSnapshot();

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

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

        try {
            Log.d(TAG, "Snapshot data: "+new String(snapshot.getSnapshotContents().readFully()));
            Log.d(TAG, "Conflicting data: "+new String(conflictSnapshot.getSnapshotContents().readFully()));
        } catch (IOException e) {
            Log.e(TAG, "ERROR WHILE READING SPAPSHOTS CONTENTS...");
        }


        Snapshots.OpenSnapshotResult resolveResult = Games.Snapshots.resolveConflict(
                mGoogleApiClient, result.getConflictId(), mResolvedSnapshot).await();

        if (retryCount < MAX_SNAPSHOT_RESOLVE_RETRIES) {
            // Recursively attempt again
            return processSnapshotOpenResult(resolveResult, retryCount);
        } else {
            // Failed, log error and show Toast to the user
            String message = "Could not resolve snapshot conflicts";
            Log.e(TAG, message);
            //Toast.makeText(getBaseContext(), message, Toast.LENGTH_LONG).show();
        }

    }

    // Fail, return null.
    return null;
}

很好地解释了冲突原则here。 我的代码基于official docs implementationssamples

因此,当离线时,一切都运行良好,但在连接时,我在同一设备上遇到冲突......也许我经常更新我保存的游戏,服务无法处理它。有任何想法吗?感谢。

1 个答案:

答案 0 :(得分:0)

Saved Games - Conflict resolution

中所述
  

通常,当您的应用程序实例在尝试加载数据或保存数据时无法访问已保存的游戏服务时,会发生数据冲突。通常,避免数据冲突的最佳方法是在应用程序启动或恢复时始终从服务加载最新数据,并以合理的频率将数据保存到服务中。

除此之外,还建议您按照Best practices for implementing saved games向玩家提供最佳产品。

另外,要了解如何为您的平台实施已保存的游戏,请参阅Client implementations中提供的资源。