From bfee524d25e8bc91eaee8d69ceb37e01d467e366 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Wed, 9 Jul 2014 23:19:19 +0300 Subject: [PATCH] Cloud save: working save/load dialog --- .../googleplaygameservices/CloudSave.java | 80 ++++++++++++++++--- .../biniax2/AndroidAppSettings.cfg | 4 +- project/jni/application/biniax2/src/biniax.c | 6 +- .../src/video/android/SDL_androidvideo.c | 2 +- project/proguard.cfg | 17 ++-- 5 files changed, 86 insertions(+), 23 deletions(-) diff --git a/project/java/googleplaygameservices/CloudSave.java b/project/java/googleplaygameservices/CloudSave.java index ae22aeadb..1c6eadb2d 100644 --- a/project/java/googleplaygameservices/CloudSave.java +++ b/project/java/googleplaygameservices/CloudSave.java @@ -23,6 +23,8 @@ import android.graphics.BitmapFactory; import android.graphics.Bitmap; import java.io.*; +import java.util.concurrent.Semaphore; +import java.util.Random; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; @@ -45,12 +47,15 @@ public class CloudSave implements GameHelper.GameHelperListener { MainActivity parent; + Semaphore semaphore; + // ===== Public API ===== public CloudSave(MainActivity p) { Log.i("SDL", "CloudSave: initializing"); parent = p; + semaphore = new Semaphore(0); mHelper = new GameHelper(parent, GameHelper.CLIENT_SNAPSHOT); mHelper.setMaxAutoSignInAttempts(0); mHelper.setup(this); @@ -66,9 +71,29 @@ public class CloudSave implements GameHelper.GameHelperListener { mHelper.onStop(); } - public void onActivityResult(int request, int response, Intent data) + SnapshotMetadata crapshotMetadata = null; + boolean createNewSave = false; + public void onActivityResult(int request, int response, Intent intent) { - mHelper.onActivityResult(request, response, data); + Log.d("SDL", "CloudSave: onActivityResult() response " + response + " intent " + (intent != null)); + try + { + if (intent != null && intent.hasExtra(Snapshots.EXTRA_SNAPSHOT_NEW)) + { + createNewSave = true; + } + if (intent != null && intent.hasExtra(Snapshots.EXTRA_SNAPSHOT_METADATA)) + { + crapshotMetadata = (SnapshotMetadata) + intent.getParcelableExtra(Snapshots.EXTRA_SNAPSHOT_METADATA); + } + } + catch (Exception e) + { + Log.w("SDL", "CloudSave: onActivityResult(): error: " + e.toString()); + } + //mHelper.onActivityResult(request, response, data); + semaphore.release(); } public synchronized boolean save(String filename, String saveId, String dialogTitle, String description, String imageFile, long playedTimeMs) @@ -87,8 +112,27 @@ public class CloudSave implements GameHelper.GameHelperListener { { if( saveId == null || saveId.length() == 0 ) { - Log.i("SDL", "CloudSave: save: user dialog is not supported yet"); - return false; + // Show dialog to the user + // Specifying Snapshots.DISPLAY_LIMIT_NONE will cause the dialog to hide "New game" button for some reason + final Intent snapshotIntent = Games.Snapshots.getSelectSnapshotIntent(getApiClient(), dialogTitle, true, true, 1000); + semaphore.drainPermits(); + crapshotMetadata = null; + createNewSave = false; + parent.runOnUiThread(new Runnable() + { + public void run() + { + parent.startActivityForResult(snapshotIntent, 0); + } + }); + semaphore.acquireUninterruptibly(); + Log.d("SDL", "CloudSave: save: user selected: " + (crapshotMetadata == null ? "null" : crapshotMetadata.getUniqueName()) + " new " + createNewSave); + if( createNewSave ) + saveId = "" + System.currentTimeMillis() + "-" + new Random().nextInt(100000); + else if( crapshotMetadata != null ) + saveId = crapshotMetadata.getUniqueName(); + else + return false; } Snapshots.OpenSnapshotResult result = Games.Snapshots.open(getApiClient(), saveId, true).await(); @@ -141,8 +185,23 @@ public class CloudSave implements GameHelper.GameHelperListener { { if( saveId == null || saveId.length() == 0 ) { - Log.i("SDL", "CloudSave: load: user dialog is not supported yet"); - return false; + // Show dialog to the user + final Intent snapshotIntent = Games.Snapshots.getSelectSnapshotIntent(getApiClient(), dialogTitle, false, true, 1000); + semaphore.drainPermits(); + crapshotMetadata = null; + createNewSave = false; + parent.runOnUiThread(new Runnable() + { + public void run() + { + parent.startActivityForResult(snapshotIntent, 0); + } + }); + semaphore.acquireUninterruptibly(); + Log.d("SDL", "CloudSave: load: user selected: " + (crapshotMetadata == null ? "null" : crapshotMetadata.getUniqueName()) + " new " + createNewSave); + if( crapshotMetadata == null ) + return false; + saveId = crapshotMetadata.getUniqueName(); } Snapshots.OpenSnapshotResult result = Games.Snapshots.open(getApiClient(), saveId, false).await(); @@ -175,12 +234,9 @@ public class CloudSave implements GameHelper.GameHelperListener { signInSucceeded = false; signInFailed = false; Log.i("SDL", "CloudSave: beginUserInitiatedSignIn()"); + semaphore.drainPermits(); beginUserInitiatedSignIn(); - Log.i("SDL", "CloudSave: beginUserInitiatedSignIn() exit"); - while (!signInSucceeded && !signInFailed) - { - try { Thread.sleep(300); } catch( Exception e ) {} - } + semaphore.acquireUninterruptibly(); return signInSucceeded; } return true; @@ -190,11 +246,13 @@ public class CloudSave implements GameHelper.GameHelperListener { public void onSignInSucceeded() { Log.i("SDL", "CloudSave: onSignInSucceeded()"); signInSucceeded = true; + semaphore.release(); } public void onSignInFailed() { Log.i("SDL", "CloudSave: onSignInFailed()"); signInFailed = true; + semaphore.release(); } public Snapshot processSnapshotOpenResult(Snapshots.OpenSnapshotResult result, int retryCount) diff --git a/project/jni/application/biniax2/AndroidAppSettings.cfg b/project/jni/application/biniax2/AndroidAppSettings.cfg index 34f5e982c..9b5e36f4e 100644 --- a/project/jni/application/biniax2/AndroidAppSettings.cfg +++ b/project/jni/application/biniax2/AndroidAppSettings.cfg @@ -7,10 +7,10 @@ AppName="Biniax2" AppFullName=com.biniax.sdl # Application version code (integer) -AppVersionCode=1405 +AppVersionCode=1406 # Application user-visible version name (string) -AppVersionName="1.4.05" +AppVersionName="1.4.06" # Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...' # If you'll start Description with '!' symbol it will be enabled by default, other downloads should be selected by user from startup config menu diff --git a/project/jni/application/biniax2/src/biniax.c b/project/jni/application/biniax2/src/biniax.c index 8f4b70298..5757ab11b 100644 --- a/project/jni/application/biniax2/src/biniax.c +++ b/project/jni/application/biniax2/src/biniax.c @@ -218,7 +218,7 @@ int main( int argc, char *argv[] ) } break; case cDoSave : - saveGame( &Game ); + //saveGame( &Game ); enterState = cStateMainMenu; break; case cDoRestart : @@ -1252,7 +1252,7 @@ BNX_BOOL saveGame( BNX_GAME *game ) fclose( file ); SDL_SaveBMP(SDL_GetVideoSurface(), "screenshot.bmp"); - SDL_ANDROID_CloudSave( sysGetFullFileName( csSaveGameName ), "save", "Biniax2", "savegame", "screenshot.bmp", game->moves ); + SDL_ANDROID_CloudSave( sysGetFullFileName( csSaveGameName ), "", "Biniax2", "savegame", "screenshot.bmp", game->moves ); return BNX_TRUE; } @@ -1263,7 +1263,7 @@ BNX_BOOL loadGame( BNX_GAME *game ) BNX_INT32 i; BNX_INT32 j; - SDL_ANDROID_CloudLoad( sysGetFullFileName( csSaveGameName ), "save", "Biniax2" ); + SDL_ANDROID_CloudLoad( sysGetFullFileName( csSaveGameName ), "", "Biniax2" ); if ( sysGetFileLen( sysGetFullFileName( csSaveGameName ) ) != cSaveFileSize ) return BNX_FALSE; diff --git a/project/jni/sdl-1.2/src/video/android/SDL_androidvideo.c b/project/jni/sdl-1.2/src/video/android/SDL_androidvideo.c index 1dcd934e3..0affa17a0 100644 --- a/project/jni/sdl-1.2/src/video/android/SDL_androidvideo.c +++ b/project/jni/sdl-1.2/src/video/android/SDL_androidvideo.c @@ -493,7 +493,7 @@ int SDLCALL SDL_ANDROID_CloudSave(const char *filename, const char *saveId, cons jstring s3 = (*JavaEnv)->NewStringUTF(JavaEnv, dialogTitle); jstring s4 = (*JavaEnv)->NewStringUTF(JavaEnv, description); jstring s5 = (*JavaEnv)->NewStringUTF(JavaEnv, screenshotFile); - int result = (*JavaEnv)->CallBooleanMethod( JavaEnv, JavaRenderer, JavaRequestCloudSave, s1, s2, s3, s4, s5, playedTimeMs ); + int result = (*JavaEnv)->CallBooleanMethod( JavaEnv, JavaRenderer, JavaRequestCloudSave, s1, s2, s3, s4, s5, &playedTimeMs ); (*JavaEnv)->DeleteLocalRef(JavaEnv, s5); (*JavaEnv)->DeleteLocalRef(JavaEnv, s4); (*JavaEnv)->DeleteLocalRef(JavaEnv, s3); diff --git a/project/proguard.cfg b/project/proguard.cfg index 943385335..ce2ed6afe 100644 --- a/project/proguard.cfg +++ b/project/proguard.cfg @@ -15,22 +15,27 @@ -keep public class com.android.vending.licensing.ILicensingService -keepclasseswithmembernames class * { - native ; + native ; } -keepclasseswithmembernames class * { - public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet); } -keepclasseswithmembernames class * { - public (android.content.Context, android.util.AttributeSet, int); + public (android.content.Context, android.util.AttributeSet, int); } -keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); + public static **[] values(); + public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; + public static final android.os.Parcelable$Creator *; +} + +-keep class com.google.android.gms.games.snapshot.SnapshotMetadataEntity +{ + *; }