WebView与JS的交互

支架 2024-06-29 10:03:03 阅读 86

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

一、WebView与JS各自的含义二、WebView与JS的交互方式1.Android调用JS方法(2种方式)2.JS调用Android方法(3种方式)第一种方式`WebView.addJavascriptInterface()`的实现步骤第二种方式`WebViewClient.shouldOverrideUrlLoading ()`的实现步骤第三种方式`WebChromeClient`的实现步骤


一、WebView与JS各自的含义

WebView在安卓中出现并不少见,尤其是需要访问网页的时候,如在APP上点击链接JS就是编写前端页面的代码,也就是网页的UI内容

像之前刚接触安卓的时候,没少看到安卓与JS交互写的一些方法代码,当时都是应付性的学习理解一下,并没有深入的学习和理解,所以今天趁着再一次学习, 把自己学的一些微小的见解写在博客上,方便后续学习。

二、WebView与JS的交互方式

大家如果想深入学习,可以看这一篇博客,内容更加具体,且下面图片出自该处

图片来源

注:AndroidJS的交互是可以通过本地文件和远程url的形式,而本文是采用Andorid调用本地JS代码说明;实际情况时,Android更多的是调用远程JS代码,即将加载的JS代码路径改成url即可

1.Android调用JS方法(2种方式)

:因为webViewAndroid的控件之一,所以这样写成AndroidJS的交互,而webview算是它们二者交互的桥梁。

第一种方式:WebView.loadUrl()

webView.loadUrl("javascript:callJS()")//当前是加载本地资源

第二种方式:WebView.evaluateJavascript()(比第一种更加高效)

// 只需要将第一种方法的loadUrl()换成下面该方法即可

mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {

@Override

public void onReceiveValue(String value) {

//此处为 js 返回的结果

}

});

}

两种加载方式对比:

在这里插入图片描述

步骤1:编写本地的html文件javascript.html

在这里插入图片描述

javascript.html内容如下:

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8"> //注意结尾后面不需要斜杠 /

<title>CXJ</title>

//JS代码

<script>

function callJS(){

alert("Android调用了JS的callJS方法");

}

</script>

</head>

</html>

步骤2:布局文件:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity"

android:orientation="vertical">

<Button

android:text="点击我"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:id="@+id/button"/>

<WebView

android:layout_width="match_parent"

android:layout_height="match_parent"

android:id="@+id/webview"/>

</LinearLayout>

步骤3:编写关键代码

//1.3先加载JS代码 规定格式:file:///android_asset/文件名.html

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

注意:file:///android_asset/文件名.html 是加载本地JS文件的规定格式

//方法名要对应javascript.html文件里面的 callJS()函数

webView.loadUrl("javascript:callJS()");

完整的代码:

public class MainActivity extends AppCompatActivity {

WebView webView;

Button button;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

webView = findViewById(R.id.webview);

button=findViewById(R.id.button);

//1.开始设置web View相关设置

WebSettings webSettings=webView.getSettings();

//1.1允许与JS发生交互

webSettings.setJavaScriptEnabled(true);

//1.2允许设置JS弹窗

webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

//1.3先加载JS代码 规定格式:file:///android_asset/文件名.html

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

//2.点击事件

button.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

webView.post(new Runnable() {

@Override

public void run() {

//第一种方式加载

//方法名要对应 callJS()

// webView.loadUrl("javascript:callJS()");

//第二种方式加载

// webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {

// @Override

// public void onReceiveValue(String s) {

// Log.d("TAG", "js返回的结果: "+s);

// }

// });

//兼容上下版本更改的方式加载

// Android版本变量

final int version = Build.VERSION.SDK_INT;

// 因为该方法在 Android 4.4 版本才可使用,所以使用时需进行版本判断

if (version < 18) {

webView.loadUrl("javascript:callJS()");

} else {

webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {

@Override

public void onReceiveValue(String s) {

Log.d("TAG", "js返回的结果: "+s);

}

});

}

}

});

}

});

//webView只是载体,内容的渲染需要使用webViewChromeClient类去实现 设置响应JS的Alert()函数

webView.setWebChromeClient(new WebChromeClient(){

@Override

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

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

builder.setTitle("Alert");

builder.setMessage(message);

builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialogInterface, int i) {

result.confirm();

}

});

builder.setCancelable(false);

builder.create().show();

return true;

}

});

}

}

2.JS调用Android方法(3种方式)

第一种方式:WebView.addJavascriptInterface()

第二种方式:WebViewClient.shouldOverrideUrlLoading ()

第三种方式:WebChromeClient.addJavascriptInterface()

在这里插入图片描述

第一种方式WebView.addJavascriptInterface()的实现步骤

步骤1:编写给JS调用的安卓方法类AndroidToJs

/**

1. 定义给JS调用的安卓方法

*/

public class AndroidToJs extends Object{

//定义给JS调用的安卓方法——且必须加上JavascriptInterface

@JavascriptInterface

public void hello(String msg){

System.out.println("JS调用安卓的Hello方法");

}

}

步骤2:将本地JS文件格式放到src/main/assets文件夹里

在这里插入图片描述

javascript2.html内容如下

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>CXJ</title>

<script>

function callAndroid(){

// 由于对象映射,所以调用test对象等于调用Android映射的对象

test.hello("js调用了android中的hello方法");

}

</script>

</head>

<body>

//点击按钮则调用callAndroid函数 这一段代码是在JS界面设置好的,不需要在安卓的布局里面添加Button控件

<button type="button" id="button1" onclick="callAndroid()"></button>

</body>

</html>

步骤3:在Android里通过WebView设置Android类与JS代码的映射

关键代码:

//2.通过addJavascriptInterface将Java映射到JS对象 参数1:javascript对象名 参数2:Java对象名

webView.addJavascriptInterface(new AndroidToJs(),"test");

注:参数1:javascript对象名(提供给JS调用的类名) 参数2:javascript2.html里面的对象

在这里插入图片描述

完整的代码:

public class JSUseAndroid extends AppCompatActivity {

WebView webView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_jsuse_android);

webView = findViewById(R.id.webview);

//1.开始设置web View相关设置

WebSettings webSettings=webView.getSettings();

//1.1允许与JS发生交互

webSettings.setJavaScriptEnabled(true);

//2.通过addJavascriptInterface将Java映射到JS对象 参数1:javascript对象名 参数2:Java对象名

webView.addJavascriptInterface(new AndroidToJs(),"test");

//3.加载JS代码

webView.loadUrl("file:///android_asset/javascript2.html");

}

}

效果展示:

在这里插入图片描述

第二种方式WebViewClient.shouldOverrideUrlLoading ()的实现步骤

原理Android通过 WebViewClient的回调方法shouldOverrideUrlLoading ()拦截 url并解析该 url 的协议,如果检测到是预先约定好的协议,就调用相应方法。

步骤1:在JS约定所需要的Url协议JS代码:javascript.html

在这里插入图片描述

步骤2:在Android通过WebViewClient复写shouldOverrideUrlLoading()

关键代码:

//3.复写WebViewClient类的shouldOverrideUrlLoading方法

webView.setWebViewClient(new WebViewClient(){

@Override

public boolean shouldOverrideUrlLoading(WebView view, String url) {

//3.1根据协议的参数,判断是否是所需要的url格式

//TODO 一般根据scheme(协议格式) & authority(协议名) 判断(前两个参数) "js://webview?arg1=111&arg2=222"

Uri uri=Uri.parse(url);

//3.2如果协议等于预先约定的js协议,则往下解析参数

if (uri.getScheme().equals("js")){

//3.3如果authority=预先约定好的webview,则表示都符合约定

if (uri.getAuthority().equals("webview")){

System.out.println("js调用了Android的方法");

//后续需要

HashMap<String,String> params=new HashMap<>();

Set<String> collection=uri.getQueryParameterNames();//获取 Uri 中的所有查询参数名称,并存储在 Set 集合中

}

return true;

}

return super.shouldOverrideUrlLoading(view, url);

}

});

uri.getScheme()对应的是约定协议约定的url协议为:js://webview?arg1=111&arg2=222js 部分 ,而 uri.getAuthority()对应的是webview

完整的代码:

public class JSUseAndroid2 extends AppCompatActivity {

WebView webView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_jsuse_android2);

webView = findViewById(R.id.webview);

//1.开始设置web View相关设置

WebSettings webSettings=webView.getSettings();

