美文网首页
Android/iOS webview Js 交互

Android/iOS webview Js 交互

作者: 張小明 | 来源:发表于2020-05-01 09:42 被阅读0次

    最近调试一个活动页面,需要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));
    })
    

    相关文章

      网友评论

          本文标题:Android/iOS webview Js 交互

          本文链接:https://www.haomeiwen.com/subject/ywufghtx.html