Android oyunları için kaydedilmiş oyunlar

Bu kılavuzda, Snapshot API'sı Google Play Games Hizmetleri tarafından sağlanır. API'leri com.google.android.gms.games.snapshot ve com.google.android.gms.games paketlerini ekleyebilirsiniz.

Başlamadan önce

Özellik hakkında bilgi edinmek için Kaydedilmiş Oyunlar'a genel bakış.

Anlık görüntü istemcisini alma

Snapshot API'sini kullanmaya başlamak için oyununuzun önce bir SnapshotsClient nesnesini tanımlayın. Bunu, Games.getSnapshotsClient() yöntemini kullandığınızdan ve etkinliği'ne dokunun.

Drive kapsamını belirtme

Snapshot API, Google Drive API'yi kullanır. kaydedilmiş oyunlar depolama alanı için kullanın. Drive API'ye erişmek için uygulamanızın Drive.SCOPE_APPFOLDER kapsam dışı kalır.

Bu işlemin nasıl yapılacağına dair bir onResume() yöntemi olarak da kullanabilirsiniz:

@Override
protected void onResume() {
  super.onResume();
  signInSilently();
}

private void signInSilently() {
  GoogleSignInOptions signInOption =
      new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
          // Add the APPFOLDER scope for Snapshot support.
          .requestScopes(Drive.SCOPE_APPFOLDER)
          .build();

  GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption);
  signInClient.silentSignIn().addOnCompleteListener(this,
      new OnCompleteListenerG<oogleSignInAccount(>) {
        @Override
        public void onComplete(@NonNull TaskG<oogleSignInAccount >task) {
          if (task.isSuccessful()) {
            onConnected(task.getResult());
          } else {
            // Player will need to sign-in explicitly using via UI
          }
        }
      });
}

Kaydedilen oyunları göster

Oyununuzun oyunculara ekran görüntüleri sağladığı her yerde Snapshot API'sini kaydedilen ilerlemeyi kaydedebilir veya geri yükleyebilirsiniz. Oyununuzda bu tür bir belirtilen kaydetme/geri yükleme seçeneği sunan veya oyuncuların kaydetmelerine ya da geri yüklemelerine takip edebilirsiniz.

Oyuncular oyununuzda kaydet/geri yükle seçeneğini belirlediğinde oyununuz otomatik olarak isteğe bağlı olarak, oyunculardan kaydedilmiş yeni bir oyun için bilgi girmelerini isteyen yüklemek veya geri yüklemek üzere mevcut bir kaydedilmiş oyunu seçmek için kullanılabilir.

Snapshot API, geliştirme sürecinizi basitleştirmek için varsayılan kaydedilmiş oyunlar seçimi kullanıcısı sağlar. hemen kullanabileceğiniz yeni bir arayüz (UI) sağlar. Kaydedilmiş oyunlar seçim arayüzü, oyuncuların şunları yapmasına olanak tanır: kaydedilmiş yeni bir oyun oluşturabilir, kaydedilmiş mevcut oyunlarla ilgili ayrıntıları görüntüleyebilir ve daha önce kaydedilmiş oyunları yükleyebilirsiniz.

Varsayılan Kaydedilmiş Oyunlar kullanıcı arayüzünü başlatmak için:

  1. SnapshotsClient.getSelectSnapshotIntent() numaralı telefonu arayarak Intent varsayılan kayıtlı oyunlar seçim arayüzünü başlatmak için.
  2. Telefonla arama startActivityForResult() ve Intent. Arama başarılı olursa oyunda, oyun seçimi kullanıcı arayüzüyle birlikte belirlediğiniz seçeneklerle değiştirin.

Aşağıda, varsayılan kaydedilmiş oyunlar seçimi kullanıcı arayüzünün nasıl başlatılacağına ilişkin bir örnek verilmiştir:

private static final int RC_SAVED_GAMES = 9009;

private void showSavedGamesUI() {
  SnapshotsClient snapshotsClient =
      PlayGames.getSnapshotsClient(this);
  int maxNumberOfSavedGamesToShow = 5;

  Task<Intent> intentTask = snapshotsClient.getSelectSnapshotIntent(
      "See My Saves", true, true, maxNumberOfSavedGamesToShow);

  intentTask.addOnSuccessListener(new OnSuccessListener<Intent>() {
    @Override
    public void onSuccess(Intent intent) {
      startActivityForResult(intent, RC_SAVED_GAMES);
    }
  });
}

