cocos creator 游戏在发布到android/ios等平台时,难免要与本地原生平台互相调用。
官方为我们提供了Java 原生反射机制和Objective-C 原生反射机制。以android的Java平台为例
cocos creator 运行时调用android原生环境
var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parameters...)
android原生环境调用cocos creator运行时
Cocos2dxJavascriptJavaBridge.evalString("cc.log(\"Javascript Java bridge!\")");
在实际的开发中这两种通讯机制往往是一一对应的。就像HTTP环境中发起一个request必然对应一个response。而这两个接口几乎是无状态的,尤其是java层发起的连返回值都没有。
举个例子axios是前端和nodejs环境非常流行的http封装
1// 发起请求request 2axios.get('/user', { 3 params: { 4 ID: 12345 5 } 6 }) 7 .then(function (response) { 8 console.log(response); 9 //返回 response 10 }) 11 .catch(function (error) { 12 console.log(error); 13 //错误捕捉 14 })
如果CocosCreator环境也可以这样使用就舒服多了。
事实上它也的确提供了JSB的方式实现这一需求。CocosCreator引用了腾讯在线教育部技术博客,对此有一个详细的描述。总之通过这种方式CocosCreator运行时
就能用回掉函数作为参数来满足这一需求。
1jsb.fileDownloader.requestDownload(url, savePath, cookies, options, (success, url, savePath, msg, code) => { 2 // do whatever you want 3});
如果这就完了,我也就不用写这篇博文来补充了。
JSB是CocosCreator的JavaScript运行时和native C++ 环境通讯的解决方案。而我的需求可能只是在CocosCreator 运行时发起一个视频激励广告,视频播放完毕后再通知CocosCreator运行时视频播放完毕,可以给予玩家奖励啦。那么JSB的方案未免过于复杂了。
cocos runtime <---JSB--> Nitive C++ <--JNI--> android runtime
实际上HTTP的Request和Response本身也是相互独立且异步的。让它们能一一对应是因为在发起request的时候添加了标示ID并记录在缓存队列,再异步返回Response时带上这个标示ID用于在缓存队列中寻找自己对应的Request上下文。我们这里借鉴HTTP协议的方式让Cocos运行时与本地代码双向通讯时可以一一对应。
1// Cococs Creator 环境使用 2 3 Platform.watch_video(_=>{ 4 // 回调函数A,激励视频播放完毕时执行,诸如音乐恢复,加金币或再玩一局 5 }) 6 7//Platform.ts 8 9 10export default class Platform { 11 private static _callbackMaps: { [key: string]: any } = {}; //回掉缓存 12 private static _callbackId = 0; //用于回掉标示的ID 13 14 15 static watch_video(callback, target?) { 16 console.log("######开始看视频") 17 if (cc.sys.WECHAT_GAME == cc.sys.platform) { 18 19 } else if (cc.sys.isNative && cc.sys.ANDROID == cc.sys.platform) { 20 cc.audioEngine.pauseMusic(); //暂停音乐 21 let cid = this._callbackId++; //自增标示ID区别每一次调用 22 //组织回调上下文,并加入缓存数组 23 let callbackContext = { 24 callback: callback, 25 target: target, 26 callbackId: cid.toString() 27 } 28 this._callbackMaps[cid] = callbackContext; 29 //调用android本地代码,并把cid作为参数。 30 var o = jsb.reflection.callStaticMethod('com/jmylab/kittenbal/AdManage', 'showAdVideo', '(Ljava/lang/String;)V', cid); 31 } else { 32 callback && callback.call(target) 33 } 34 } 35 //提供给android和ios应用层调用的接口 36 static onNativeCall(state, callbackId) { 37 //清除缓存 38 let callbackContext =null; 39 if (this._callbackMaps.hasOwnProperty(callbackId)) { 40 callbackContext = this._callbackMaps[callbackId]; 41 delete this._callbackMaps[callbackId]; 42 } 43 44 if (state == 'reward') { 45 //给予奖励,执行回掉函数A 46 callbackContext.callback && callbackContext.callback.call(callbackContext.target); 47 } else if (state == 'close') { 48 Toast.make("必须看完视频,才能获取奖励") 49 } else if (state == 'failed') { 50 Toast.make("failed ") 51 } 52 53 } 54} 55//挂在window对象,方便本地代码调用 56window['Platform'] = Platform;