‹ SdkboxAds Doc Home

SdkboxPlay Integration Guide

For the C++ version of cocos2d-x v3.x - (all other versions)

FAQ

  1. 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

Google Play check list

  1. Application id (string.xml)
  2. App Release mode
  3. cloud_save is optional, enalbe and fill true if you will use Saved Game else fill false
  4. Publish to Alpha/Bete test
  5. Add your test account to tester list
  6. SHA-1 keys
  7. web_client_id is optional, fill it when you need google signin authcode else remove it
  8. More Troubleshoot

Game Center

Cloud Save

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

  1. 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" />
  1. 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:

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:

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:

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.

#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 );
};
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, the increment 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 or onRevelError 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 or onSetStepsError 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



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 use

sdkbox.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 and collection_type are the supplied values to getMyScore 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 and collection_type are the supplied values to getMyScore method call. error_code and error_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 and collection_type are the values supplied to getPlayerCenteredScores method. error_code and error_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. The json_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.

Copy Files

Copy the following jar files from plugin/android/libs folder of this bundle into your project's /libs folder.

PluginSdkboxPlay.jar

sdkbox.jar

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

  1. Find the AppActivity.java
find . -name "AppActivity.java"
  1. Replace extends Cocos2dxActivity with extends 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

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
import android.content.Intent;
import com.sdkbox.plugin.SDKBox;
onLoadNativeLibraries();
SDKBox.init(this);
    @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 /libs folder.

Modify files for Eclipse

  1. 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)

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

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

  1. implement onGenerateIdentityVerificationSignature function in SdkboxPlayListener
  2. invoke sdkbox::PluginSdkboxPlay::generateIdentityVerificationSignature();

Android

    "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

  1. _ZN6sdkbox20GPGAchievementsProxy6unlockERKNSt6__ndk112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE

Please be cure the user is signed in, call sdkbox::PluginSdkboxPlay::isSignedIn().