SdkboxPlay Integration Guide
For the C++ version of cocos2d-x v3.x - (all other versions)
FAQ
-
submitScore
: java.lang.IllegalStateException: Score tags must be no more than 64 URI safe characters. Input was *.The characters generally considered unsafe are:
- space (" ")
- less than and greater than ("<>")
- open and close brackets ("[]")
- open and close braces ("{}")
- pipe ("|")
- backslash ("\")
- caret ("^")
- percent ("%")
Prerequisites
Google play
-
Follow this instructions to enable game services for your game and create a linked application. Otherwise, the app won't be able to make connections to google play. It's recommended to follow the instruction rigorously to avoid any issues.
-
Use developer console to configure leaderboards and achievements.
-
Find your app id and you'll need to replace replace it in the
AndroidManifest.xml
later
Google Play check list
- Application id (string.xml)
- App Release mode
cloud_save
is optional, enalbe and filltrue
if you will use Saved Game else fillfalse
- Publish to Alpha/Bete test
- Add your test account to tester list
- SHA-1 keys
web_client_id
is optional, fill it when you need google signin authcode else remove it- More Troubleshoot
Game Center
- Enable Game Center on XCode.
- Use itunes connect to configure leaderboards and achievements.
- Make sure Leaderboard and Achievements are live before testing
Cloud Save
- Enable iCloud on Xcode.
- Enable
Saved Games
on Google Play Console
NOTE: In 2.3.14 cloud save is enable as default, it cause user can't sign-in on android if you do not enable Save Games
on Google Play Console.
Integration
Open a terminal and use the following command to install the SDKBOX SdkboxPlay plugin. Make sure you setup the SDKBOX installer correctly.
$ sdkbox import sdkboxplay
JSON Configuration
Replace App ID
You should replace your app_id in AndroidManifest.xml
- replace following line
<meta-data android:name="com.google.android.gms.games.APP_ID" android:value="_your_app_id_" />
with
<meta-data android:name="com.google.android.gms.games.APP_ID" android:value="@string/app_id" />
- add following line to
<Your Project>\proj.android\res\values\strings.xml
<string name="app_id">_your_app_id_</string>
Update sdkbox_config.json
SDKBOX Installer will automatically create a sample configuration sdkbox_config.json
for you
Here is an example of the SdkboxAds configuration:
"sdkboxplay" : {
"leaderboards" : [
{
"id" : "CgkI0sux8sMWEAIQAA",
"name" : "ldb1"
}
],
"achievements" : [
{
"id" : "CgkI0sux8sMWEAIQAg",
"name" : "ten-games",
"incremental" : false
},
{
"id" : "CgkI0sux8sMWEAIQAw",
"name" : "hunter",
"incremental" : false
},
...
],
"debug" : true,
"show_achievement_notification": true,
"connect_on_start" : false
}
As it can be seen, leaderboards and achievements have a human readable name, and a machine generated id. This is on purpose so that the same API can be used between platforms. While Google play generated random ids like the ones shown, iOS Game Center will be more human friendly. In either case, the developer will reference leaderboards and achievements by a name of his choice, like in the example shown.
if you don't want popup show when unlock achievement, you can set 'show_achievement_notification' false.
Usage
Initialize SdkboxPlay
Initialize the plugin where appropriate in your code. We recommend to do this in the AppDelegate::applicationDidFinishLaunching()
or AppController:didFinishLaunchingWithOptions()
. Make sure to include the appropriate headers:
#include "PluginSdkboxPlay/PluginSdkboxPlay.h"
AppDelegate::applicationDidFinishLaunching()
{
sdkbox::PluginSdkboxPlay::init();
}
Using SdkboxPlay
Intro
SdkboxPlay is an abstraction for Google Play and Game Center's social services. Under a common API exposes access to Leaderboards and Achievements for each platform. In order to keep the API fit to the two models, some tradeoffs have been made, which will be detailed in each section
Logged in user info
Calling the method sdkbox::SdkboxPlay::getPlayerId()
to get an id per platform that uniquely identifies the logged-in user.
Additionally, you can query more information about the user.
iOS/Android fields
These fields are common to ios and android: * player_id * name * display_name
making a call to sdkbox::SdkboxPlay::getPlayerAccountField( const std::string& field )
will return a string with the field
contents.
If the requested field does not exist, empty string will returned in exchange.
player_id
will be returned by calling sdkbox::SdkboxPlay::getPlayerId()
too.
Android only fields
For Android platform, there are some other available fields:
- title
- icon_image_uri
- hires_image_uri
- last_play_timestamp
- retrieved_timestamp
- server_auth_code
use the same getPlayerAccountField
to get these values as strings.
Achievements
Achievements are defined on the respective platform's developer console. There are differences in concept between GooglePlay and GameCenter's achievements: + Google Play differentiates between achievements, and incremental achievements. Google keeps track of incremental achievements progress. Achievements are achieved only once. + For Game Center, all achievements are incremental, but Game center does not keep track of its progress. Achievements are expected to be achieved during a game session. Achievements can be set to be unlocked several times. + Google Play has the notion of newly unlocked achievement (first time unlocked), and Game Center has the notion of recurrently unlockable achievement. Both concepts are complementary.
To keep things consisten, SdkboxPlay API:
- Allows you to define non-incremental achievements. For ios, are submitted with an incremental value of 100, which means it will be unlocked.
- Allows you to define Incremental achievements. In Google play, incremental achievements have defined their unlocking value on the application console.
- For consistency, it is recommended to define Google Play's achievements with a count of 100. This is the value Game Center expects to be reached to unlock an achievement.
Leaderboards
Leaderboards are defined on the respective platform's developer console. To keep things simple, the current SdkboxPlay implementation does not allow to define group leaderboards from iOS. For both platforms, an arbitrary number of leaderboards can be defined. Though both, GooglePlay and GameCenter define leaderboards in the same way, in the runtime there are some differences:
- Google Play creates automatically 3 time frames for each leaderboard: daily, weekly and all time best scores.
- Game Center creates just one timeframe.
This will be resembled on the observer methods for leaderboard operations as described below.
Usage
A call to sdkbox::SdkboxPlay::init()
will configure the plugin with the selected leaderboards and achievements present in the sdkbox_config.json file.
First, a connection to the games services must be done by calling:
sdkbox::PluginSdkboxPlay::signin();
If connection is successful, you'll be able to use the SdkboxPlay services with the following API:
Leaderboards
void submitScore( const std::string& leaderboard_name, long score )
This method submits a update request to the given leaderboard. The leaderboard name must match any of the leaderboard names defined in the configuration block. If a request is sent to a non existent leaderboard, nothing will happen. Whether to store the new score or not, can be defined in the developer's console (store always latest score, only maximum, etc.) This method will invoke plugin's observer method:
void onScoreSubmitted(
const std::string& leaderboard_name,
long score,
bool maxScoreAllTime,
bool maxScoreWeek,
bool maxScoreToday )
For iOS, this method will have the three boolean flags as false.
void showLeaderboard( const std::string& leaderboard_name );
Request to show the leaderboard information. This will invoke a platform specific UI. For iOS, there's no different UI for requesting leaderboards and achievements, so this method will invoke the UI with the leaderboards view enabled.
Achievements
void unlockAchievement( const std::string& achievement_name );
Unlock a non incremental achievement. In the case of iOS, it will send a request to Game Center of unlock with 100 progress points. If the achievement type is incorrectly defined in the configuration file (wrong id), or the play services determines it is of the wrong type (Google play) the method will fail silently. Upon successful call, this method will invoke the listener's method: onAchievementUnlocked( const std::string& achievement_name, bool newlyUnlocked ).
void incrementAchievement(
const std::string& achievement_name,
int increment );
Increment an incremental achievement.
The method will silently fail if the achievement type is incorrectly defined in the configuration file (wrong or non existent id), or the play services determines it is of the wrong type (Google Play).
If the call is successful, this method may invoke two different methods:
+ onIncrementalAchievementStep( const std::string& achievement_name, double step )
if the achievement is not unlocked.
+ onIncrementalAchievementUnlocked( const std::string& achievement_name, bool newlyUnlocked )
the first time it's been unlocked.
void showAchievements( );
Request to show the default Achievements view. This view only shows public achievements. t will show specific per platform information, like whether it's been unlocked, remaining unlocking steps (Google Play only), total experience count, etc.
CloudSave
void loadAllGameData();
Load all game data saved in cloud.
void saveGameDataBinary(const std::string& name, const void* data, int length);
Save binary data. if you want to save string, translate to char* .
SdkboxPlay events
This allows you to catch SdkboxPlay
' events.
- Allow your class to extend
sdkbox::SdkboxPlayListener
and override the functions listed:
#include "PluginSdkboxPlay/PluginSdkboxPlay.h"
class MyClass : public sdkbox::SdkboxPlayListener
{
protected:
/**
* Call method invoked when the Plugin connection changes its status.
* Values are as follows:
* + GPS_CONNECTED: successfully connected.
* + GPS_DISCONNECTED: successfully disconnected.
* + GPS_CONNECTION_ERROR:error with google play services connection.
*/
void onConnectionStatusChanged( int status );
/**
* Callback method invoked when an score has been successfully submitted to a leaderboard.
* It notifies back with the leaderboard_name (not id, see the sdkbox_config.json file) and the
* subbmited score, as well as whether the score is the daily, weekly, or all time best score.
* Since Game center can't determine if submitted score is maximum, it will send the max score flags as false.
*/
void onScoreSubmitted( const std::string& leaderboard_name, long score, bool maxScoreAllTime, bool maxScoreWeek, bool maxScoreToday );
/**
* Callback method invoked when the request call to increment an achievement is succeessful and
* that achievement gets unlocked. This happens when the incremental step count reaches its maximum value.
* Maximum step count for an incremental achievement is defined in the google play developer console.
*/
void onIncrementalAchievementUnlocked( const std::string& achievement_name );
/**
* Callback method invoked when the request call to increment an achievement is successful.
* If possible (Google play only) it notifies back with the current achievement step count.
*/
void onIncrementalAchievementStep( const std::string& achievement_name, double step );
/**
* Call method invoked when the request call to unlock a non-incremental achievement is successful.
* If this is the first time the achievement is unlocked, newUnlocked will be true.
*/
void onAchievementUnlocked( const std::string& achievement_name, bool newlyUnlocked );
};
- Create a listener that handles callbacks:
sdkbox::PluginSdkboxPlay::setListener( new MyClass() );
API Reference
Methods
static bool init ( ) ;
Initialize the plugin instance. The plugin initializes from the sdkbox_config.json file, and reads a configuration of the form: { "leaderboards" : LeaderboardObject[], "achievements" : AchievementObject[], "connect_on_start" : boolean, "debug" : boolean, "enabled" : boolean }
debug: is a common value to all plugins which enables debug info to be sent to the console. Useful when developing. enabled: is a common value to all plugins, which enables or disables the plugin. If enabled is false, the plugin methods will do nothing. connect_on_start: tells the plugin to make an automatic connection to Google Play Services on application startup. leaderboards: a collection of objects of the form: { "id" : // google play's assigned leaderboard id "name" : // human readable leaderboard name. You'll request leaderboard actions with this name. } achievements: a collection of objects of the form: { "id" : // google play's assigned achievement id. "name" : // human readable achievement name. You'll request achievement actions with this name. "incremental" : // boolean }
static void setListener ( SdkboxPlayListener * listener ) ;
Set SdkboxPlay plugin listener.
static SdkboxPlayListener * getListener ( ) ;
Get the plugin's listener.
static void removeListener ( ) ;
Remove the listener. This plugin allows only for one listener which will be disabled after calling this method.
static std::string getVersion ( ) ;
Use this to get the version of the SDK. @return The version of the SDK.
static void submitScore ( const std::string & leaderboard_name , long score ) ;
Request submission of an score value to a leaderboard name defined in sdkbox_config.json file. If the leaderboard name does not exists, or the id associated is not defined in the Developer Console for the application, the call will silently fail. If everything's right, it will notify the method
onScoreSubmitted
.
static void showAllLeaderboards ( ) ;
Request to show all leaderboards.
static void showLeaderboard ( const std::string & leaderboard_name = "" ) ;
Request to show the default Leaderboard view. In this view you'll be able to interactively select between daily, weekly or all-time leaderboard time frames and the scope to global or you google play's friends results.
Android only: if empty string or __ALL__ is used as leaderboard_name, sdkbox play will invoke an activity with all game-defined leader boards.
static void getMyScore ( const std::string & leaderboard_name ,
int time_span ,
int collection_type ) ;
Get The signed-in user score for an specified leaderboard. This method notifies its result in a call to SdkboxPlay's listener
onMyScore
method.time_span
offers the abbility to filter leaderboard for one of the three time spans each leaderboard offers. Values are: + 0 : daily time span + 1 : weekly time span + any other value : all time time span.collection_type
is to filter the leaderboard between social or global scopes. Values are: + 1 : social collection type + any other value : global collection type
static void getPlayerCenteredScores ( const std::string & leaderboard_name ,
int time_span ,
int collection_type ,
int number_of_entries ) ;
Get leaderboard information. This method notifies its result in a call to SdkboxPlay's listener
onPlayerCenteredScores
method. The information supplied is a json array encoded string. Each json element contains the following information:
{
"display_rank" : string,
"display_score" : string,
"rank" : number, // long
"score" : number, // long,
"holder_display_name" : string,
"hires_imageuri" : string, // content:// protocol
"lowres_imageuri" : string,
"tag" : string,
"timestamp_millis" : long
}
time_span
offers the abbility to filter leaderboard for one of the three time spans each
leaderboard offers. Values are:
+ 0 : daily time span
+ 1 : weekly time span
+ any other value : all time time span.
collection_type
is to filter the leaderboard between social or global scopes.
Values are:
+ 1 : social collection type
+ any other value : global collection type
static void loadAchievements ( bool force_reload ) ;
Load achievements metadata. A forece reload will force a cloud-side requery of the achievements information. See
onAchievementsLoaded
for a description on the returned information.
static void unlockAchievement ( const std::string & achievement_name ) ;
Request to unlock an achievement defined by its name. This method assumes the achievement is non incremental. If the achievement type is incorrectly defined in the configuration file, or the play services determines it is of the wrong type, this method will fail silently. Otherwise, if everything is right, the method
onAchievementUnlocked
will be invoked on the plugin listener.
static void incrementAchievement ( const std::string & achievement_name ,
double increment ) ;
Request to increment the step count of an incremental achievement by the specified number of steps. This method assumes the achievement is incremental. If the achievement type is incorrectly defined in the configuration file, or the play services determines it is of the wrong type, this method will fail silently. If the call is successful, this method may invoke two different methods: +
onIncrementalAchievementStep
if the achievement is not unlocked. +onIncrementalAchievementUnlocked
the first time it's been newly unlocked. On Android, the achievement is set to a fixed number of incremental steps. On iOS, the achievment is set as a percentage value (0..100). In either case, theincrement
value will be added to the current achievement's value.
static void showAchievements ( ) ;
Request to show the default Achievements view. In this view, you'll only see public achievements. It will show wether or not achievements are unlocked, and the steps towards unlocking it for incremental achievements. Total experience count is measured as well.
static void reveal ( const std::string & achievement_name ) ;
Reveal a hidden achievement. This method will notify on plugin's listener
onReveal
oronRevelError
methods.
static void setSteps ( const std::string & achievement_name , double steps ) ;
Set an incremental achievement to the given amount of steps. If achievement's current steps are already equal or bigger the specified steps, nothing will happen. This method will notify on plugin's listener
onSetSteps
oronSetStepsError
methods.
static bool isConnected ( ) ;
Fast method to know plugin's connection status. @deprecated
static bool isSignedIn ( ) ;
Same as isConnected (deprecated) but more consistent with naming.
static void signin ( bool showLoginUI = true ) ;
Request connection to the platform-specific services backend. This method will invoke plugin's listener
onConnectionStatusChanged
method.
static void signout ( ) ;
Request disconnection from the GooglePlay/Game Center backend. This method will invoke plugin's listener
onConnectionStatusChanged
method.
static std::string getPlayerId ( ) ;
Get the currently logged in player's id.
static std::string getPlayerAccountField ( const std::string & field ) ;
Get a field from the user account's info obtained after authentication. Current values are: iOS/Android
- display_name
- name
- player_id Android only:
- title
- icon_image_uri
- hires_image_uri
- last_play_timestamp
- retrieved_timestamp
- server_auth_code If a field not valid is queried an empty string will be returned.
static void resetAchievements ( ) ;
Calling this class method deletes all progress towards achievements previously reported for the local player. Hidden achievements that were previously visible are now hidden again.
iOS Only
static void loadAllData ( ) ;
DEPRECATED >>>>>> Please use loadAllGameData to replace load all saved user game data in clound will trigger onGameData callback
static void loadGameData ( const std::string & save_name ) ;
DEPRECATED >>>>>> Please use loadAllGameData to replace load one saved user game data in clound will trigger onGameData callback
static void saveGameData ( const std::string & save_name ,
const std::string & data ) ;
DEPRECATED >>>>>> Please use saveGameDataBinary(name, data, length) to replace save user game data in cloud will trigger onGameData callback
static void fetchGameDataNames ( ) ;
fetch game data names will trigger onGameDataNames
static void loadOneGameData ( const std::string & name ) ;
load game data item will trigger onLoadGameData
static void loadAllGameData ( ) ;
load all saved game data will trigger onLoadGameData callback
static void saveGameDataBinary ( const std::string & name ,
const void * data ,
int length ) ;
save user game data will trigger onSaveGameData callback
Note: if you want to save string, please translate to void> In JavaScript, please usesdkbox.PluginSdkboxPlay.saveGameDataBinary('name', 'stringdata');
static void generateIdentityVerificationSignature ( ) ;
Generates a signature that allows a third party server to authenticate the local player. just vaild on iOS
https://developer.apple.com/documentation/gamekit/gklocalplayer/1515407-generateidentityverificationsign Note: on Android, you can get server_auth_code from getPlayerAccountField
Listeners
void onConnectionStatusChanged ( int status );
Call method invoked when the Plugin connection changes its status. Values are as follows: + GPS_CONNECTED: successfully connected. + GPS_DISCONNECTED: successfully disconnected. + GPS_CONNECTION_ERROR:error with google play services connection.
void onScoreSubmitted ( const std::string & leaderboard_name ,
long score ,
bool maxScoreAllTime ,
bool maxScoreWeek ,
bool maxScoreToday );
Callback method invoked when an score has been successfully submitted to a leaderboard. It notifies back with the leaderboard_name (not id, see the sdkbox_config.json file) and the subbmited score, as well as whether the score is the daily, weekly, or all time best score. Since Game center can't determine if submitted score is maximum, it will send the max score flags as false.
void onMyScore ( const std::string & leaderboard_name ,
int time_span ,
int collection_type ,
long score )
Callback method invoked from a call to
getMyScore
method.time_span
andcollection_type
are the supplied values togetMyScore
method call.
void onMyScoreError ( const std::string & leaderboard_name ,
int time_span ,
int collection_type ,
int error_code ,
const std::string & error_description )
Callback method invoked from a call to
getMyScore
method and the method was errored.time_span
andcollection_type
are the supplied values togetMyScore
method call.error_code
anderror_description
give extended info about the error.
void onPlayerCenteredScores ( const std::string & leaderboard_name ,
int time_span ,
int collection_type ,
const std::string & json_with_score_entries )
Callback method invoked from a call to
getPlayerCenteredScores
method.json_with_score_entries
is an json array enconded string, each of which elements is of the form: Each json element contains the following information:
{
"display_rank" : string,
"display_score" : string,
"rank" : number, // long
"score" : number, // long,
"holder_display_name" : string,
"hires_imageuri" : string, // content:// protocol
"lowres_imageuri" : string,
"tag" : string,
"timestamp_millis" : long
}
time_span
and collection_type
are the values supplied to getPlayerCenteredScores
method.
void onPlayerCenteredScoresError ( const std::string & leaderboard_name ,
int time_span ,
int collection_type ,
int error_code ,
const std::string & error_description )
Callback method invoked from a call to
getPlayerCenteredScores
method was errored.time_span
andcollection_type
are the values supplied togetPlayerCenteredScores
method.error_code
anderror_description
give extended info about the error.
void onIncrementalAchievementUnlocked ( const std::string & achievement_name );
Callback method invoked when the request call to increment an achievement is succeessful and that achievement gets unlocked. This happens when the incremental step count reaches its maximum value. Maximum step count for an incremental achievement is defined in the google play developer console.
void onIncrementalAchievementStep ( const std::string & achievement_name ,
double step );
Callback method invoked when the request call to increment an achievement is successful. If possible (Google play only) it notifies back with the current achievement step count.
void onIncrementalAchievementStepError ( const std::string & name ,
double steps ,
int error_code ,
const std::string & error_description )
void onAchievementUnlocked ( const std::string & achievement_name ,
bool newlyUnlocked );
Call method invoked when the request call to unlock a non-incremental achievement is successful. If this is the first time the achievement is unlocked, newUnlocked will be true.
void onAchievementUnlockError ( const std::string & achievement_name ,
int error_code ,
const std::string & error_description )
void onAchievementsLoaded ( bool reload_forced ,
const std::string & json_achievements_info )
Method invoked after calling plugin's
loadAchievements
method. Thejson_achievements_info
parameter is a json array encoded string.
Android fields:
each array element is of the form:
{
"id" : string,
"name" : string,
"xp_value" : string, // experience value
"last_updated_timestamp" : number,
"description" : string,
"type" : number, // 0 = standard, 1 = incremental
"state" : number, // 0 = unlocked, 1 = revealed, 2 = hidden
"unlocked_image_uri" : string, // content:// protocol
"revealed_image_uri" : string, // content:// protocol
}
If the achievement is incremental, these fileds will also be available:
{
"formatted_current_steps" : string,
"formatted_total_steps" : string,
current_steps" : number,
"total_steps" : number
}
IOS fields:
{
"id" : string,
"name" : string,
"xp_value" : number, int
"last_updated_timestamp" : number,
"description" : string, // maybe empty if no achievemnt submission happened before.
"state" : number, // 0 = unlocked, 1 = revealed, 2 = hidden
"type" : 1, // on ios all achievemtns are incremental.
"current_steps" : number, // double value. percentage 0.0 .. 100.0
"total_steps" : number, // 100.0
}
```
iOS only fields:
```json
{
"replayable" : boolean,
}
void onSetSteps ( const std::string & name , double steps )
void onSetStepsError ( const std::string & name ,
double steps ,
int error_code ,
const std::string & error_description )
void onReveal ( const std::string & name )
void onRevealError ( const std::string & name ,
int error_code ,
const std::string & error_description )
void onGameData ( const std::string & action ,
const std::string & name ,
const std::string & data ,
const std::string & error )
DEPRECATED >>>>>>
void onSaveGameData ( bool success , const std::string & error )
void onLoadGameData ( const SavedGameData * savedData ,
const std::string & error )
void onGameDataNames ( const std::vector <std::string> & names ,
const std::string & error )
void onGenerateIdentityVerificationSignature ( const std::string & publicKeyUrl ,
const std::string & signatureBase64 ,
const std::string & saltBase64 ,
unsigned long long timestamp ,
const std::string & error )
trigger after call generateIdentityVerificationSignature
Manual Integration
If the SDKBOX Installer fails to complete successfully, it is possible to integrate SDKBOX manually. If the installer complete successfully, please do not complete anymore of this document. It is not necessary.
These steps are listed last in this document on purpose as they are seldom needed. If you find yourself using these steps, please, after completing, double back and re-read the steps above for other integration items.
Manual Integration For iOS
Drag and drop the following frameworks from the plugins/ios folder of
the SdkboxPlay
bundle into your Xcode project, check Copy items if needed
when adding frameworks:
sdkbox.framework
PluginSdkboxPlay.framework
The above frameworks depend upon a large number of other frameworks. You also need to add the following system frameworks, if you don't already have them:
GameKit.framework
UIKit.framework
Manual Integration For Android
SDKBOX supports three different kinds of Android projects command-line, eclipse and Android Studio.
proj.android
will be used as our<project_root>
for command-line and eclipse projectproj.android-studio
will be used as our<project_root>
for Android Studio project.
Copy Files
Copy the following jar files from plugin/android/libs
folder of this
bundle into your project's
PluginSdkboxPlay.jar
sdkbox.jar
-
If you're using cocos2d-x from source copy the jar files to:
Android command-line:
cocos2d/cocos/platform/android/java/libs
Android Studio:
cocos2d/cocos/platform/android/java/libs cocos2d/cocos/platform/android/libcocos2dx/libs
-
If you're using cocos2d-js or lua copy the jar files to:
Android command-line:
frameworks/cocos2d-x/cocos/platform/android/java/libs
Android Studio:
frameworks/cocos2d-x/cocos/platform/android/java/libs frameworks/cocos2d-x/cocos/platform/android/libcocos2dx/libs
-
If you're using prebuilt cocos2d-x copy the jar files to:
Android command-line:
proj.android/libs
Copy the sdkboxplay_lib
directories from plugin/android/libs
to your <project_root>/libs/
directory.
Copy jni libs
Copy and overwrite all the folders from plugin/android/jni
to your <project_root>/jni/
directory.
Edit AndroidManifest.xml
Include the following permissions above the application tag:
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
To enable hardware acceleration in your application tag. This tag is optional on newer sdk versions and doesn't work on version 2.3.3.
<android:hardwareAccelerated="true" />
Edit Android.mk
Edit proj.android/jni/Android.mk
to:
Add additional requirements to LOCAL_WHOLE_STATIC_LIBRARIES:
LOCAL_WHOLE_STATIC_LIBRARIES += android_native_app_glue
LOCAL_LDLIBS += -landroid
LOCAL_LDLIBS += -llog
LOCAL_WHOLE_STATIC_LIBRARIES += PluginSdkboxPlay
LOCAL_WHOLE_STATIC_LIBRARIES += sdkbox
Add a call to:
$(call import-add-path,$(LOCAL_PATH))
before any import-module statements.
Add additional import-module statements at the end:
$(call import-module, ./sdkbox)
$(call import-module, ./pluginsdkboxplay)
This means that your ordering should look similar to this:
$(call import-add-path,$(LOCAL_PATH))
$(call import-module, ./sdkbox)
$(call import-module, ./pluginsdkboxplay)
Edit Application.mk
Edit proj.android/jni/Application.mk
to:
Add APP_PLATFORM version requirements:
APP_PLATFORM := android-10
Modify AppActivity.java
Plugin >= 2.4.0.3
- Find the AppActivity.java
find . -name "AppActivity.java"
- Replace
extends Cocos2dxActivity
withextends com.sdkbox.plugin.SDKBoxActivity
Example of the directory where the AppActivity.java file is located:
cpp
- proj.android/src/org/cocos2dx/cpp/AppActivity.java
- proj.android-studio/app/src/org/cocos2dx/cpp/AppActivity.java
- proj.android/app/src/org/cocos2dx/cpp/AppActivity.java ( from cocos2d-x 3.17)
lua
- frameworks/runtime-src/proj.android/src/org/cocos2dx/lua/AppActivity.java
- frameworks/runtime-src/proj.android-studio/app/src/org/cocos2dx/lua/AppActivity.java
- frameworks/runtime-src/proj.android/app/src/org/cocos2dx/lua/AppActivity.java (from cocos2d-x 3.17)
js
- frameworks/runtime-src/proj.android/src/org/cocos2dx/javascript/AppActivity.java
- frameworks/runtime-src/proj.android/app/src/org/cocos2dx/javascript/AppActivity.java ( from cocos2d-x 3.17)
Plugin < 2.4.0.3
-
If you're using cocos2d-x from source, assuming you are in the proj.android directory, Cocos2dxActivity.java is located:
../../cocos2d-x/cocos/platform/android/java/src/org/cocos2dx/ lib/Cocos2dxActivity.java
-
If you're using the prebuilt cocos2d-x libraries assuming you are in the
proj.android
directory, Cocos2dxActivity.java is located:./src/org/cocos2dx/lib/Cocos2dxActivity.java
Note: When using Cocos2d-x from source, different versions have Cocos2dxActivity.java in a different location. One way to find the location is to look in proj.android/project.properties. Example:
android.library.reference.1=../../cocos2d-x/cocos/platform/android/java
In this case, Cocos2dxActivity.java should be located at:
../../cocos2d-x/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java
- Modify Cocos2dxActivity.java to add the following imports:
import android.content.Intent;
import com.sdkbox.plugin.SDKBox;
- Second, modify Cocos2dxActivity.java to edit the
onCreate(final Bundle savedInstanceState)
function to add a call toSDKBox.init(this);
. The placement of this call is important. It must be done after the call toonLoadNativeLibraries();
. Example:
onLoadNativeLibraries();
SDKBox.init(this);
-
Last, we need to insert the proper overrides code. There are a few rules here.
-
If the method listed has not been defined, add it.
-
If the method listed has been defined, add the calls to
SDKBox
in the same existing function.
-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(!SDKBox.onActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
protected void onStart() {
super.onStart();
SDKBox.onStart();
}
@Override
protected void onStop() {
super.onStop();
SDKBox.onStop();
}
@Override
protected void onResume() {
super.onResume();
SDKBox.onResume();
}
@Override
protected void onPause() {
super.onPause();
SDKBox.onPause();
}
@Override
public void onBackPressed() {
if(!SDKBox.onBackPressed()) {
super.onBackPressed();
}
}
Manual Integration for Google Play Services SDK (dependent library only)
Suggestion
Please try the SDKBOX installer first. It will do all the following step for you automatically.
$ sdkbox import googleplayservices
Modify project.properties
An Android Library Reference for Google Play Services is required. The path will be different depending upon your setup. Also, this is an additional download that does not come as part of a standard install. To install use the sdk installer and choose extras->google play services. Here is an example of what this line could look like:
android.library.reference.1=
../android/sdk.latest/extras/google/google_play_services/libproject/
google-play-services_lib
Note: if you already have an android.library.reference.1
you can add
another by incrementing the number as android.library.reference.2
, etc.
Integration manually
We make a lite version of Google Play Services, the project repo is https://github.com/darkdukey/Google-Play-Service-Lite
Copy Files
Copy the gps
folder from plugin
folder of this bundle into your project's
-
If you're using cocos2d-x from source copy the
gps
folder to:Android command-line:
cocos2d/cocos/platform/android/java/libs
Android Studio:
cocos2d/cocos/platform/android/libcocos2dx/libs
-
If you're using cocos2d-js or lua copy the
gps
folder to:Android command-line:
frameworks/cocos2d-x/cocos/platform/android/java/libs
Android Studio:
frameworks/cocos2d-x/cocos/platform/android/libcocos2dx/libs
-
If you're using prebuilt cocos2d-x copy the
gps
folder to:Android command-line:
<project_root>/libs
Modify files for Eclipse
- Modify project.properties
# For source project
android.library.reference.2=../cocos2d/cocos/platform/android/java/libs/gps/
# Or
# For framework project
android.library.reference.1=libs/gps/
Modify files for Android Studio
1. Modify cocos2d/cocos/platform/android/libcocos2dx/build.gradle
dependencies {
+ compile project(':gps')
compile fileTree(dir: '../java/libs', include: ['*.jar'])
}
2. Modify proj.android-studio/app/project.properties
# Project target.
target=android-14
+android.library.reference.1=../cocos2d/cocos/platform/android/java/libs/gps/
3. Modify proj.android-studio/settings.gradle
project(':libcocos2dx').projectDir = new File(settingsDir, '../cocos2d/cocos/platform/android/libcocos2dx')
include ':your_project_name'
project(':your_project_name').projectDir = new File(settingsDir, 'app')
+
+include ':gps'
+project(':gps').projectDir = new File(settingsDir, '../cocos2d/cocos/platform/android/java/libs/gps')
Proguard (optional)
- Edit
project.properties
to specify aProguard
configuration file. Example:
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
Use any Google Play proguard configuration that fitst your needs. This is default proguard config:
-keep class com.google.protobuf.** { *; }
-dontwarn com.google.protobuf.**
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
@com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
Note: Proguard only works with Release builds (i.e cocos run -m release
) debug builds do not invoke Proguard rules.
Q&A
How To Submit Float Score
static void submitScore( const std::string& leaderboard_name, long score );
The meaning of the score value depends on the formatting of the leaderboard established in the developer console.
Fixed-point formats:
score represents a raw value, and will be formatted based on the number of decimal places configured. A score of 1000 would be formatted as 1000, 100.0, or 10.00 for 0, 1, or 2 decimal places.
eg. if you want to submit score 3.14, you must set score formats is Fixed Point To 2 Decimal
(change score format at apple/google develope website), and invoke like follow:
submitScore("leaderboardName", 3.14 * 100);
Cloud Save
SDKBoxPlay support iOS/Google cloud game save, developer can save user's game data in iColud/Google Drive.
iOS Cloud Save
- The player must have an iCloud account to save games
- developer must enable iCloud in their App
Usage
load all saved game data
sdkbox::PluginSdkboxPlay::loadAllData();
load special saved game data
sdkbox::PluginSdkboxPlay::loadGameData("key2");
save game data
sdkbox::PluginSdkboxPlay::saveGameData("key1", "{\"game_name\": \"sdkbox go\", \"stage\": 3}");
iOS SavedGame Document
Android SavedGame Document
Thrid Server Authenticate
iOS
- implement
onGenerateIdentityVerificationSignature
function inSdkboxPlayListener
- invoke
sdkbox::PluginSdkboxPlay::generateIdentityVerificationSignature();
Android
- add
web_client_id
tosdkbox_config.json
"sdkboxplay" : {
"web_client_id": "......."
}
take a look at this to generate web_client_id
* sign
* sdkbox::PluginSdkboxPlay::getPlayerAccountField("server_auth_code")
to get google server auth code
Crash
Please be cure the user is signed in, call sdkbox::PluginSdkboxPlay::isSignedIn().