问题
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