//1.1允许与JS发生交互

webSettings.setJavaScriptEnabled(true);

//2.加载JS代码

webView.loadUrl("file:///android_asset/javascript3.html");

//3.复写WebViewClient类的shouldOverrideUrlLoading方法

webView.setWebViewClient(new WebViewClient(){

@Override

public boolean shouldOverrideUrlLoading(WebView view, String url) {

//3.1根据协议的参数,判断是否是所需要的url格式

//TODO 一般根据scheme(协议格式) & authority(协议名) 判断(前两个参数) "js://webview?arg1=111&arg2=222"

Uri uri=Uri.parse(url);

//3.2如果协议等于预先约定的js协议,则往下解析参数

if (uri.getScheme().equals("js")){

//3.3如果authority=预先约定好的webview,则表示都符合约定

if (uri.getAuthority().equals("webview")){

System.out.println("js调用了Android的方法");

//后续需要

HashMap<String,String> params=new HashMap<>();

Set<String> collection=uri.getQueryParameterNames();//获取 Uri 中的所有查询参数名称,并存储在 Set 集合中

}

return true;

}

return super.shouldOverrideUrlLoading(view, url);

}

});

}

}

效果展示:

在这里插入图片描述

第三种方式WebChromeClient的实现步骤

有三种形式

WebChromeClient.onJsAlert()WebChromeClient.onJsConfirm()WebChromeClient.onJsPrompt()

在这里插入图片描述

步骤1:在JS约定所需要的Url协议JS代码:javascript.html

在这里插入图片描述

步骤2:在Android通过WebChromeClient复写onJsPrompt()

关键代码:

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

//3.1根据协议的参数,判断是否是所需要的url格式

//TODO 一般根据scheme(协议格式) & authority(协议名) 判断(前两个参数) "js://webview?arg1=111&arg2=222"

Uri uri=Uri.parse(message);//TODO 这样传入的是promt()的内容

//3.2如果协议等于预先约定的js协议,则往下解析参数

if (uri.getScheme().equals("js")){

//3.3如果authority=预先约定好的webview,则表示都符合约定

if (uri.getAuthority().equals("demo")){

System.out.println("js调用了Android的方法");

//后续需要

HashMap<String,String> params=new HashMap<>();

Set<String> collection=uri.getQueryParameterNames();//获取 Uri 中的所有查询参数名称,并存储在 Set 集合中

//参数result:代表消息框的返回值(输入值)

result.confirm("js调用Android方法成功啦");

}

return true;

}

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

}

完整代码:

public class JSuseAndroid3 extends AppCompatActivity {

WebView webView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_jsuse_android3);

webView = findViewById(R.id.webview);

//1.开始设置web View相关设置

WebSettings webSettings=webView.getSettings();

//1.1允许与JS发生交互

webSettings.setJavaScriptEnabled(true);

//1.2 允许设置JS弹窗

webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

//2.加载JS代码

webView.loadUrl("file:///android_asset/javascript4.html");

//3.复写

webView.setWebChromeClient(new WebChromeClient(){

//拦截输入框 参数message:代表promt()的内容(不是url) 参数result:代表输入框的返回值

@Override

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

//3.1根据协议的参数,判断是否是所需要的url格式

//TODO 一般根据scheme(协议格式) & authority(协议名) 判断(前两个参数) "js://webview?arg1=111&arg2=222"

Uri uri=Uri.parse(message);//TODO 这样传入的是promt()的内容

//3.2如果协议等于预先约定的js协议,则往下解析参数

if (uri.getScheme().equals("js")){

//3.3如果authority=预先约定好的webview,则表示都符合约定

if (uri.getAuthority().equals("demo")){

System.out.println("js调用了Android的方法");

//后续需要

HashMap<String,String> params=new HashMap<>();

Set<String> collection=uri.getQueryParameterNames();//获取 Uri 中的所有查询参数名称,并存储在 Set 集合中

//参数result:代表消息框的返回值(输入值)

result.confirm("js调用Android方法成功啦");

}

return true;

}

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

}

//拦截JS的警告框

@Override

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

return super.onJsAlert(view, url, message, result);

}

//拦截JS的确认框

@Override

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

return super.onJsConfirm(view, url, message, result);

}

});

}

}

效果图:

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。