2016-07-13 18 views
0

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.

+0

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

Antwort

0

Als

Typischerweise treten, Datenkonflikte in Saved Games - Conflict resolution diskutiert, wenn eine Instanz der Anwendung nicht in der Lage ist, den gespeicherte Spiele-Dienst zu erreichen, während der Daten oder speichern zu laden versuchen, zu. Im Allgemeinen ist der beste Weg, Datenkonflikte zu vermeiden, immer die neuesten Daten aus dem Dienst zu laden, wenn Ihre Anwendung startet oder fortsetzt, und Daten mit angemessener Häufigkeit im Dienst zu speichern.

Darüber hinaus wird empfohlen, Best practices for implementing saved games zu folgen, um Ihren Spielern das bestmögliche Produkt zu liefern. Weitere Informationen zum Implementieren von gespeicherten Spielen für Ihre Plattform finden Sie in den Ressourcen unter .