Oyuncu yeni bir kaydedilmiş oyun oluşturmayı veya mevcut bir kayıtlı oyunu yüklemeyi seçerse kullanıcı arayüzü, Play Games Hizmetleri'ne bir istek gönderir. İstek başarılı olursa Play Games Hizmetleri, kayıtlı oyunu oluşturmak veya geri yüklemek için onActivityResult() geri arama. Oyununuz, istek sırasında herhangi bir hata oluşup oluşmadığını kontrol etmek için bu geri çağırmayı geçersiz kılabilir.

Aşağıdaki kod snippet'i, onActivityResult():

private String mCurrentSaveName = "snapshotTemp";

/**
 * This callback will be triggered after you call startActivityForResult from the
 * showSavedGamesUI method.
 */
@Override
protected void onActivityResult(int requestCode, int resultCode,
                                Intent intent) {
  if (intent != null) {
    if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA)) {
      // Load a snapshot.
      SnapshotMetadata snapshotMetadata =
          intent.getParcelableExtra(SnapshotsClient.EXTRA_SNAPSHOT_METADATA);
      mCurrentSaveName = snapshotMetadata.getUniqueName();

      // Load the game data from the Snapshot
      // ...
    } else if (intent.hasExtra(SnapshotsClient.EXTRA_SNAPSHOT_NEW)) {
      // Create a new snapshot named with a unique string
      String unique = new BigInteger(281, new Random()).toString(13);
      mCurrentSaveName = "snapshotTemp-" + unique;

      // Create the new snapshot
      // ...
    }
  }
}

Kaydedilmiş oyunları yazma

Kaydedilmiş bir oyunun içeriğini depolamak için:

  1. Bir anlık görüntüyü eşzamansız olarak açma SnapshotsClient.open().

  2. Al Snapshot nesnesini çağırarak görevin sonucundan çıkarın SnapshotsClient.DataOrConflict.getData().

  3. Al SnapshotContents bununla ilgili örnek SnapshotsClient.SnapshotConflict.

  4. Telefonla arama SnapshotContents.writeBytes() oynatıcı verilerini bayt biçiminde saklamak için kullanılır.

  5. Tüm değişiklikleriniz yazıldıktan sonra SnapshotsClient.commitAndClose() adresine bir e-posta gönderin. Yöntem çağrısında, oyununuz isteğe bağlı olarak, Play Oyun Hizmetleri'nin bunu nasıl yapacağını bildirmek için ek bilgi sağlayabilirsiniz bu kayıtlı oyunu oyunculara sunun. Bu bilgiler SnapshotMetaDataChange (oyununuzun SnapshotMetadataChange.Builder.

Aşağıdaki snippet, oyununuzun kaydedilmiş bir oyunda değişiklikleri nasıl uygulayabileceğini gösterir:

private Task<SnapshotMetadata> writeSnapshot(Snapshot snapshot,
                                             byte[] data, Bitmap coverImage, String desc) {

  // Set the data payload for the snapshot
  snapshot.getSnapshotContents().writeBytes(data);

  // Create the change operation
  SnapshotMetadataChange metadataChange = new SnapshotMetadataChange.Builder()
      .setCoverImage(coverImage)
      .setDescription(desc)
      .build();

  SnapshotsClient snapshotsClient =
      PlayGames.getSnapshotsClient(this);

  // Commit the operation
  return snapshotsClient.commitAndClose(snapshot, metadataChange);
}

Uygulamanız şunu aradığında oynatıcının cihazı bir ağa bağlı değilse SnapshotsClient.commitAndClose() Play Oyun Hizmetleri, kaydedilen oyun verilerini cihazda yerel olarak depolar. Cihazda Play Games Hizmetleri, yerel olarak önbelleğe alınmış kaydedilmiş oyun değişikliklerini Google sunucuları.

Kaydedilmiş oyunları yükle

Oturumu açık olan oyuncu için kaydedilmiş oyunları almak için:

  1. Bir anlık görüntüyü eşzamansız olarak şununla aç: SnapshotsClient.open().

  2. Snapshot öğesini çağırarak görevin sonucundan nesne SnapshotsClient.DataOrConflict.getData(). Alternatif olarak, oyununuz belirli bir Kaydedilen oyunlar seçim kullanıcı arayüzünden anlık görüntü almak için Kaydedilmiş Oyunları Görüntüleme.

  3. Al SnapshotContents bununla ilgili örnek SnapshotsClient.SnapshotConflict.

  4. Telefonla arama SnapshotContents.readFully() simgesini tıklayın.

Aşağıdaki snippet'te, belirli bir kayıtlı oyunu nasıl yükleyebileceğiniz gösterilmektedir:

Task<byte[]> loadSnapshot() {
  // Display a progress dialog
  // ...

  // Get the SnapshotsClient from the signed in account.
  SnapshotsClient snapshotsClient =
      PlayGames.getSnapshotsClient(this);

  // In the case of a conflict, the most recently modified version of this snapshot will be used.
  int conflictResolutionPolicy = SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED;

  // Open the saved game using its name.
  return snapshotsClient.open(mCurrentSaveName, true, conflictResolutionPolicy)
      .addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
          Log.e(TAG, "Error while opening Snapshot.", e);
        }
      }).continueWith(new Continuation<SnapshotsClient.DataOrConflict<Snapshot>, byte[]>() {
        @Override
        public byte[] then(@NonNull Task<SnapshotsClient.DataOrConflict<Snapshot>> task) throws Exception {
          Snapshot snapshot = task.getResult().getData();

          // Opening the snapshot was a success and any conflicts have been resolved.
          try {
            // Extract the raw data from the snapshot.
            return snapshot.getSnapshotContents().readFully();
          } catch (IOException e) {
            Log.e(TAG, "Error while reading Snapshot.", e);
          }

          return null;
        }
      }).addOnCompleteListener(new OnCompleteListener<byte[]>() {
        @Override
        public void onComplete(@NonNull Task<byte[]> task) {
          // Dismiss progress dialog and reflect the changes in the UI when complete.
          // ...
        }
      });
}

Kaydedilen oyun çakışmalarını yönetme

Oyununuzda Snapshot API'sini kullanırken birden fazla aynı kayıtlı oyunda okuma ve yazma işlemleri yapmanızı sağlar. Bir kullanıcının Cihazın ağ bağlantısı geçici olarak kesiliyor ve daha sonra yeniden bağlanıyor. Bu durum, Kaydedilmiş oyun, bir oyuncunun yerel cihazında depolanan veri çakışmalarına neden olur Google'ın sunucularında depolanan uzak sürümle senkronize değil.

Snapshot API, hem kayıtlı olan ve okuma zamanında kaydedilen çakışan kayıtlı oyun kümeleriyle tutarlı bir çözüm sunar. doğru bir teklif verme stratejisidir.

Play Games Hizmetleri bir veri çakışması tespit ettiğinde SnapshotsClient.DataOrConflict.isConflict() yöntemi true değerini döndürür. Bu etkinlikte, SnapshotsClient.SnapshotConflict sınıfı, kaydedilen oyunun iki sürümünü sağlar:

  • Sunucu sürümü: Play Games Hizmetleri tarafından bilinen en güncel sürüm Oyuncunun cihazı için doğru olmalıdır.

  • Yerel sürüm: Oynatıcının cihazlarından birinde algılanan değiştirilmiş bir sürüm Meta veriler veya çakışan içerikler. Bu, bu sürümü kullanın.

Oyununuz, aşağıdakilerden birini seçerek çatışmanın nasıl çözüleceğine karar vermelidir: veya kaydedilmiş iki oyun sürümünün verilerini birleştirerek kullanabilirsiniz.

