最近调试一个活动页面,需要app和web端传值。这里iOS讨论的是WKWebView
URL传值
最开始我们使用了url传值,在url中拼接各种参数,虽然暴力,但是好用,不过最后领导给否了。
Cookie传值
转为cookie传值,cookie传值的坑还蛮多的。
-
iOS
iOS WKWebView Cookie 写入可以参考这篇文章,不过用户信息改变的时候,我们需要进行reload操作
[self.webconfig.userContentController removeAllUserScripts];
//这里重新设置一遍
NSString *cookieSource = [NSString stringWithFormat:@"document.cookie = 'user=%@';", @"userValue"];
WKUserScript *cookieScript1 = [[WKUserScript alloc] initWithSource:cookieSource1 injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[self.webconfig.userContentController addUserScript:cookieScript1];
[self.webView reload];
方法同样来源于网络,不过找不到那篇文章了。
我们改变用户信息的时候要记住需要把之前的cookie清除,可能你会想到在设置新的cookie前清除之前的cookie,不过
* 清除cookie的操作无论在iOS还是Android(部分机型)中都是异步的
所以你在设置cookie前得保证清除操作已经完成,否则你新设置的cookie也被清空了,就会出现时灵时不灵的现象。iOS最后采用在控制器的生命周期中进行相应的清空/写入cookie操作,离开清空,回来写入。
-
Android
Android遇到一个cookie的奇怪问题,无法在三星手机(其它机型没发现这个问题,公司两台三星测试机都出现这个问题)中连续操作cookie,比如你写入了,再清空清除不了,比如你第一次loadURL的时候没写入,之后用户信息改变的时候去写入,又写入不了。不知道有没有人遇到相同的问题。下面是我使用的方式,不过因为发现部分机型有问题就没有再使用,希望可以有人帮忙查看一下问题
void setCookie() {
wvView.clearCache(true);
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.removeSessionCookies(null);
cookieManager.removeAllCookies(null);
} else {
cookieManager.removeSessionCookie();
cookieManager.removeAllCookie();
}
Token token = TokenManager.getInstance().getToken();
if (token != null && UserManager.getInstance().getUser() != null) {
String StringCookie1 = "userId=" + UserManager.getInstance().getUser().id;
String StringCookie2 = "ticket=" + token.getTicket();
cookieManager.setAcceptCookie(true);
cookieManager.setCookie(originalUrl, StringCookie1);
cookieManager.setCookie(originalUrl, StringCookie2);
}
CookieSyncManager.getInstance().sync();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
wvView.loadUrl(originalUrl);
}
},1000);
}
JS传值
最后采用JS传值。
-
iOS
对于iOS与JS交互,可以使用webkit的messagehandlers方法
这篇文章可以了解一下。
不过需要注意我们希望JS调用的方法,需要先进行如下操作注册你希望监听的JS调用,否则你会得到一个Type error
[userContentController addScriptMessageHandler:self name:@"Share"];
[userContentController addScriptMessageHandler:self name:@"Camera"];
关于传值,上面的那篇文章也有提到,我们需要两个方法,一个方法前端调用APP,APP收到消息后主动调用JS写好的回调方法,大概是这个样子。
if ([message.name isEqualToString:@"test"]){
NSString *value = @"";
[self.webView evaluateJavaScript:[NSString stringWithFormat:@"testCallback('%@')",value] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
NSLog(@"mserr%@", error);
}];
}
不过如果你确保完全遵循了上面文章的方法,却在调用前端JS的时候仍然遇到了Type error: undefined is not a function 错误,首先检查方法名是否完全一致,如果一切正常,那么有可能你们的web端是使用Vue框架,使用Vue的话,我们需要把JS回调的方法在相应的生命周期中挂载在window上,参考这篇文章,我们在实际操作时候还进行了一个延时操作,看你们自己的情况,我们大概是这个样子
延时操作{
window.testCallback = this.testCallback
}
-
Android
WebViewJavaScriptBridge
JsBridge很强大但是也有很多莫名其妙的问题
推荐 DSBridge,一切按照文档来就好
如果遇到跑不通的情况,多调调文档中的示例
示例:
In Java
public class JsEchoApi {
@JavascriptInterface
public Object syn(Object args) throws JSONException {
return args;
}
@JavascriptInterface
public void asyn(Object args,CompletionHandler handler){
handler.complete(args);
}
}
//namespace is "echo"
dwebView.addJavascriptObject(new JsEchoApi(),"echo");
In Javascript
// call echo.syn
var ret=dsBridge.call("echo.syn",{msg:" I am echoSyn call", tag:1})
alert(JSON.stringify(ret))
// call echo.asyn
dsBridge.call("echo.asyn",{msg:" I am echoAsyn call",tag:2},function (ret) {
alert(JSON.stringify(ret));
})
网友评论