Saved Games Snapshot initialization (null object reference)

白昼怎懂夜的黑 提交于 2020-01-04 09:12:04

问题


I am trying to use the new Saved Games (Snapshot) API

But I keep getting this error:

java.lang.NullPointerException: Attempt to invoke interface method 'boolean com.google.android.gms.games.snapshot.Snapshot.writeBytes(byte[])' on a null object reference


Here's the code for what I'm trying

Snapshot snapshot = new Snapshot();
snapshot.writeBytes(my_app_state);

// Save the snapshot.
SnapshotMetadataChange metadataChange
        = new SnapshotMetadataChange.Builder()
        .setDescription("Completed %" + (levelscompleted/totallevels) + " of levels.")
        .build();
Games.Snapshots.commitAndClose(getApiClient(), snapshot,
        metadataChange);


I'm trying to figure out how to initialize snapshot because = new Snapshot(); does not work.


回答1:


The Snapshot API is very specific in how you must do things. The following is the high-level procedure for Snapshot save:

  • Open the snapshot
  • Resolve conflicts
  • Save

The following code is from the Google Play Games Snapshot sample which shows you how to use Snapshots cross-platform across Android and iOS.

First, you must open the snapshot and resolve conflicts on open.

/**
 * Prepares saving Snapshot to the user's synchronized storage, conditionally resolves errors,
 * and stores the Snapshot.
 */
void saveSnapshot() {
    AsyncTask<Void, Void, Snapshots.OpenSnapshotResult> task =
            new AsyncTask<Void, Void, Snapshots.OpenSnapshotResult>() {
                @Override
                protected Snapshots.OpenSnapshotResult doInBackground(Void... params) {
                    Snapshots.OpenSnapshotResult result = Games.Snapshots.open(getApiClient(),
                            currentSaveName, true).await();
                    return result;
                }

                @Override
                protected void onPostExecute(Snapshots.OpenSnapshotResult result) {
                    Snapshot toWrite = processSnapshotOpenResult(result, 0);

                    Log.i(TAG, writeSnapshot(toWrite));
                }
            };

    task.execute();
}

Next, you must handle conflict resolution:

/**
 * Conflict resolution for when Snapshots are opened.
 * @param result The open snapshot result to resolve on open.
 * @return The opened Snapshot on success; otherwise, returns null.
 */
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) {
        return result.getSnapshot();
    } else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE) {
        return result.getSnapshot();
    } else if (status == GamesStatusCodes.STATUS_SNAPSHOT_CONFLICT){
        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;
        }

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

        if (retryCount < MAX_SNAPSHOT_RESOLVE_RETRIES){
            return processSnapshotOpenResult(resolveResult, retryCount);
        }else{
            String message = "Could not resolve snapshot conflicts";
            Log.e(TAG, message);
            Toast.makeText(getBaseContext(), message, Toast.LENGTH_LONG);
        }

    }
    // Fail, return null.
    return null;
}

The following code is how this is done in the Google Play Games Snapshots sample app:

/**
 * Generates metadata, takes a screenshot, and performs the write operation for saving a
 * snapshot.
 */
private String writeSnapshot(Snapshot snapshot){
    // Set the data payload for the snapshot.
    snapshot.writeBytes(mSaveGame.toBytes());

    // Save the snapshot.
    SnapshotMetadataChange metadataChange = new SnapshotMetadataChange.Builder()
            .setCoverImage(getScreenShot())
            .setDescription("Modified data at: " + Calendar.getInstance().getTime())
            .build();
    Games.Snapshots.commitAndClose(getApiClient(), snapshot, metadataChange);
    return snapshot.toString();
}



回答2:


I think, instead of creating Snapshot object explicitly. It should get generated in onActivityResult. So you need to handle it in onActivityResult. Then your writeBytes() will perform further operations.

Check documentation, In that loadFromSnapshot() contains

 Snapshot snapshot = result.getSnapshot();

So I think, you are getting null/false response on your onActivityResult. If not then follow same steps given in loadFromSnapshot() documentation.



来源:https://stackoverflow.com/questions/24924615/saved-games-snapshot-initialization-null-object-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!