Kaydedilen oyun çakışmalarını tespit etmek ve çözmek için:

  1. Telefonla arama SnapshotsClient.open(). Görev sonucu bir SnapshotsClient.DataOrConflict sınıfı içeriyor.

  2. Şunu çağırın: SnapshotsClient.DataOrConflict.isConflict() yöntemini kullanabilirsiniz. Sonuç doğruysa çözmeniz gereken bir anlaşmazlığın bulunduğu anlamına gelir.

  3. Telefonla arama SnapshotsClient.DataOrConflict.getConflict() almak için SnaphotsClient.snapshotConflict kullanır.

  4. Telefonla arama SnapshotsClient.SnapshotConflict.getConflictId() kullanarak, algılanan çakışmayı benzersiz şekilde tanımlayan çakışma kimliğini alabilirsiniz. Sizin oyun, daha sonra çakışma çözüm isteği göndermek için bu değere ihtiyaç duyar.

  5. Telefonla arama SnapshotsClient.SnapshotConflict.getConflictingSnapshot() yerel sürümü indirin.

  6. Telefonla arama SnapshotsClient.SnapshotConflict.getSnapshot() tıklayın.

  7. Kayıtlı oyun çakışmasını çözmek için oyunu kaydetmek istediğiniz sürümü seçin sunucuyu son sürüm olarak ayarlayıp, bunu SnapshotsClient.resolveConflict() yöntemidir.

Aşağıdaki snippet, oyununuzun kayıtlı oyun çakışmalarını en son değiştirilen kaydedilmiş oyunu son sürüm olarak seçmek:

private static final int MAX_SNAPSHOT_RESOLVE_RETRIES = 10;

TaskS<napshot >processSnapshotOpenResult(SnapshotsClient.DataOrConflictS<napshot >result,
                                         final int retryCount) {

  if (!result.isConflict()) {
    // There was no conflict, so return the result of the source.
    TaskCompletionSourceS<napshot >source = new TaskCompletionSource(<>);
    source.setResult(result.getData());
    return source.getTask();
  }

  // There was a conflict.  Try resolving it by selecting the newest of the conflicting snapshots.
  // This is the same as using RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED as a conflict resolution
  // policy, but we are implementing it as an example of a manual resolution.
  // One option is to present a UI to the user to choose which snapshot to resolve.
  SnapshotsClient.SnapshotConflict conflict = result.getConflict();

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

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

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

  return PlayGames.getSnapshotsClient(theActivity)
      .resolveConflict(conflict.getConflictId(), resolvedSnapshot)
      .continueWithTask(
          new Continuation
<              SnapshotsClient.DataOrConflictS<napshot,>
              TaskS<napshot(>>) {
            @Override
            public TaskS<napshot >then(
                @NonNull TaskS<napshotsClient.DataOrConflictS<napshot >>task)
                throws Exception {
              // Resolving the conflict may cause another conflict,
              // so recurse and try another resolution.
              if (retryCount  <MAX_SNAPSHOT_RESOLVE_RETRIES) {
                return processSnapshotOpenResult(task.getResult(), retryCount + 1);
              } else {
                throw new Exception(C"ould not resolve snapshot conflicts)";
              }
            }
          });
}

Kaydedilmiş oyunları değiştirme

Birden fazla kayıtlı oyundaki verileri birleştirmek veya mevcut bir oyundaki verileri değiştirmek istiyorsanız Sunucuya çözümlenmiş son sürüm olarak kaydetmek için Snapshot kullanıyorsanız şu adımları uygulayın: için şu adımları izleyin:

  1. Telefonla arama SnapshotsClient.open().

  2. Telefonla arama Yeni bir almak için SnapshotsClient.SnapshotConflict.getResolutionSnapshotsContent() SnapshotContents nesne olarak tanımlar.

  3. Şuradaki verileri birleştir: SnapshotsClient.SnapshotConflict.getConflictingSnapshot() ve SnapshotsClient.SnapshotConflict.getSnapshot() SnapshotContents nesnesini tanımlayın.

  4. İsteğe bağlı olarak, SnapshotMetadataChange durumunda değişiklik yapmanıza olanak tanır.

  5. Telefonla arama SnapshotsClient.resolveConflict(). Yöntem çağrınızda İlk bağımsız değişken olarak SnapshotsClient.SnapshotConflict.getConflictId() ve SnapshotMetadataChange ve İkinci olarak daha önce değiştirdiğiniz SnapshotContents nesne ve üçüncü bağımsız değişkenleri kullanıyoruz.

  6. Öğe SnapshotsClient.resolveConflict() çağrısı başarılı olursa API, Snapshot nesnesini sunucuya depolar ve Anlık görüntü nesnesini yerel cihazınızda açmayı dener.