In meinem Spiel habe ich In-Game-Währung und ich möchte seinen Wert in der Cloud speichern. Ich habe mich für die Google Saved Games API entschieden. Alles funktioniert gut, aber wenn ich Daten in den Snapshots speichere und sie dann lese, wenn das Spiel wieder startet, bekomme ich Konflikte, selbst wenn ich auf demselben Gerät bin. Jetzt spare ich den Zustand der Währung nach jeder Änderung, also wenn der Spieler spendiert oder "Münzen" bekommt. Ich denke, das könnte sehr oft passieren und Dienste können damit nicht umgehen, denn wenn ich offline bin (ohne Verbindung zum Netzwerk), funktioniert alles gut und schnell, aber wenn ich online bin (verbunden mit Wi-Fi) arbeite ich mit Snapshots sind langsamer und wie gesagt habe ich Konflikte mit Daten, die ich zuletzt gespeichert habe und früheren Daten, die ich gespeichert habe (ich logg alle Werte ...). Manchmal bekomme ich sogar 5 Konflikte. Ich habe 3 Funktionen, um mit gespeicherten Spielen zu arbeiten. Eine zum Lesen von Daten, eine für Datensicherung und eine für Konflikte Überprüfung:Android Google Gespeicherte Spiele unerwartete Konflikte
Lesen von Daten:
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();
}
Speichern von Daten:
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();
}
Überprüfung auf Konflikte oder HandhabungOpenSnapshotResult
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;
}
Konflikt Principes sind schön erklärt . Mein Code basiert auf official docs implementations und samples.
Also, wenn offline, funktioniert alles hervorragend, aber wenn verbunden, bekomme ich Konflikte auf dem gleichen Gerät ... Vielleicht aktualisiere ich mein gespeichertes Spiel sehr oft und Dienste können damit nicht umgehen. Irgendwelche Ideen? Vielen Dank.
hast du es gelöst? Ich stehe vor demselben Problem. Derselbe Code funktioniert auf iCloud einwandfrei, aber bei Google werden zufällige Konflikte generiert. Ist es an die Sparfrequenz gebunden? Die "angemessene Häufigkeit" der Dokumente bedeutet nichts. – mcmorry