0


Android中使用WebView与JS交互全解析

在这里插入图片描述

1.概述

首先,需要提出一个概念,那就是hybrid,主要意思就是native原生Android和h5混合开发。为什么要这样做呢?大家可以想象一下针对于同一个活动,如果使用纯native的开发方式,Android和iOS两边都要维护同一套界面甚至是逻辑,这样开发和维护的成本会很大,而使用hybrid的开发方式的话,让前端的同学去写一套界面和逻辑,对于native端来说只要使用对应的容器去展示就可以了(对于Android来说这个容器当然就是WebView)。那为什么不所有的页面都使用这种方式开发呢?因为使用h5来展示界面的话用户体验始终是不如native的,所以在这两者之间我们需要一个权衡。

介绍完了何为hybrid,我们来思考下面几个场景: 场景1:前端那边的页面有一个按钮,点击这个按钮需要显示一个native的组件(比如一个toast),或者点击这个按钮需要去在native端执行一个耗时的任务。 场景2:还是前端页面有一个按钮,点击这个按钮的逻辑是:如果登录了,则跳转到相应的界面,如果没有登录,则跳转到登录界面。而这个登录界面是我们native维护的。 看完上面两个场景,相信大家也发现了一个问题,hybrid这样的开发方式有一个问题需要解决,那就是前端和本地的通信。 下面将会给大家介绍active原生Android和h5之间的通信方式。

2.如何使用WebView

使用WebView控件 与其他控件的使用方法相同 在layout中使用一个”WebView”标签 WebView不包括导航栏,地址栏等完整浏览器功能,只用于显示一个网页 在WebView中加载Web页面,使用loadUrl()

这里写图片描述

这里写图片描述

注意在manifest文件中加入访问互联网的权限:

1.<uses-permission android:name="android.permission.INTERNET"/>

但是,在Android中点击一个链接,默认是调用手机上已经安装的浏览器程序来启动,因此想要通过WebView代为处理这个动作 ,那么需要通过WebViewClient

这里写图片描述

这里写图片描述

当然,我们也可以写一个类继承WebViewClient来对WebViewClient对象进行扩展

这里写图片描述

这里写图片描述

然后只需要将setWebViewClient的内容进行修改即可

这里写图片描述

这里写图片描述

另外出于用户习惯上的考虑 需要将WebView表现得更像一个浏览器,也就是需要可以回退历史记录,因此需要覆盖系统的回退键 goBack,goForward可向前向后浏览历史页面

这里写图片描述

这里写图片描述

例子1:WebViewClient的使用 布局代码activity_main.xml:

1.<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"2.xmlns:tools="http://schemas.android.com/tools"3.android:layout_width="match_parent"4.android:layout_height="match_parent"5.android:paddingBottom="@dimen/activity_vertical_margin"6.android:paddingLeft="@dimen/activity_horizontal_margin"7.android:paddingRight="@dimen/activity_horizontal_margin"8.android:paddingTop="@dimen/activity_vertical_margin"9.tools:context="com.example.hybirddemo.MainActivity">10.11.<WebView
12.android:layout_width="match_parent"13.android:layout_height="match_parent"14.android:id="@+id/webView"/>15.16.</RelativeLayout>

MainActivity代码:

