和编程在一起的第三年 : Android WebView、js交互方式原理总结

5699111-782b65f81ae79343.jpg
6826752-871b78d79223ff02.jpg

前言

好的,今天是2018.4.18日,是我和Android在一起的第三年。今天分享给大家的是Android WebView 、Js交互方式的原理总结。也是笔者参加第一次面试的时候被问到的。很尴尬,当时清楚的记得 没答出来..只是笼统的说了说WebView.

鸡汤

精通android的人有,精通javascript的人亦有,但同时深入掌握两门语言的人少有!

正文

android与js交互有两种方式,第一种是通过系统提供的@JavascriptInterface注解实现,第二种就是js注入。下面来详细讲解一下二者的使用方式,原理,区别。

一、@JavascriptInterface实现

实现步骤:

  • a.设置WebView支持js脚本

  • b.为提供给js调用的方法加上@JavascriptInterface注解

  • c.给WebView添加js接口

webView.getSettings().setJavaScriptEnabled(true);  
webView.addJavascriptInterface(new JSMethod(mContext), "lh");  
public class JSMethod {  
private Context mContext;  

public JSMethod(Context mContext) {  
    this.mContext = mContext;  
}  
@JavascriptInterface  
public void toast(String msg) {  
    Toast.makeText(mContext, msg == null ? "" : msg, Toast.LENGTH_SHORT).show();  
}  
}  

js端调用android方法:

lh.toast("Hello,China!");  

android端执行js方法:

 android端执行js方法:

二、js注入实现

先来说一下原理吧,当js调用prompt()方法时候,WebChromeClient.OnJsPrompt()方法会被触发,当js触发Android提供的接口方法时候,将该方法的名称、参数类型、参数值转成Json、然后通过prompt方法传递给Android端、android端解析json并通过反射执行对应的方法,同时也支持执行匿名回调。

5699111-e396b2906b411423.png
image.png

为WebView绑定WebChormeClient监听,在Html加载进度25%时进行js注入(注入的Js是根据android提供给Js的对象类名动态生成)

动态注入的Js代码如下:

javascript: (function(b) {  
console.log("HostApp initialization begin");  
var a = {  
    queue: [],  
    callback: function() {  
          
        var d = Array.prototype.slice.call(arguments, 0);//获取该函数参数并转换为Array数组  
        var c = d.shift();//取得数组第一个元素  
        var e = d.shift();  
        this.queue[c].apply(this, d);//新建一个对象 属性名称为取得的c,并将d数组作为他的值。然后将这个对象push到queue数组  
        if(!e) {//e为空的时候,将queue数组属性名称为c的对象删除  
            delete this.queue[c]  
        }  
    }  
};  
//各种赋值,最后都等于同一个函数  
a.alert = a.alert = a.alert = a.delayJsCallBack = a.getIMSI = a.getOsSdk = a.goBack = a.overloadMethod = a.overloadMethod = a.passJson2Java = a.passLongType = a.retBackPassJson = a.retJavaObject = a.testLossTime = a.toast = a.toast = function() {  
    var f = Array.prototype.slice.call(arguments, 0);  
    if(f.length < 1) {  
        throw "HostApp call error, message:miss method name"  
    }  
    var e = [];  
    //此段判断,然后赋值  
    for(var h = 1; h < f.length; h++) {  
        var c = f[h];  
        var j = typeof c;  
        e[e.length] = j;  
        if(j == "function") {  
            var d = a.queue.length;  
            a.queue[d] = c;  
            f[h] = d  
        }  
    }  
    //将匿名对象{method: f.shift(),types: e,args: f}转换成json字符串并用浏览器弹出确认可输入框,然后取得输入框的值json序列化为js对象  
    var g = JSON.parse(prompt(JSON.stringify({  
        method: f.shift(),  
        types: e,  
        args: f  
    })));  
    if(g.code != 200) {  
        throw "HostApp call error, code:" + g.code + ", message:" + g.result  
    }  
    return g.result  
};  
//获取a的属性值,然后循环  
Object.getOwnPropertyNames(a).forEach(function(d) {  
    var c = a[d];  
    //判断赋值  
    if(typeof c === "function" && d !== "callback") {  
        a[d] = function() {  
            //concat 连接两个数组  
            return c.apply(a, [d].concat(Array.prototype.slice.call(arguments, 0)))  
        }  
    }  
});  
b.HostApp = a;  
console.log("HostApp initialization end")  
 })(window);//闭包函数默认执行,然后赋给window。这样window.b就可以执行了 b.HostApp就是执行a的内容,但是a具体处理逻辑不对外开放,避免外部污染a内部逻辑  

