简体   繁体   English

如何以静默方式下载Google Play游戏服务保存的游戏快照的数据?

[英]How to download a Google Play Games Services Saved Games Snapshot's Data, silently?

I'm trying to use Google's Saved Games feature with Google Play Games Services in my Android app. 我正在尝试在我的Android应用中将Google的“保存的游戏”功能与Google Play游戏服务一起使用。 Google provides sample code how to do so : Google提供了如何执行的示例代码

private static final int RC_SAVED_GAMES = 9009;
private String mCurrentSaveName = "snapshotTemp";

private void showSavedGamesUI() {
  SnapshotsClient snapshotsClient =
      Games.getSnapshotsClient(this, GoogleSignIn.getLastSignedInAccount(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);
    }
  });
}

@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
      // ...
    }
  }
}

Obviously, Google wants you to use their provided intent to let the user decide which saved game to load or if a new save game should be created. 显然,Google希望您使用他们提供的意图让用户决定要加载哪个已保存的游戏,或者是否应该创建一个新的保存游戏。

I, on the other hand, want to do this decision for the user. 另一方面,我想为用户做出此决定。 However, I'm unable to find a way to return a list of snapshots and to load snapshot data. 但是,我找不到返回快照列表和加载快照数据的方法。

Since my game won't require to maintain more than one saved game per user I'm less interested in getting a list of snapshots without an intent (which would be an interesting solution, though) and more in loading a snapshot based on the name of the saved game, silently. 由于我的游戏不需要为每个用户维护一个以上的已保存游戏,因此我对无意获取快照列表的兴趣较小(尽管这将是一个有趣的解决方案),而对基于名称加载快照的兴趣不大静默保存的游戏。

How can I load a snapshot without showing an intent? 如何加载快照而不显示意图?

The comment of jess leaded me to a solution that is now deprecated. 杰西(Jess)的评论使我提出了一个现已过时的解决方案。 However the person who posted the answer pointed out that there is also a working solution in the CollectAllTheStars sample app that is provided by Google. 但是,发布答案的人指出,Google提供的CollectAllTheStars示例应用程序中还有一个可行的解决方案。 I was tempted to check this sample app to find out if the Google team has changed the code to fit the new way. 我很想检查这个示例应用程序,以了解Google团队是否已更改代码以适应新的方式。 For my amuse the comments in that sample app were describing the old deprecated way, still, but the code was changed for my luck. 令我感到高兴的是,该示例应用程序中的注释仍在描述旧的不赞成使用的方式,但是由于我的运气,代码已更改。

Inspecting the code gave me ideas, so I came up with this solution: 检查代码给了我一些想法,因此我想出了以下解决方案:

String serializedSavedGameData;
public void downloadSavedGameData(final String name) {
    if(snapshotsClient != null) {
        snapshotsClient.open(name, true, SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED).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);
                } catch (NullPointerException e) {
                    Log.e(TAG, "Error while reading snapshot: ", e);
                }
                return null;
            }
        }).addOnCompleteListener(new OnCompleteListener<byte[]>() {
            @Override
            public void onComplete(@NonNull Task<byte[]> task) {
                if(task.isSuccessful()) {
                    byte[] data = task.getResult();
                    try {
                        serializedSavedGameData = new String(data, "UTF-16BE");
                    } catch (UnsupportedEncodingException e) {
                        Log.d(TAG, "Failed to deserialize save game data: " + e.getMessage());
                    }
                } else {
                    Exception ex = task.getException();
                    Log.d(TAG, "Failed to load saved game data: " + (ex != null ? ex.getMessage() : "UNKNOWN"));
                }
            }
        });
    }
}

I implemented a simple resolving policy (take the newest saved game on conflicts), but I had no time to hard test all the different cases like conflicts, but it passed my simple tests so far. 我实施了一个简单的解决策略(在冲突时使用最新保存的游戏),但是我没有时间来艰难地测试所有不同的情况,例如冲突,但是到目前为止,它已经通过了我的简单测试。

Hopefully anybody can profit from this. 希望任何人都可以从中受益。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM