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封装
// 发起请求request
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
//返回 response
})
.catch(function (error) {
console.log(error);
//错误捕捉
})
如果CocosCreator环境也可以这样使用就舒服多了。
事实上它也的确提供了JSB的方式实现这一需求。CocosCreator引用了腾讯在线教育部技术博客,对此有一个详细的描述。总之通过这种方式CocosCreator运行时
就能用回掉函数作为参数来满足这一需求。
jsb.fileDownloader.requestDownload(url, savePath, cookies, options, (success, url, savePath, msg, code) => {
// do whatever you want
});
如果这就完了,我也就不用写这篇博文来补充了。
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运行时与本地代码双向通讯时可以一一对应。
// Cococs Creator 环境使用
Platform.watch_video(_=>{
// 回调函数A,激励视频播放完毕时执行,诸如音乐恢复,加金币或再玩一局
})
//Platform.ts
export default class Platform {
private static _callbackMaps: { [key: string]: any } = {}; //回掉缓存
private static _callbackId = 0; //用于回掉标示的ID
static watch_video(callback, target?) {
console.log("######开始看视频")
if (cc.sys.WECHAT_GAME == cc.sys.platform) {
} else if (cc.sys.isNative && cc.sys.ANDROID == cc.sys.platform) {
cc.audioEngine.pauseMusic(); //暂停音乐
let cid = this._callbackId++; //自增标示ID区别每一次调用
//组织回调上下文,并加入缓存数组
let callbackContext = {
callback: callback,
target: target,
callbackId: cid.toString()
}
this._callbackMaps[cid] = callbackContext;
//调用android本地代码,并把cid作为参数。
var o = jsb.reflection.callStaticMethod('com/jmylab/kittenbal/AdManage', 'showAdVideo', '(Ljava/lang/String;)V', cid);
} else {
callback && callback.call(target)
}
}
//提供给android和ios应用层调用的接口
static onNativeCall(state, callbackId) {
//清除缓存
let callbackContext =null;
if (this._callbackMaps.hasOwnProperty(callbackId)) {
callbackContext = this._callbackMaps[callbackId];
delete this._callbackMaps[callbackId];
}
if (state == 'reward') {
//给予奖励,执行回掉函数A
callbackContext.callback && callbackContext.callback.call(callbackContext.target);
} else if (state == 'close') {
Toast.make("必须看完视频,才能获取奖励")
} else if (state == 'failed') {
Toast.make("failed ")
}
}
}
//挂在window对象,方便本地代码调用
window['Platform'] = Platform;