publicclassMainActivityextendsActivity{2.3.private WebView webView;4.5.      @Override
6.protectedvoidonCreate(Bundle savedInstanceState){7.super.onCreate(savedInstanceState);8.setContentView(R.layout.activity_main);9.10.// 获取webview控件11.         webView =(WebView)findViewById(R.id.webView);12.//设置WebViewClient13./*webView.setWebViewClient(new MyWebViewClient());*/14.//使用webview加载页面15.         webView.loadUrl("http://www.baidu.com");16.17.         webView.setWebViewClient(newWebViewClient(){18.19.             @Override
20.public boolean shouldOverrideUrlLoading(WebView view, String url){21.                 view.loadUrl(url);22.returntrue;23.}24.25.             @Override
26.publicvoidonPageStarted(WebView view, String url, Bitmap favicon){27.// TODO Auto-generated method stub28.super.onPageStarted(view, url, favicon);29.}30.31.             @Override
32.publicvoidonPageFinished(WebView view, String url){33.// TODO Aut (view, url);34.}35.36.});37.38.}39.40.     @Override
41.//覆盖系统的回退键42.public boolean onKeyDown(int keyCode, KeyEvent event){43.if(keyCode == KeyEvent.KEYCODE_BACK&& webView.canGoBack()){44.             webView.goBack();45.returntrue;46.}47.48.returnsuper.onKeyDown(keyCode, event);49.}50.51.}

3.JavaScript和java的相互调用

WebSetting用处非常大,通过WebSetting可以使用Android原生的JavascriptInterface来进行js和java的通信。 例子2:JavaScript和java的相互调用

首先我们写一段html代码:

1.<!DOCTYPE html>2.<html>3.<head>4.<title>MyHtml.html</title>5.6.<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">7.<meta http-equiv="description" content="this is my page">8.<meta http-equiv="content-type" content="text/html; charset=UTF-8">9.10.<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->11.<script type="text/javascript">12.functionshowToast(toast){13.javascript:control.showToast(toast);14.}15.functionlog(msg){16.         consolse.log(msg);17.}18.</script>19.</head>20.21.<body>22.<input type="button" value="toast" onclick="showToast('hello world!')">23.</body>24.</html>

这是一个很简单的html5页面,里面有一个button,点击这个button就执行js脚本中的showToast方法。

这里写图片描述

那么这个showToast方法做了什么呢?

这里写图片描述

可以看到control.showToast,这个是什么我们后面再说,下面看我们Android工程中的java代码。

编写布局文件activity_main.xml 布局的内容很简单,就是嵌套一个WebView控件

这里写图片描述

这里写图片描述

编写MainActivity.java代码

1.package com.example.hybirddemo;2.3.import android.annotation.SuppressLint;4.import android.app.Activity;5.import android.os.Bundle;6.import android.util.Log;7.import android.view.Menu;8.import android.view.MenuItem;9.import android.webkit.JavascriptInterface;10.import android.webkit.WebSettings;11.import android.webkit.WebView;12.import android.widget.Toast;13.14.publicclassMainActivityextendsActivity{15.16.private WebView webView;17.18.     @Override
19.protectedvoidonCreate(Bundle savedInstanceState){20.super.onCreate(savedInstanceState);21.setContentView(R.layout.activity_main);22.// 获取webview控件23.         webView =(WebView)findViewById(R.id.webView);24.// 获取WebView的设置25.         WebSettings webSettings = webView.getSettings();26.// 将JavaScript设置为可用,这一句话是必须的,不然所做一切都是徒劳的27.         webSettings.setJavaScriptEnabled(true);28.//给webview添加JavaScript接口29.         webView.addJavascriptInterface(newJsInterface(),"control");30.//通过webview加载html页面31.         webView.loadUrl("file:///android_asset/MyHtml.html");32.33.}34.publicclassJsInterface{35.          @JavascriptInterface
36.publicvoidshowToast(String toast){37.             Toast.makeText(MainActivity.this,toast , Toast.LENGTH_SHORT).show();38.             Log.d("html","show toast success");39.}40.publicvoidlog(final String msg){41.             webView.post(newRunnable(){42.43.                 @Override
44.publicvoidrun(){45.                     webView.loadUrl("javascript log("+"'"+msg+"'"+")");46.47.}48.});49.}50.}51.}

上面的代码主要做了以下的步骤: a) 获取webview控件 b) 获取webview的设置,将JavaScript设置为可用,打开JavaScript的通道

这里写图片描述

这里写图片描述

c) 在Android程序中建立接口 ,并编写相关逻辑 再去看之前js脚本中的那个showToast()方法

这里写图片描述

这里写图片描述

这里的control就是我们的那个interface,调用了interface的showToast方法,很明显这里是js调用了Android的代码,输出了一个Toast

这里写图片描述

可以看到这个interface我们给它取名叫control,最后通过loadUrl加载页面。

这里写图片描述

可以看到先显示一个toast,然后调用log()方法,log()方法里调用了js脚本的log()方法, js的log()方法做的事就是在控制台输出msg,这里明显是Android调用了js的方法。

这里写图片描述

d) 给webview添加我们自己编写的JavaScript接口 通过WebView的addJavascriptInterface方法去注入一个我们自己写的interface。

这里写图片描述

e) 使用webview控件加载我们之前编写的html文件

这里写图片描述

在真实手机上运行程序,在控制台成功输出内容:

这里写图片描述

这样我们就完成了js和java的互调,是不是很简单。

4.Android中处理JS的警告,对话框等

在Android中处理JS的警告,对话框等需要对WebView设置WebChromeClient对象,并复写其中的onJsAlert,onJsConfirm,onJsPrompt方法可以处理javascript的常用对话框 例子3:在Android中处理javascript的对话框****1) 编写html页面布局

1.<%@LANGUAGE="JAVASCRIPT"CODEPAGE="936"%>2.<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">3.<html xmlns="http://www.w3.org/1999/xhtml">4.<head>5.<meta http-equiv="Content-Type" content="text/html; charset=UTF-8 "/>6.<title>分别测试javascript的三种对话框</title>7.<script language="javascript">8.functionale()9.{10.alert("这是一个警告对话框!");11.}12.functionfirm()13.{14.if(confirm("更多信息请到我的博客去?"))15.{16.         location.href="http://yarin.javaeye.com";17.}18.else19.{20.alert("你选择了不去!");21.}22.}23.functionprom()24.{25.var str=prompt("演示一个带输入的对话框","这里输入你的信息");26.if(str)27.{28.alert("谢谢使用,你输入的是:"+ str)29.}30.}31.</script>32.</head>33.<body>34.<p>下面我们演示3种对话框</p>35.<p>警告、提醒对话框</p>36.<p>37.<input type="submit" name="Submit" value="提交" onclick="ale()"/>38.</p>39.<p>带选择的对话框</p>40.<p>41.<input type="submit" name="Submit2" value="提交" onclick="firm()"/>42.</p>43.<p>要求用户输入的对话框</p>44.<p>45.<input type="submit" name="Submit3" value="提交" onclick="prom()"/>46.</p>47.</body>48.</html>

页面效果:

这里写图片描述

2) Android中布局的编写

1.<?xml version="1.0" encoding="utf-8"?>2.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3.android:orientation="vertical"4.android:layout_width="fill_parent"5.android:layout_height="fill_parent"6.>7.<LinearLayout 
8.android:orientation="horizontal"9.android:layout_width="fill_parent"10.android:layout_height="fill_parent"11.android:animationCache="true"12.android:layout_weight="9">13.<EditText 
14.android:id="@+id/EditText01"15.android:layout_width="wrap_content"16.android:layout_weight="9"17.android:layout_height="wrap_content"18.android:text="请输入网址"/>19.<Button android:id="@+id/Button01"20.android:layout_width="wrap_content"21.android:layout_weight="1"22.android:layout_height="wrap_content"23.android:text="连接"/>24.</LinearLayout>25.<WebView 
26.android:id="@+id/WebView01"27.android:layout_width="fill_parent"28.android:layout_height="fill_parent"29.android:layout_weight="1"30./>31.</LinearLayout>

3) 编写自定义对话框的布局 新建prom_dialog.xml文件,在其中自定义一个带输入的对话框由TextView和EditText构成

1.<?xml version="1.0" encoding="utf-8"?>2.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"3.android:gravity="center_horizontal"4.android:orientation="vertical"5.android:layout_width="fill_parent"6.android:layout_height="wrap_content"7.>8.<TextView 
9.android:id="@+id/TextView_PROM"10.android:layout_width="fill_parent"11.android:layout_height="wrap_content"/>12.<EditText 
13.android:id="@+id/EditText_PROM"14.android:layout_width="fill_parent"15.android:layout_height="wrap_content"16.android:selectAllOnFocus="true"17.android:scrollHorizontally="true"/>18.</LinearLayout>

4) 获取WebView控件,并进行相关的设置

这里写图片描述

5) 复写onKeyDown方法,当用户按返回键时,返回上一个加载的页面

这里写图片描述

6) 给WebView设置setWebChromeClient,并复写其中的方法