代码不难,可以自行理解,其中回调函数被封装在了a对象里面,确保android 端可以通过webview.loadUrl()执行回调。

android端回调js代码如下:

javascript:HostApp.callback(0, 0 ,"call back haha");  

android 提供的每一个Js方法都对应一个JsCallBack对象。android就可以通过JsCallBack对象来生成并执行回调js的代码。

三、优缺点。

  • a第一种方式不安全,不添加addJavaScriptInterface,甚至默认为false,在低于API的webView上默认添加"SearchBoxJavaBridge_"到mJavaScriptObjects中。这样就有可能通过用户信任的客户端获取SD卡的数据。

  • b 第一种方式必须要API大于17才可以用。

  • c. 第一种方式当有js回调函数需要android端执行时,都需要将匿名回调函数赋值给全局函数才能供android端回调,增加了js和Android端通信的封装层的低效代码量;而第二种方式则是通过动态注入Js的方式则非常方便。

  • d 第二种方式也有一定的限制,比如android提供的方法必须是static修饰的。且方法第一个参数必须为webView,不过这不影响使用。

最后,附上代码地址:源码地址

面试的几个建议:

1.简历要如实写,相关的知识点一定要烂熟于心。
2.基础扎实,android和java相关的知识树网上有很多资料,看过但让你讲出来未必能说的好。
3.提前总结,你还擅长什么其他技术?这种开放问题要看知识面了。
4.学会提问,你有什么问题要问我吗?这种礼貌性问题也是一个了解对方的好机会。
5.良好的心里素质,无论遇到什么情况,面试官迟到、面试官态度冰冷说话不客气、质疑你的回答等等各种问题都不要慌也不要排斥,一定要沉住气,耐心积极的思考并回答对方的提问。
6.推荐几本书,也是好几次面试后发现里面涵盖了大部分答案。《Android开发艺术探索》《Android源码设计模式-解析与实战》《Android进阶之光》《深入理解Java虚拟机》,多看几遍。

大厂的面试流程比较长,面试是一场全面大考验,如果想换个工作,最好提前充分准备,最后,看到这里的人给你点个赞并有福利喽,下面的链接是对以上一些问题的答案的整理,以及一些其他的经典问题,链接:面试那些事。其中因为时间问题其他主题还没有开始动笔,并且引用了很多博客链接,希望相关博主不要介意。仅作为参考。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android WebView 是一个能够在 Android 应用程序中嵌入网页的组件,它可以开发出能够与 Web 页面进行交互应用。其中与 Web 页面进行交互的一种方法是与 JavaScript 进行交互。下面简要解释一下 Android WebViewJS 交互的方式。 1. 加载本地 HTML 文件 在 Android WebView 中加载本地 HTML 文件时,需要使用 loadUrl() 方法加载。HTML 文件中的 JavaScript 可以通过 WebView 提供的 addJavascriptInterface() 方法注册为 Java 中的一个对象,然后在 Java 中调用该对象的方法,即可实现 JS 与 Java 的交互。 2. 加载远程 Web 页面 在 Android WebView 中加载远程 Web 页面时,需要添加 WebViewClient 和 WebChromeClient,分别是用来管理 WebView 的网络请求和处理页面上的 JavaScript 弹窗等请求。 在远程 Web 页面上,JS 代码可以通过 WebView 提供的 addJavascriptInterface() 方法注册为 Java 中的一个对象,然后在 Java 中调用该对象的方法,即可实现 JS 与 Java 的交互。 同时,在 Android 中处理 JS 的事件需要通过 JavaScriptInterface 向 WebView 注册一个映射对象,来实现 JS、Java 相互调用的机制,静态 HTML 文件是通过 WebView 中的 evaluateJavascript() 方法来调用 JS,来实现双向通信和数据交互总结来说,Android WebViewJS 交互的方式主要是通过 WebView 提供的 addJavascriptInterface() 方法注册为 Java 中的一个对象,然后在 Java 中调用该对象的方法,来实现 JS 和 Java 的交互。同时,JS 也可以通过 WebView 的 evaluateJavascript() 方法来调用 Java 中的方法,实现双向通信和数据交互

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值