Cloud save: working implementation, no dialog to select your games yet

This commit is contained in:
Sergii Pylypenko
2014-07-09 20:50:16 +03:00
parent ed57fac3c9
commit 8e2ad620d8
18 changed files with 663 additions and 53 deletions

View File

@@ -19,8 +19,24 @@ package com.google.example.games.basegameutils;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import java.io.*;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.Scopes;
import com.google.android.gms.games.Games;
import com.google.android.gms.games.GamesStatusCodes;
import com.google.android.gms.games.snapshot.Snapshot;
import com.google.android.gms.games.snapshot.SnapshotMetadata;
import com.google.android.gms.games.snapshot.SnapshotMetadataBuffer;
import com.google.android.gms.games.snapshot.SnapshotMetadataChange;
import com.google.android.gms.games.snapshot.Snapshots;
public class CloudSave implements GameHelper.GameHelperListener {
@@ -40,54 +56,225 @@ public class CloudSave implements GameHelper.GameHelperListener {
mHelper.setup(this);
}
public GameHelper getGameHelper() {
return mHelper;
}
public void onStart() {
public void onStart()
{
mHelper.onStart(parent);
}
public void onStop() {
public void onStop()
{
mHelper.onStop();
}
public boolean save(String filename, String description, String imageFile)
public void onActivityResult(int request, int response, Intent data)
{
mHelper.onActivityResult(request, response, data);
}
public synchronized boolean save(String filename, String saveId, String dialogTitle, String description, String imageFile, long playedTimeMs)
{
Log.d("SDL", "CloudSave: save: file " + filename + " saveId " + saveId + " dialogTitle " + dialogTitle + " desc " + description + " imageFile " + imageFile + " playedTime " + playedTimeMs);
if( !signIn() )
return false;
if( !filename.startsWith("/") )
filename = Globals.DataDir + "/" + filename;
if( imageFile.length() > 0 && !imageFile.startsWith("/") )
imageFile = Globals.DataDir + "/" + imageFile;
try
{
if( saveId == null || saveId.length() == 0 )
{
Log.i("SDL", "CloudSave: save: user dialog is not supported yet");
return false;
}
Snapshots.OpenSnapshotResult result = Games.Snapshots.open(getApiClient(), saveId, true).await();
Snapshot crapshot = processSnapshotOpenResult(result, 0);
if( crapshot == null )
return false;
crapshot.writeBytes(readFile(filename));
Bitmap bmp = BitmapFactory.decodeFile(imageFile);
while( bmp != null && bmp.getByteCount() > Games.Snapshots.getMaxCoverImageSize(getApiClient()) )
bmp = Bitmap.createScaledBitmap(bmp, bmp.getWidth() * 3 / 4, bmp.getHeight() * 3 / 4, true);
SnapshotMetadataChange.Builder metadataChange = new SnapshotMetadataChange.Builder()
.setDescription(description)
.setPlayedTimeMillis(playedTimeMs);
if( bmp != null )
metadataChange.setCoverImage(bmp);
Games.Snapshots.commitAndClose(getApiClient(), crapshot, metadataChange.build())
.setResultCallback(new ResultCallback<Snapshots.CommitSnapshotResult>()
{
public void onResult(Snapshots.CommitSnapshotResult r)
{
Log.i("SDL", "CloudSave: save final net sync result: " + r.getStatus().toString());
}
});
Log.i("SDL", "CloudSave: save succeeded");
return true;
}
catch(Exception e)
{
Log.i("SDL", "CloudSave: save failed: " + e.toString());
}
return false;
}
public boolean load (String filename)
public synchronized boolean load(String filename, String saveId, String dialogTitle)
{
Log.d("SDL", "CloudSave: load: file " + filename + " saveId " + saveId + " dialogTitle " + dialogTitle);
if( !signIn() )
return false;
if( !filename.startsWith("/") )
filename = Globals.DataDir + "/" + filename;
try
{
if( saveId == null || saveId.length() == 0 )
{
Log.i("SDL", "CloudSave: load: user dialog is not supported yet");
return false;
}
Snapshots.OpenSnapshotResult result = Games.Snapshots.open(getApiClient(), saveId, false).await();
if (result.getStatus().getStatusCode() != GamesStatusCodes.STATUS_OK)
{
Log.i("SDL", "CloudSave: load: failed to load game " + saveId + ": " + result.getStatus());
return false;
}
boolean written = writeFile(filename, result.getSnapshot().readFully());
Log.i("SDL", "CloudSave: load: status: " + written);
return written;
}
catch(Exception e)
{
Log.i("SDL", "CloudSave: load failed: " + e.toString());
}
return false;
}
public class loadDialogResult
{
public boolean status = false;
public String filename = "";
}
public loadDialogResult loadDialog(String filename, String dialogTitle)
{
loadDialogResult res = new loadDialogResult();
res.status = false;
res.filename = "";
return res;
}
// ===== Private API =====
public void onActivityResult(int request, int response, Intent data) {
mHelper.onActivityResult(request, response, data);
boolean signInSucceeded = false;
boolean signInFailed = false;
public boolean signIn()
{
//Log.i("SDL", "CloudSave: signIn()");
if( !isSignedIn() )
{
signInSucceeded = false;
signInFailed = false;
Log.i("SDL", "CloudSave: beginUserInitiatedSignIn()");
beginUserInitiatedSignIn();
Log.i("SDL", "CloudSave: beginUserInitiatedSignIn() exit");
while (!signInSucceeded && !signInFailed)
{
try { Thread.sleep(300); } catch( Exception e ) {}
}
return signInSucceeded;
}
return true;
}
public void onSignInSucceeded() {
Log.i("SDL", "CloudSave: onSignInSucceeded()");
signInSucceeded = true;
}
public void onSignInFailed() {
Log.i("SDL", "CloudSave: onSignInFailed()");
signInFailed = true;
}
public Snapshot processSnapshotOpenResult(Snapshots.OpenSnapshotResult result, int retryCount)
{
Snapshot mResolvedSnapshot = null;
retryCount++;
int status = result.getStatus().getStatusCode();
Log.i("SDL", "CloudSave: processSnapshotOpenResult status: " + result.getStatus());
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().getPlayedTime() == conflictSnapshot.getMetadata().getPlayedTime()) {
if (snapshot.getMetadata().getLastModifiedTimestamp() < conflictSnapshot.getMetadata().getLastModifiedTimestamp()) {
mResolvedSnapshot = conflictSnapshot;
}
} else if (snapshot.getMetadata().getPlayedTime() < conflictSnapshot.getMetadata().getPlayedTime()) {
mResolvedSnapshot = conflictSnapshot;
}
Snapshots.OpenSnapshotResult resolveResult = Games.Snapshots.resolveConflict(
getApiClient(), result.getConflictId(), mResolvedSnapshot)
.await();
if (retryCount < 3) {
return processSnapshotOpenResult(resolveResult, retryCount);
} else {
Log.i("SDL", "CloudSave: could not resolve snapshot conflict");
}
}
Log.i("SDL", "CloudSave: could not get savegame snapshot");
return null;
}
static public byte[] readFile(String filename)
{
int len = (int)(new File(filename).length());
if( len == 0 )
return new byte[0];
try
{
byte buf[] = new byte[len];
if( new FileInputStream(filename).read(buf, 0, len) != len )
return new byte[0];
return buf;
}
catch( Exception e )
{
Log.i("SDL", "CloudSave: readFile() error: " + e.toString());
}
return new byte[0];
}
static public boolean writeFile(String filename, byte[] data)
{
try
{
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(filename));
out.write(data, 0, data.length);
out.close();
return true;
}
catch( Exception e )
{
Log.i("SDL", "CloudSave: writeFile() error: " + e.toString() + " file " + filename);
}
return false;
}
public GameHelper getGameHelper() {
return mHelper;
}
public GoogleApiClient getApiClient() {