-
Creator 版本:2.1
-
目标平台:iOS / Android
项目中用到了webview登陆,登陆成功之后通知客户端,参照官方最新的2.1使用手册
cc.Class({
extends: cc.Component,
properties: {
webview: cc.WebView
},
onLoad: function () {
var scheme = "TestKey";// 这里是与内部页面约定的关键字
function jsCallback (url) {
// 这里的返回值是内部页面的 url 数值,
// 需要自行解析自己需要的数据
var str = url.replace(scheme + '://', '');
var data = JSON.stringify(str);// {a: 0, b: 1}
}
this.webview.setJavascriptInterfaceScheme(scheme);
this.webview.setOnJSCallback(jsCallback);
}
});
// 因此当你需要通过内部页面交互 WebView 时,
// 应当设置内部页面 url 为:TestKey://(后面你想要回调到 WebView 的数据)
// WebView 内部页面代码
<html>
<body>
<dev>
<input type="button" value="触发" onclick="onClick()"/>
</dev>
</body>
<script>
function onClick () {
// 其中一个设置URL方案
document.location = 'TestKey://{a: 0, b: 1}';
}
</script>
</html>
结果一般都是 Failed to create URI from url
看了一下源码
try {
URI uri = URI.create(urlString);
if (uri != null && uri.getScheme().equals(mJSScheme)) {
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
Cocos2dxWebViewHelper._onJsCallback(mViewTag, urlString);
}
});
return true;
}
} catch (Exception e) {
Log.d(TAG, "Failed to create URI from url");
}
URI uri = URI.create(urlString);
这里就会进入catch里面了
尝试了不同的creator几个版本,只有某一个版本设置
var scheme = "http";
setJavascriptInterfaceScheme 和 setOnJSCallback 方法才能正确执行
尝试换一种思路,使用
Cocos2dxJavascriptJavaBridge.evalString("console.log('test')");
发现可以正确输出log,于是猜测这个函数可以执行全局的js函数,测试确实可行。下面是我的实现代码:
class Cocos2dxWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, final String urlString) {
Cocos2dxActivity activity = (Cocos2dxActivity) getContext();
try {
/* ------------------------------登陆成功 start------------------------------- */
String strType = urlString.substring(0, 6);
if (strType.equals("peter:")) {
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
String str = urlString.substring(6).substring(1);
str = str.substring(0, str.length() - 1);
Log.d(TAG, "peter str1 = " + str);
Cocos2dxJavascriptJavaBridge.evalString("login_callback(" + str + ")");
}
});
return false;
}
/* ------------------------------登陆成功 end--------------------------------- */
URI uri = URI.create(urlString);
if (uri != null && uri.getScheme().equals(mJSScheme)) {
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
Cocos2dxWebViewHelper._onJsCallback(mViewTag, urlString);
}
});
return true;
}
} catch (Exception e) {
Log.d(TAG, "Failed to create URI from url");
}
boolean[] result = new boolean[]{true};
CountDownLatch latch = new CountDownLatch(1);
// run worker on cocos thread
activity.runOnGLThread(new ShouldStartLoadingWorker(latch, result, mViewTag, urlString));
// wait for result from cocos thread
try {
latch.await();
} catch (InterruptedException ex) {
Log.d(TAG, "'shouldOverrideUrlLoading' failed");
}
return result[0];
}
- 前端代码:
let data = JSON.stringify({
type:"login_success",
phone: res.phone,
headImg: res.headImg,
account_type: res.accountType,
isNative: res.isNative
});
if (!res.isNative) {
top.postMessage(data, '*');
} else {
document.location = 'peter:' + data;
}
- native平台js回调函数
需要写在onload之类的函数里面,不然放在最外面,android会报错
window.login_callback = (para) => {
console.log(JSON.stringify(para));
}
- client端如何接收web端传递的值?
上面判断非原声平台的if里面使用到了
top.postMessage(data, '*');
web端的client可以这么接收数值:
if (!cc.sys.isNative) {
window.addEventListener("message",
function (e) {
if (e.data.target || typeof e.data != 'string') return;
let data = JSON.parse(e.data);
if (!data.type) return;
switch (data.type) {
case 'login_success': // 登陆成功,跳转
console.log(data);
break;
default:
break;
}
}, false
);
}
希望引擎团队优化一下文档里面的函数,api里面明明写了,就是调用不起来。@jare