android 添加js对象吗,Android和JS的交互

现在很多App为了降低开发成本和维护成本,都会内置Web网页,在安卓端是通过WebView来实现的,这就要求我们开发人员具备Android和JS交互的开发能力。

我将通过这篇文章来记录我的学习历程,在学习过程中我还是通过一个demo来加深理解,下面先贴上效果图:

3e0bfc87fb75

安卓与js的交互

效果图分别展示了js调用安卓方法的三种效果以及安卓调用js方法的两种效果,下面我把这五个方法拆开来单个学习理解。

一、先介绍一下安卓调用js方法的两种实现方式 :

1、通过webview对象调用方法loadUrl(),这样可以实现安卓调用js的方法;

2、通过webview对象调用方法evaluateJavascript(),实现安卓调用js方法。

下面从代码来具体看这两种方法的实现过程:

先贴上html文件:

安卓与js交互

function callJS1(){

alert("安卓调用JS中的callJs方法");

}

这是一个webview

这里为了代码看起来清晰明了,只放了需要的部分。代码中只放了一个功能供安卓调用。下面是安卓端的代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private WebView mWebView;

private Button mBtn1,mBtn2;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initView();

configWebview();

}

@SuppressLint("SetJavaScriptEnabled")

private void configWebview() {

WebSettings settings = mWebView.getSettings();

//允许与js交互

settings.setJavaScriptEnabled(true);

//允许js弹窗

settings.setJavaScriptCanOpenWindowsAutomatically(true);

//加载html文件

mWebView.loadUrl("file:///android_asset/javascript.html");

mWebView.setWebChromeClient(new WebChromeClient(){

//这里的参数message就是html文件中callJS1()方法下alert中的文本

@Override

public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {

//创建一个弹窗

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

builder.setTitle("安卓与JS交互");

builder.setMessage(message);

builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int which) {

result.confirm();

}

});

builder.setCancelable(false);

builder.create().show();

return true;

}

}

private void initView() {

mWebView = findViewById(R.id.webview);

mBtn1 = findViewById(R.id.btn1);

mBtn2 = findViewById(R.id.btn2);

mBtn1.setOnClickListener(this);

mBtn2.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch(v.getId()){

case R.id.btn1:

//通过loadUrl()方法调用JS的方法

getMethodByLoadUrl();

break;

}

}

private void getMethodByLoadUrl() {

mWebView.post(new Runnable() {

@Override

public void run() {

//这种方法调用js的方法没有返回值

mWebView.loadUrl("javascript:callJS1()");

}

});

}

}

安卓和js交互的中间桥梁就是安卓中的控件WebView,其对象一边绑定html文件,一边和安卓系统交互,这样就连接起了安卓和js。

通过WebView的对象调用方法getSettings()获取WebSettings对象,从对象名称就能看出这个类是来设置WebView一些属性的:

WebSettings settings = mWebView.getSettings();

拿到WebSettings对象后,通过以下代码设置安卓系统和js交互的权限:

settings.setJavaScriptEnabled(true);

webview中经常有一些弹窗,我们可以通过以下代码来设置js弹窗的权限:

settings.setJavaScriptCanOpenWindowsAutomatically(true);

WebView是一个View,我们就可以加载之前写好的html文件,WebView可以自动完成对页面的渲染:

mWebView.loadUrl("file:///android_asset/javascript.html");

我这里是加载的工程下assets文件下的一个本地html文件,在实际开发中将url更换成远程的就可以。

在这个方法中因为没有去获取返回值,所以设置了一个弹窗来检验安卓调用js方法的结果,所以在设置WebView属性的时候设置了同意js弹窗的权限,即settings.setJavaScriptCanOpenWindowsAutomatically(true);,这里WebView只是一个View,一扇窗户(载体),里面的窗花(弹窗)需要我们自己去定义,WebView给我们提供了方法去处理js中弹窗,就是setWebChromeClient()方法,创建弹窗的方法就是原生安卓的方法,下面贴上代码:

mWebView.setWebChromeClient(new WebChromeClient(){

//这里的参数message就是html文件中callJS1()方法下alert中的文本

@Override

public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {

//创建一个弹窗

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

builder.setTitle("安卓与JS交互");

builder.setMessage(message);

builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int which) {

result.confirm();

}

});

builder.setCancelable(false);

builder.create().show();

return true;

}

}

好了,以上就是安卓调用js方法的第一种方式,用WebView提供的方法loadUrl()实现。

由于第一种方法存在一个缺点就是,安卓无法高效的获取到返回值,所以在Android4.4以后安卓系统提供了第二种方法,就是用WebView提供的方法evaluateJavaScript()来实现安卓调用js的方法,这种方法能直接获取到返回值,相较于第一种比较高效,下面来看看第二种方法的实现:

html部分代码:

function callJS2(){

return "js返回的数据";

}

这部分js功能中,我只返回了一个值,目的就是校验第二种方法获取返回值。

安卓端部分代码:

mWebView.evaluateJavascript("javascript:callJS2()", new ValueCallback() {

@Override

public void onReceiveValue(String value) {

//js返回值处理

tipString(value);

}

});

从代码中看出,第二种方法传入了两个参数,第一个参数对应js中的方法,第二个参数是一个回调对象,并且重写了一个方法,方法中包含一个String类型参数,这个参数就是js方法中返回的值。

上面学习了安卓调用js方法的两种方式,下面做个总结:

第一种方法比较方便简洁,但是获取返回值比较繁琐,需要js再去调用安卓的方法将返回值传过来,这样效率很低;

第二种方法能够获取到js的返回值,但是只支持Android4.4以上的设备,向下兼容性比较差。

综于以上总结,在实际开发中 ,为了兼容各个版本,我们可以在Android4.4以前的系统使用方法一,在4.4以上的用方法二。

二、学习完了安卓调用js的方法,下面来学习js调用安卓的方法,先简单介绍实现js调用安卓方法的三种方式:

`1、通过WebView对象调用方法addJavascriptInterface()将安卓对象映射成一个字符串,这样就可以在js中通过这个字符串调用安卓中的方法;

2、安卓端通过WebViewClient的shouldOverrideUrlLoading ()方法回调拦截url,然后解析url的协议,判断是否和预先约定好的一致,做出相应的操作;

3、安卓端通过WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt()消息.

下面来逐个学习,先贴上html文件 :

安卓与js交互

function callAndroid1(){

android.test("js调用了安卓的test方法");

}

function callAndroid2(){

document.location="js://webview?name=张三&age=24";

}

function callAndroid3(){

var result=prompt("js://android?name=李四&age=24");

alert(result);

}

这是一个webview

点击调用安卓的方法1

点击调用安卓的方法2

点击调用安卓的方法3

代码中定义了三个js方法,分别是callAndroid1()、callAndroid2()和callAndroid3(),还有三个按钮,点击的时候分别去调用三个方法,下面看看安卓端的代码是怎么实现js和安卓的交互的:

首先,第一个方法是映射一个安卓对象,所以需要先创建一个类,里面包含供js调用的方法:

public class Android {

private Context context;

Android(Context context) {

this.context = context;

}

@JavascriptInterface

public void test(String msg){

Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();

}

}

建好了类,定义好了供js调用的方法后,通过如下代码完成安卓对象的映射:

mWebView.addJavascriptInterface(new Android(this),"android");

以上代码将安卓对象映射成android,所以在html文件中就有android.test("js调用了安卓的test方法");,到了这就完成了js对安卓方法的调用。

不过这里需要注意一点:这种方法在Android4.2以前存在漏洞,就是映射之后这个类中所有的方法都会暴漏在js中,当有些方法我们是不希望js能够调用到的时候,这个时候就存在安全威胁,所以在4.2以后 ,安卓系统让能够被js调用的方法加上注释@JavascriptInterface。

学习完了第一种方式,下面学习第二种方式,html文件和第一种差不多,上面已经给出,这里直接贴上安卓端的处理部分代码:

mWebView.setWebViewClient(new WebViewClient(){

@Override

public boolean shouldOverrideUrlLoading(WebView view, String url) {

Uri uri = Uri.parse(url);

if (uri.getScheme() != null && uri.getScheme().equals("js")) {

if (uri.getAuthority() != null && uri.getAuthority().equals("webview")) {

Set names = uri.getQueryParameterNames();

// tip(names);

//调用Android中的方法

tipString(uri.getQueryParameter("name"));

}

//处理完了记得return 不然会出错

return true;

}

return super.shouldOverrideUrlLoading(view, url);

}

});

代码中WebViewClient通过shouldOverrideUrlLoading拦截url,并转换成uri,然后获取url的协议,即uri.getScheme()和uri.getAuthority(),然后判断是否和事先约定好的一致,当一致的时候再来做出相应的操作,在这里我是将拼接在url的参数取出来并显示在屏幕上。

上面就是第二种方式的实现过程,他不存在第一种方法那样的漏洞,但是也存在一个缺点 ,因为这种方法是通过拦截url,然后判断协议的方式来调用安卓方法的,在js将url传递过来后,安卓就失去了和js的通信,所以它也存在和安卓通过loadUrl()调用js方法一样的缺点,就是无法高效获取返回值,要想取得返回值,只能让安卓再去调用js的方法将返回值传递给js,这样效率明显不理想,所以在一些不需要返回值的交互场景中推荐这种方法 。

接下来学习第三种方式,这里只是学习了输入框,另外的警告框和确认框差不多的。

安卓端的处理部分代码:

@Override

public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {

Uri uri = Uri.parse(message);

if (uri.getScheme() != null && uri.getScheme().equals("js")) {

if (uri.getAuthority() != null && uri.getAuthority().equals("android")) {

//通过这个方法将安卓中的数据返回到js中去

result.confirm("JS调用安卓的方法");

}

//处理完了记得return 不然会出错

return true;

}

return super.onJsPrompt(view, url, message, defaultValue, result);

}

这种方法和第二种差不多,都是判断url的协议,然后根据判断的结果做出相应的操作,它和第二种方法的区别就是第三种方法js能够获取到返回值,因为js中警告框、确认框和输入框这三种弹框都有返回值,并且都能监听到选择或是输入的结果。这也使得第三种方法能满足大多数场合。

好了 ,以上就是对js调用安卓方法三种实现方式的学习,这里总结以下:

第一种方法方便简洁,但在Android4.2以前存在漏洞,4.2以后的场合可以 考虑这种方法;

第二种方法不存在漏洞了,但是url的协议判断过程相对来说复杂,而且获取返回值也比较复杂,不需要返回值的场合可以考虑用这种方法;

第三种方法不存在漏洞,判断url协议和第二种方法一样,但这种方法能获取到返回值,所以第三种方法能满足大多数场合。

以上就是本人对Android和JS交互的学习,希望发现文中有不当之处的朋友们能够指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值