1.// 设置WebChromeClient2.          mWebView.setWebChromeClient(newWebChromeClient(){3.4.              @Override
5.// 处理javascript中的alert6.public boolean onJsAlert(WebView view, String url, String message,7.                      final JsResult result){8.// 构建一个Builder来显示网页中的对话框9.                  Builder builder =newBuilder(MainActivity.this);10.                 builder.setTitle("提示对话框");11.                 builder.setMessage(message);12.                 builder.setPositiveButton(android.R.string.ok,13.newAlertDialog.OnClickListener(){14.15.                             @Override
16.publicvoidonClick(DialogInterface dialog,17.                                     int which){18.// TODO Auto-generated method stub19.// 点击确定按钮之后,继续执行网页中的操作20.                                 result.confirm();21.}22.});23.                 builder.setNegativeButton(android.R.string.cancel,24.newOnClickListener(){25.26.                             @Override
27.publicvoidonClick(DialogInterface dialog,28.                                     int which){29.                                 result.cancel();30.31.}32.});33.                 builder.setCancelable(false);34.                 builder.create();35.                 builder.show();36.37.returntrue;38.39.}40.41.             @Override
42.//处理javascript中的confirm43.public boolean onJsConfirm(WebView view, String url,44.                     String message, final JsResult result){45.                 Builder builder =newBuilder(MainActivity.this);46.                 builder.setTitle("带选择的对话框");47.                 builder.setMessage(message);48.                 builder.setPositiveButton(android.R.string.ok,49.newAlertDialog.OnClickListener(){50.publicvoidonClick(DialogInterface dialog, int which){51.                                 result.confirm();52.}53.});54.                 builder.setNegativeButton(android.R.string.cancel,55.newDialogInterface.OnClickListener(){56.publicvoidonClick(DialogInterface dialog, int which){57.                                 result.cancel();58.}59.});60.                 builder.setCancelable(false);61.                 builder.create();62.                 builder.show();63.returntrue;64.}65.66.             @Override
67.// 处理javascript中的prompt68.// message为网页中对话框的提示内容69.// defaultValue在没有输入时,默认显示的内容70.public boolean onJsPrompt(WebView view, String url, String message,71.                     String defaultValue, final JsPromptResult result){72.// 自定义一个带输入的对话框由TextView和EditText构成73.                 LayoutInflater layoutInflater = LayoutInflater
74..from(MainActivity.this);75.                 final View dialogView = layoutInflater.inflate(76.R.layout.prom_dialog,null);77.78.// 设置TextView对应网页中的提示信息79.((TextView) dialogView.findViewById(R.id.TextView_PROM))80..setText(message);81.// 设置EditText对应网页中的输入框82.((EditText) dialogView.findViewById(R.id.EditText_PROM))83..setText(defaultValue);84.//构建一个Builder来显示网页中的对话框  85.                 Builder builder =newBuilder(MainActivity.this);86.//设置弹出框标题87.                 builder.setTitle("带输入的对话框");88.//设置弹出框的布局89.                 builder.setView(dialogView);90.//设置按键的监听91.                 builder.setPositiveButton(android.R.string.ok,92.newAlertDialog.OnClickListener(){93.94.                             @Override
95.publicvoidonClick(DialogInterface dialog,96.                                     int which){97.98.// 点击确定之后,取得输入的值,传给网页处理99.                                 String value =((EditText) dialogView
100..findViewById(R.id.EditText_PROM))101..getText().toString();102.                                    result.confirm(value);103.}104.105.});106.107.                    builder.setNegativeButton(android.R.string.cancel,108.newOnClickListener(){109.110.                                @Override
111.publicvoidonClick(DialogInterface dialog,112.                                        int which){113.// TODO Auto-generated method stub114.                                    result.cancel();115.}116.});117.118.                    builder.setOnCancelListener(newDialogInterface.OnCancelListener(){119.publicvoidonCancel(DialogInterface dialog){120.                            result.cancel();121.}122.});123.                    builder.show();124.returntrue;125.}126.127.                @Override
128.//设置网页加载的进度条129.publicvoidonProgressChanged(WebView view, int newProgress){130.                    MainActivity.this.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, newProgress *100);131.super.onProgressChanged(view, newProgress);132.}133.134.                @Override
135.publicvoidonReceivedTitle(WebView view, String title){136.                    MainActivity.this.setTitle(title);137.super.onReceivedTitle(view, title);138.}139.140.});141.            mButton.setOnClickListener(newView.OnClickListener(){142.143.                @Override
144.publicvoidonClick(View v){145.//取得编辑框中我们输入的内容146.                    String url = mEditText.getText().toString().trim();147.//判断输入的内容是不是网址148.if(URLUtil.isNetworkUrl(url)){149.//装载网址150.                        mWebView.loadUrl(url);151.}else{152.                        mEditText.setText("输入网址错误,请重新输入");153.}154.}155.});156.157.}

这里写图片描述

图1 dialog.html页面

这里写图片描述

图2 javascript的警告对话框

这里写图片描述

图3 javascript的confirm对话框

这里写图片描述

图4 javascript的prompt对话框

总结:在这个项目中,使用setWebChromeClient方法来为WebView设置一个WebChromeClient对象,来辅助WebView来处理Javascript的对话框等,图4是我们自定义的对话框,图2和图3我们都只需要监听按钮的点击事件,然后通过confirm和cancel方法将我们的操作传递给Javascript进行处理。当你在图1的界面,点击第一个按钮时,会打开图2的对话框,点击第二个按钮时,会打开图3的对话框,同时在这里点击确定,会跳转到另一个页面,当点击第三个按钮时,会打开图4对话框,并且可以输入内容。

更多Android进阶指南 可以扫码 解锁****《Android十大板块文档》


1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2023最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔


本文转载自: https://blog.csdn.net/Coo123_/article/details/134028524
版权归原作者 Android小安 所有, 如有侵权,请联系我们删除。

“Android中使用WebView与JS交互全解析”的评论:

还没有评论