Cocos Creator中快速接入U8SDK(Android平台)
之前我们已经介绍过Egret(白鹭引擎)和LayaAir中如何接入U8SDK了。这篇博客我们来介绍下如何在Cocos Creator中接入U8SDK手游联运聚合SDK。这里我们使用的Cocos Creator版本是目前最新版本V 2.4.0,语言我们采用TypeScript。
在开始之前,我们需要先了解一下Cocos Creator中,原生java平台是如何和游戏引擎交互的。 关于这个,官方文档中已经有了详细的说明,我们这里简单用示例总结一下:
1、TypeScript中调用android层java代码的逻辑如下:
1 |
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/U8SDKForCocos", "login", "()V"); |
2、android层java代码调用TypeScript代码的示例如下:
1 |
Cocos2dxJavascriptJavaBridge.evalString("window.u8sdkApi.onU8LoginSuccess('uid1111')"); |
知道TypeScript和Java交互的方式之后,我们就可以着手来写接入代码了。 另外,为了方便调用和后期扩展,我们在两个平台之间的参数,统一采用json格式来传递。
和之前各个游戏引擎平台中接入思路一致, 我们先在TypeScript中封装一个U8SDK组件,负责和原生平台的交互调用;然后,我们再编译生成原生工程,在原生工程中封装一个供TypeScript中调用的原生类组件。
首先,我们在TypeScript里面,增加一个U8SDK.ts组件,里面定义和封装U8SDK和原生平台相互调用的API以及回调处理逻辑等。很简单的组件,我们直接上源码(看源码注释):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
//支付参数 export class U8PayParams{ productId : string; //游戏中商品ID productName : string; //游戏中商品名称,比如元宝,钻石... productDesc : string; //游戏中商品描述 price : number; //价格,单位为元 buyNum : number; //购买数量,一般都为1. coinNum : number; //当前玩家身上剩余的虚拟币数量 serverId : string; //当前角色所在的服务器ID serverName : string; //当前角色所在的服务器名称 roleId : string; //当前角色ID roleName : string; //当前角色名称 roleLevel : number; //当前角色等级 payNotifyUrl : string; //游戏服的支付回调地址,用于接收支付回调通知 vip : string; //当前角色的vip等级 extension : string; //扩展数据, 支付成功回调通知游戏服务器的时候,会原封不动返回这个值 } //数据上报参数 export class U8GameData{ //调用时机——2 : 创建角色; 3:进入游戏; 4:登记提升;5:退出游戏 dataType : number; //角色ID roleID:string; //角色名称 roleName : string; //角色等级 roleLevel : number; //服务器ID serverID : string; //服务器名称 serverName : string; //当前角色生成拥有的虚拟币数量 moneyNum : number; //角色创建时间,从1970年到现在的时间,单位秒 roleCreateTime : string; //角色等级变化时间,从1970年到现在的时间,单位秒, 没有传0 roleLevelUpTime : string; } //抽象的SDK api接口 declare interface IU8Platform { login(): Promise; //登录接口 pay(data : U8PayParams): Promise; //支付接口 submitGameData(data : U8GameData) : Promise; //上报数据接口, 需要分别在创建角色,进入游戏,登记升级, 退出游戏四个地方调用, 每个地方调用时,U8GameData中的dataType注意设置为对应的值。 exit(): Promise; //退出游戏接口, 调用会弹出渠道SDK的退出确认框 getChannelID(): Promise; //获取渠道号 } //U8SDK Android平台调用接口实现 class U8AndroidPlatform implements IU8Platform{ androidClass : string = "org/cocos2dx/javascript/U8SDKForCocos"; login(){ console.debug("login in cocos for android called."); jsb.reflection.callStaticMethod(this.androidClass, "login", "()V"); } pay(data:U8PayParams){ let payData = JSON.stringify(data); console.debug("pay in cocos for android called." + payData); jsb.reflection.callStaticMethod(this.androidClass, "pay", "(Ljava/lang/String;)V", payData); } submitGameData(data:U8GameData){ let gameData = JSON.stringify(data); console.debug("submitGameData in cocos for android called." + gameData); jsb.reflection.callStaticMethod(this.androidClass, "submitGameData", "(Ljava/lang/String;)V", gameData); } exit(){ console.debug("submitGameData in cocos for android called."); jsb.reflection.callStaticMethod(this.androidClass, "exit", "()V"); } getChannelID(){ console.debug("getChannelID in cocos for android called."); jsb.reflection.callStaticMethod(this.androidClass, "getChannelID", "(I)V"); } } //U8SDK iOS平台调用接口实现 class U8IOSPlatform implements IU8Platform{ login(){ //wait to implements } pay(data:U8PayParams){ //wait to implements } submitGameData(data:U8GameData){ //wait to implements } exit(){ //wait to implements } getChannelID(){ //wait to implements } } //U8SDK windows等平台默认实现 class U8DebugPlatform implements IU8Platform{ login(){ console.log("u8 login called."); } pay(data:U8PayParams){ let payData = JSON.stringify(data); console.log("u8 pay called. data:" + payData); } submitGameData(data:U8GameData){ let gameData = JSON.stringify(data); console.log("u8 submitGameData called. data:" + gameData); } exit(){ console.log("u8 exit called."); } getChannelID(){ console.log("u8 getChannelID called."); } } //U8SDK接口对外调用类 //这里处理原生层的api调用,以及收到原生层的回调接口处理 class U8SDK { private static _instance:U8SDK = null; public static getInatance(){ if(this._instance==null) { this._instance = new U8SDK(); } return this._instance; } platform : IU8Platform; public constructor() { } //初始化SDK public initSDK () { console.log("u8sdk initSDK in wrapper called"); if(!this.platform){ if(cc.sys.OS_ANDROID === cc.sys.os){ this.platform = new U8AndroidPlatform(); }else if(cc.sys.OS_IOS == cc.sys.os){ this.platform = new U8IOSPlatform(); }else{ this.platform = new U8DebugPlatform(); } console.log("u8sdk inited in wrapper"); } } //SDK登录成功回调, loginResult是json格式的登录结果 //userID : 唯一账号ID //sdkUserID : 渠道平台那边的玩家唯一账号(不可以用这个单独作为和游戏角色绑定的字段) //username : 用户名, 无意义 //sdkUsername : 渠道平台用户名 //token : 聚合server返回的token, 携带给游戏服务器, 游戏服务器去聚合server做二次登陆校验使用 onLoginSuccess(loginResult:string){ console.log("onLoginSuccess called in egret."+loginResult); } //SDK登出回调,游戏需要在这里引导玩家登出游戏,返回登录界面,重新拉起SDK登录界面,让玩家重新登录 onLogout(){ console.log("onLogout called in egret."); } //SDK切换账号回调, 游戏需要在这里引导玩家登出游戏,返回登录界面,重新拉起SDK登录界面,让玩家重新登录 onSwitchAccountSuccess(loginResult:string){ console.log("onSwitchAccountSuccess called in egret."+loginResult); } //SDK支付客户端结果, 注意发货不要依赖这个接口, 以游戏服务器收到聚合服务器的支付回调通知为准。 payCode为0,说明支付成功,其他为支付失败。 onPayResult(payCode:string){ console.log("onPayResult called in egret."+payCode); } //获取渠道号回调 onGetChannel(channel:string){ console.log("onGetChannel called in egret."+channel); } // 调用登录 login(){ console.debug("u8 login called in wrapper."); this.platform.login(); } // 调用支付 pay(data:U8PayParams){ console.debug("u8 pay called in wrapper."); this.platform.pay(data); } // 调用数据上报 submitGameData(data:U8GameData){ console.debug("u8 submitGameData called in wrapper."); this.platform.submitGameData(data); } // 调用退出游戏 exit(){ console.debug("u8 exit called in wrapper."); this.platform.exit(); } // 获取当前渠道号 getChannelID(){ console.debug("u8 getChannelID called in wrapper."); this.platform.getChannelID(); } ////////////////// 原生平台的回调 //////////////////////// // 登录成功回调 // result: 登录成功之后, u8sdk服务端返回的结果,json格式 //userID : 唯一账号ID //sdkUserID : 渠道平台那边的玩家唯一账号(不可以用这个单独作为和游戏角色绑定的字段) //username : 用户名, 无意义 //sdkUsername : 渠道平台用户名 //token : 聚合server返回的token, 携带给游戏服务器, 游戏服务器去聚合server做二次登陆校验使用 onU8LoginSuccess(result:string) { console.debug("onU8LoginSuccess called in U8SDK.ts. " + result) } // 登出回调, 当玩家从SDK的悬浮窗中登出, 会触发该回调 // 游戏层收到该回调, 需要引导玩家返回游戏登录界面,重新调用登录API进行登录。 onU8Logout() { console.debug("onU8Logout called in U8SDK.ts") } // 切换到新账号成功的回调,当玩家从SDK的悬浮窗中切换到新账号时,会触发该该回调 // 游戏层收到该回调,需要引导玩家返回游戏登录界面重新以当前新账号登录信息查询角色信息,让玩家以新账号对应的角色重新进入游戏 // result: 新账号登录成功之后, u8sdk服务端返回的结果, 和登录成功结果格式一致,json格式 //userID : 唯一账号ID //sdkUserID : 渠道平台那边的玩家唯一账号(不可以用这个单独作为和游戏角色绑定的字段) //username : 用户名, 无意义 //sdkUsername : 渠道平台用户名 //token : 聚合server返回的token, 携带给游戏服务器, 游戏服务器去聚合server做二次登陆校验使用 onU8SwitchAccountSuccess(result:string) { console.debug("onU8SwitchAccountSuccess called in U8SDK.ts. " + result) } // 调用上面getChannelID接口之后,渠道号会通过该接口返回 // result: 渠道号 onU8GetChannel(result:string) { console.debug("onU8GetChannel called in U8SDK.ts. " + result) } } // 全局定义一个u8sdkApi,其他文件中可以直接使用u8sdkApi.来调用这里对应的api接口 window["u8sdkApi"] = U8SDK.getInatance(); |
定义好该组件之后, 游戏中登录,支付等地方,就可以直接调用u8sdkApi来完成U8SDK API的调用了。 我们看Hello World.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
const {ccclass, property} = cc._decorator; import {U8PayParams, U8GameData} from './U8SDK'; @ccclass export default class Helloworld extends cc.Component { @property(cc.Label) label: cc.Label = null; @property text: string = 'U8SDK——让手游发行更简单'; @property(cc.Button) btnLogin: cc.Button = null; @property(cc.Button) btnPay: cc.Button = null; @property(cc.Button) btnSubmit: cc.Button = null; @property(cc.Button) btnExit: cc.Button = null; start () { // init logic this.label.string = this.text; this.btnLogin.node.on('click', this.onLoginClicked, this); this.btnPay.node.on('click', this.onPayClicked, this); this.btnSubmit.node.on('click', this.onSubmitClicked, this); this.btnExit.node.on('click', this.onExitClicked, this); if(cc.sys.platform == cc.sys.ANDROID){ // 监听android 手机返回键事件 cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); } //初始化SDK u8sdkApi.initSDK(); } onKeyDown(event){ switch (event.keyCode) { case cc.macro.KEY.back: // 如果是手机返回键, 调用退出接口, 弹出渠道SDK的退出确认框 u8sdkApi.exit(); break; } } onLoginClicked (btn) { console.log("btnLogin clicked................."); u8sdkApi.login(); } onPayClicked (btn) { console.log("btnPay clicked................."); let payData = new U8PayParams(); payData.productId = "1"; payData.productName = "100元宝"; payData.productDesc = "购买100元宝,送20"; payData.price = 1; payData.buyNum = 1; payData.coinNum = 1000; payData.serverId = "1"; payData.serverName = "刺激战场"; payData.roleId = "1"; payData.roleName = "u8demo"; payData.roleLevel = 1; payData.payNotifyUrl = "http://game.h5.com/gameCallback"; payData.vip = "10"; payData.extension = "custom data will be sent to game server with pay callback."; u8sdkApi.pay(payData); } onSubmitClicked (btn) { console.log("btnSubmit clicked................."); let data = new U8GameData(); data.dataType = 2; //以下四个地方都需要调用该接口。 每个地方对应的dataType不同。 dataType: 2:创建角色;3:进入游戏;4:等级升级;5:退出游戏 data.roleID = "1"; data.roleName = "u8demo"; data.roleLevel = 1; data.serverID = "1"; data.serverName = "刺激战场"; data.moneyNum = 1000; data.roleCreateTime = "1000035434"; data.roleLevelUpTime = "0"; u8sdkApi.submitGameData(data); } onExitClicked (btn) { console.log("btnExit clicked................."); u8sdkApi.exit(); } } |
这样TypeScript里面的组件,我们就封装完毕了;接下来,我们就需要将游戏工程编译成Android Studio工程。 如果这里有疑问或者不清楚如何编译,请参考[Cocos Creator官方文档]
生成之后,我们用Android Studio打开生成的Android项目工程,开始编写代码之前,我们先对工程做一些配置:
1、引用U8SDKRelease
将U8SDKRelease放到生成的Android工程目录下, 然后打开settings.gradle文件,在其中加上一句:
1 |
include ':U8SDKRelease' |
工程目录/app/build.gradle中最下面dependencies依赖配置中,增加一个U8SDKRelease工程的引用,如下:
1 |
implementation project(':U8SDKRelease') |
同样的,工程目录/game/build.gradle中最下面dependencies依赖配置中,也增加一个U8SDKRelease工程的引用,如下:
1 |
implementation project(':U8SDKRelease') |
然后在AS工程中gradle视图中,重新Refresh一下同步一下工程。
2、设置U8Application
接入U8SDK时,我们需要将工程的Application设置为com.u8.sdk.U8Application。 打开工程目录/app/AndroidManifest.xml文件,在application节点中增加一个android:name配置:
1 |
android:name="com.u8.sdk.U8Application" |
如果游戏有自己的Application,那么可以将游戏自己的Application继承com.u8.sdk.U8Application。
3、实现代码
接下来,我们就可以编写Android层的代码了。通过上面typescript中的U8SDK.ts组件我们可以看到,TypeScript中最终是调用了Java层的org.cocos2dx.javascript.U8SDKForCocos类中的相关API。
所以,我们在生成的AS工程/src目录中org.cocos2dx.javascript中定义一个U8SDKForCocos单例类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
public class U8SDKForCocos { private static final String TAG = "U8SDKForCocos"; private static U8SDKForCocos instance; private Cocos2dxActivity context; public static U8SDKForCocos getInstance(){ if(instance == null){ instance = new U8SDKForCocos(); } return instance; } // 回调给ts中 private static void callbackToJs(final String jsMethod) { getInstance().context.runOnGLThread(new Runnable() { @Override public void run() { Cocos2dxJavascriptJavaBridge.evalString("window.u8sdkApi." + jsMethod); } }); } public void initSDK(final Cocos2dxActivity context){ this.context = context; U8Platform.getInstance().init(context, new U8InitListener() { @Override public void onLogout() { //用户登出回调(需要收到该回调需要返回游戏登录界面,并调用login接口,打开SDK登录界面) callbackToJs("onU8Logout()"); } @Override public void onSwitchAccount(UToken data) { //游戏中通过SDK切换到新账号的回调,游戏收到该回调,需要引导用户重新登录,重新加载该新用户对应的角色数据 //Toast.makeText(context, "切换账号并登陆成功", Toast.LENGTH_LONG).show(); String jsonResult = loginResult2Json(data); callbackToJs("onU8SwitchAccountSuccess('" + jsonResult + "')"); } @Override public void onPayResult(int code, String msg) { Log.d("U8SDK", "pay result. code:"+code+";msg:"+msg); int payCode = 0; //成功 switch(code){ case U8Code.CODE_PAY_SUCCESS: Toast.makeText(context, "支付成功", Toast.LENGTH_LONG).show(); //因为部分SDK支付成功回调触发的时机并不是真的支付成功,所以这里最好不要主动给用户提示, 以SDK充值界面中显示的状态为准。 break; case U8Code.CODE_PAY_FAIL: Toast.makeText(context, "支付失败", Toast.LENGTH_LONG).show(); payCode = 1; //因为部分SDK支付界面关闭可能也会触发支付失败回调,所以这里最好不要主动给用户提示, 以SDK充值界面中显示的状态为准。 break; case U8Code.CODE_PAY_CANCEL: Toast.makeText(context, "支付取消", Toast.LENGTH_LONG).show(); payCode = 1; break; case U8Code.CODE_PAY_UNKNOWN: payCode = 1; Toast.makeText(context, "未知错误", Toast.LENGTH_LONG).show(); break; default: payCode = 1; } } @Override public void onRealnameResult(final URealNameInfo realNameInfo) { // 如果使用u8防沉迷插件, 游戏层不需要处理实名认证和防沉迷逻辑, 这里可以不需要管 // 如果游戏层自己实现防沉迷, 调用U8SDK实名查询和实名认证接口,相关结果会回调到这里 if(realNameInfo.isRealname()){ //已经实名了 U8SDK.getInstance().runOnMainThread(new Runnable() { @Override public void run() { ResourceHelper.showTipStr(context, "玩家已完成实名,年龄:"+realNameInfo.getAge()); } }); }else { //没有实名,并且结果是从查询接口返回的,则调用实名认证UI界面 ResourceHelper.showTipStr(context, "玩家未完成实名"); if(realNameInfo.isTypeQuery()){ // 调用实名认证界面接口,弹出实名认证接口,让玩家实名 } } } @Override public void onLoginResult(int code, UToken data) { switch(code){ case U8Code.CODE_LOGIN_SUCCESS: //SDK登录成功回调 String jsonResult = loginResult2Json(data); callbackToJs("onU8LoginSuccess('" + jsonResult + "')"); break; case U8Code.CODE_LOGIN_FAIL: Log.d("U8SDK", "login failed from sdk."); Toast.makeText(context, "登录失败", Toast.LENGTH_LONG).show(); break; } } @Override public void onInitResult(int code, String msg) { Log.d("U8SDK", "init result.code:"+code+";msg:"+msg); switch(code){ case U8Code.CODE_INIT_SUCCESS: Toast.makeText(context, "初始化成功", Toast.LENGTH_LONG).show(); break; case U8Code.CODE_INIT_FAIL: Toast.makeText(context, "初始化失败", Toast.LENGTH_LONG).show(); break; } } @Override public void onProductQueryResult(List result) { //不需要处理 } @Override public void onDestroy() { Log.d("U8SDK", "game onDestroy callback called."); } @Override public void onSinglePayResult(int code, U8Order order) { //单机游戏支付回调处理接口 Log.d("U8SDK", "single pay callback. code:"+code); } @Override public void onResult(int code, String msg) { //不需要处理 } }); } /** * 调用U8SDK 框架的登录接口 */ public static void login() { Log.d(TAG, "login called."); getInstance().context.runOnUiThread(new Runnable() { @Override public void run() { U8Platform.getInstance().login(getInstance().context); } }); } /** * 调用U8SDK 框架的支付接口 * @param jsonData 游戏层传入的json格式的U8PayParams对象 */ public static void pay(final String jsonData) { Log.d(TAG, "pay called. data: " + jsonData); getInstance().context.runOnUiThread(new Runnable() { @Override public void run() { PayParams payParams = parsePayParams(jsonData); U8Platform.getInstance().pay(getInstance().context, payParams); } }); } /** * 调用U8SDK 框架的数据上报接口 * @param jsonData 游戏层传入的json格式的U8GameData对象 */ public static void submitGameData(final String jsonData) { Log.d(TAG, "submitGameData called. data:" + jsonData); getInstance().context.runOnUiThread(new Runnable() { @Override public void run() { UserExtraData data = parseGameData(jsonData); U8Platform.getInstance().submitExtraData(data); } }); } /** * 退出游戏, 弹出退出确认框 */ public static void exit() { Log.d(TAG, "exit called."); getInstance().context.runOnUiThread(new Runnable() { @Override public void run() { exitSDK(); } }); } /** * 获取当前渠道的渠道ID * @return */ public static int getChannelID() { Log.d(TAG, "getChannelID called."); int channelID = U8SDK.getInstance().getCurrChannel(); callbackToJs("onU8SwitchAccountSuccess('" + channelID + "')"); return channelID; } private static void exitSDK(){ U8Platform.getInstance().exitSDK(new U8ExitListener() { @Override public void onGameExit() { //游戏自己的退出确认框 AlertDialog.Builder builder = new AlertDialog.Builder(getInstance().context); builder.setTitle("退出确认"); builder.setMessage("现在还早,要不要再玩一会?"); builder.setCancelable(true); builder.setPositiveButton("好吧", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { //这里什么都不用做 } }); builder.setNeutralButton("一会再玩", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { //退出游戏 getInstance().context.finish(); System.exit(0); } }); builder.show(); } }); } //反序列化从js层传过来的上报参数 private static UserExtraData parseGameData(String str){ UserExtraData data = new UserExtraData(); JSONObject json = null; try { json = new JSONObject(str); data.setDataType(json.getInt("dataType")); data.setRoleID(json.getString("roleID")); data.setRoleName(json.getString("roleName")); data.setRoleLevel(json.getString("roleLevel")); data.setServerID(json.getInt("serverID")); data.setServerName(json.getString("serverName")); data.setMoneyNum(json.getInt("moneyNum")); String roleCreateTime = json.getString("roleCreateTime"); String roleLevelUpTime = json.getString("roleLevelUpTime"); if(!TextUtils.isEmpty(roleCreateTime.trim())){ data.setRoleCreateTime(Long.valueOf(roleCreateTime.trim())); } if(!TextUtils.isEmpty(roleLevelUpTime.trim())){ data.setRoleLevelUpTime(Long.valueOf(roleLevelUpTime.trim())); } data.setVip(json.optString("vip", "0")); } catch (Exception e) { e.printStackTrace(); } return data; } //反序列化从js层传来的支付参数 private static PayParams parsePayParams(String str){ PayParams params = new PayParams(); try{ JSONObject json = new JSONObject(str); params.setProductId(json.getString("productId")); params.setProductName(json.getString("productName")); params.setProductDesc(json.getString("productDesc")); params.setPrice(json.getInt("price")); params.setRatio(0);//该字段废弃不用 params.setBuyNum(json.getInt("buyNum")); params.setCoinNum(json.getInt("coinNum")); params.setServerId(json.getString("serverId")); params.setServerName(json.getString("serverName")); params.setRoleId(json.getString("roleId")); params.setRoleName(json.getString("roleName")); params.setRoleLevel(json.getInt("roleLevel")); params.setPayNotifyUrl(json.getString("payNotifyUrl")); params.setVip(json.getString("vip")); params.setExtension(json.getString("extension")); }catch(Exception e){ e.printStackTrace(); } return params; } //登录结果转json private static String loginResult2Json(UToken authResult){ JSONObject json = new JSONObject(); try{ json.put("userID", authResult.getUserID()); json.put("sdkUserID", authResult.getSdkUserID()); json.put("username", authResult.getUsername()); json.put("sdkUsername", authResult.getSdkUsername()); json.put("token", authResult.getToken()); }catch(Exception e){ e.printStackTrace(); } return json.toString(); } } |
这个组件就是供游戏层TypeScript中调用,以及将SDK层相关的结果回调给游戏层TypeScript中。
然后在AppActivity.java中,我们还需要调用一下初始化和相关的生命周期函数。
在AppActivity.java中onCreate函数中,调用以下SDK初始化接口:
1 2 |
//初始化U8SDK U8SDKForCocos.getInstance().initSDK(this); |
然后其他生命周期函数如下调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
@Override protected void onResume() { super.onResume(); SDKWrapper.getInstance().onResume(); U8SDK.getInstance().onResume(); } @Override protected void onPause() { super.onPause(); SDKWrapper.getInstance().onPause(); U8SDK.getInstance().onPause(); } @Override protected void onDestroy() { super.onDestroy(); // Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508 if (!isTaskRoot()) { return; } SDKWrapper.getInstance().onDestroy(); U8SDK.getInstance().onDestroy(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); SDKWrapper.getInstance().onActivityResult(requestCode, resultCode, data); U8SDK.getInstance().onActivityResult(requestCode, resultCode, data); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); SDKWrapper.getInstance().onNewIntent(intent); U8SDK.getInstance().onNewIntent(intent); } @Override protected void onRestart() { super.onRestart(); SDKWrapper.getInstance().onRestart(); U8SDK.getInstance().onRestart(); } @Override protected void onStop() { super.onStop(); SDKWrapper.getInstance().onStop(); U8SDK.getInstance().onStop(); } @Override public void onBackPressed() { SDKWrapper.getInstance().onBackPressed(); super.onBackPressed(); U8SDK.getInstance().onBackPressed(); } @Override public void onConfigurationChanged(Configuration newConfig) { SDKWrapper.getInstance().onConfigurationChanged(newConfig); U8SDK.getInstance().onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { SDKWrapper.getInstance().onRestoreInstanceState(savedInstanceState); super.onRestoreInstanceState(savedInstanceState); } @Override protected void onSaveInstanceState(Bundle outState) { SDKWrapper.getInstance().onSaveInstanceState(outState); super.onSaveInstanceState(outState); } @Override protected void onStart() { SDKWrapper.getInstance().onStart(); U8SDK.getInstance().onStart(); super.onStart(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); U8SDK.getInstance().onRequestPermissionResult(requestCode, permissions, grantResults); } |
好了, 这些实现之后, 我们就可以编译运行app模块生成游戏的apk。 然后点击登录,看下是否弹出U8SDK默认的测试登录界面吧。 最终效果如下:
本文出自 U8SDK技术博客,转载时请注明出处及相应链接。
本文永久链接: http://www.uustory.com/?p=2335