Android 原生 WebView 与 JavaScript 交互

如今的纯原生的 APP 不多见了,几乎都是原生中嵌者网页的 hybird APP,或者直接使用 React Native 开发。原生 App 中嵌者网页原生与网页中 JavaScript 的交互几乎没法避免,毕竟在本身的应用中嵌入网页不仅是想让应用当个浏览器用。
Android 原生中加载网页的控件是 WebView,所以要想原生与 JavaScript 交互也同样必须经过 WebView 来实现。javascript

相关类和主要方法

WebView

低版本和高版本的 Android 系统中 WebView 采用不一样的内核, Android 4.4 以后直接使用了 Chrome 的内核。
经常使用方法:html

//根据 url 去加载一个网页
webView.loadUrl(String url);

//根据 HTML 数据显示出内容,其中 loadData() 方法的 data 中不能出现英文的 %,#,\,? 四个字符,不然可能会报错
webView.loadData(String data,String mimeType,String encoding);
webView.loadDataWithBaseUrl(String baseUrl,String mimeType,String encoding,String historyUrl);

// webView 处于激活状态,能正常加载和响应网页
webView.onResume();

// webView 处于暂停状态,当页面失去焦点切换到后台时调用
// 处于 pause 状态的 WebView 会中止动画和计算,可是不会中止 JavaScript 的执行
webView.onPause();

//暂停全部 WebView 的 layout、parsing、JavaScriptTimers 以下降 CPU 消耗(全局有效)
webView.pauseTimers();

// 恢复 pauseTimers 的暂停状态
webView.resumeTimers();

// 销毁一个 WebView 时要先将 WebView 和当前界面解绑再销毁
parentLayout.removeView(webView);
webView.destroy();

// 判断网页是否能够后退(能够实现监听,当网页能够后退事点击返回键和返回按钮不退出浏览界面)
webView.canGoBack();

//后退网页
webView.goBack();

// 判断网页是否能够前进
webView.canGoForward();

//前进网页
webView.goForward();

//以当前页为起点前进后退 steps 个页面(正数前进,负数后退)
webView.goBackOrForward(int steps);复制代码

WebSetting

WebSetting 是为 WebView 提供配置和管理的一个抽象类,它经过 webView.getSettings() 方法获取实例。
经常使用方法:前端

// 设置 webView 是否支持 JavaScript 的调用(应用中涉及原生与 JS 交互的必须设置为 true)
webSettings.setJavaScriptEnabled(true);

// 设置是否容许 JS 开启新窗口(function window.open())
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

// 设置 webView 是否支持插件
webSettings.setPluginsEnable(true);

// 设置编码方式

// 设置是否自适应屏幕,(通常图片和网页缩放同时使用)
webSettings.setUseWideViewPort(true); //将图片调整到适合 webView 的大小
webSettings.setLoadWithOverviewMode(true); //缩放至屏幕的大小(显示未作移动端兼容的 PC 网页)

// 设置是否支持缩放,默认为支持
webSettings.setSupportZoom(true);
// 设置内置的缩放控件
webSettings.setBuiltInZoomControls(true);
// 隐藏原生的缩放控件
webSettings.setDisplayZoomControls(true);复制代码

WebViewClient

WebViewClient 主要用来帮助 WebView 处理请求的各类状态事件。
经常使用方法:java

// 页面开始加载的时候回调
onPageStarted(WebView view, String url, Bitmap favicon);
// 页面加载结束时回调
onPageFinished(WebView view, String url);
// 将要加载资源时回调,每次资源的加载都会调用
onLoadResource(WebView view, String url);
// 加载的页面 404 时将会回调
onReceivedError(WebView view, WebResourceRequest request, WebResourceError error);复制代码

webView 默认状况下是不会加载 https 请求的,页面将显示空白,若是加载 https 页面须要进行以下设置:git

webView.setWebViewClient(new WebViewClient() {    
        @Override    
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {    
            handler.proceed();    //表示等待证书响应
        // handler.cancel(); //表示挂起链接,为默认方式
        // handler.handleMessage(null); //可作其余处理
        }    
    });复制代码

WebChromeClient

辅助 WebView 处理 JavaScript 对话框,加载进度,网页图标等。
经常使用方法:github

// 加载进度回调
onProgressChanged(WebView view, int newProgress);
// 获取到网页 Title 回调
onReceivedTitle(WebView view, String title);
// 获取到网页图标回调
onReceivedIcon(WebView view, Bitmap icon);复制代码

WebView 的使用

经过前面的了解,WebView 及他的辅助类的一些基本方法咱们是知道了,接下来就看一下一下怎么使用 WebView 以及怎样经过 WebView 让 Android 源生代码与 JavaScript 代码进行交互。web

JS 调用原生方法

JS 调用源生的方法时该方法必需要加上 @JavascriptInterface 注解,咱们能够定义一个类或者接口来单独存放用于 JS 调用的方法,这里我以接口为例。接口中提供一个 getUrl(String url) 方法用于提供给 JS 调用,传递一个 String 类型的值给源生方法:chrome

/** * Created by PandaQ on 2017/3/22. * JS 接口方法定义 * 接口中定义方法时不用加注解,使用时才加注解 */
public interface JavaScriptFunction {
    void getUrl(String string);
}复制代码
// 此代码片断为 PandaEye 中点击加载的 html 数据中的图片跳转到新的 Activity 显示图片的功能
webView.addJavascriptInterface(new JavaScriptFunction() {
            @Override
            @JavascriptInterface // 加上注解 getUrl() 方法才能被 JS 调用
            public void getUrl(String imageUrl) {
                LogWritter.LogStr(imageUrl);
                Intent intent = new Intent();
                intent.putExtra("imageUrls", mImageUrls);
                intent.putExtra("curImageUrl", imageUrl);
                intent.setClass(ZhihuStoryInfoActivity.this, PhotoViewActivity.class);
                startActivity(intent);
            }
        }, "JavaScriptFunction");复制代码
// 在 HTML 中图片的点击事件 JS 方法中就能够执行以下代码来调用源生的接口方法
function(){
    window.JavaScriptFunction.getUrl(this.src);
}复制代码

原生调用 JS

在熊猫眼 PandaEye 中由于使用的知乎日报和网易新闻的 API 因此下发的 HTML body 数据须要咱们本身加个 HTML 的壳,而后再源生加载咱们须要的 JavaScrpit 代码来实现咱们的功能。
加载 JS 能够直接 webView.load() 加载完整的 JS 代码也能够在本身加的 head 节点引入 JS 文件而后 webView 直接 load 其中的方法, PandaEye 中使用的是第二种方法:
在拼装 HTML 时在 head 中引入放在 asset 文件夹中的 js 文件浏览器

enter description here
enter description here

imageClick.js 中的内容以下:ide

function initClick() {
    var objects = document.getElementsByTagName("img");
    for(var i=0;i<objects.length;i++)
    {
        objects[i].onclick= function (){
            window.JavaScriptFunction.getUrl(this.src);
        }
    }
}复制代码

而后在 WebChromeClient 当加载进度达到 100% 后去调用 JS 文件中的 initClick() 方法,为每一张图片设置点击事件:

/** * 为全部的图片添加点击事件 * * @param webView 对应的 WebView */
    private void addImageClickListener(WebView webView) {
        webView.loadUrl("javascript:(initClick())()");
    }复制代码

直接加载 JS 把 initClick() 用 JS 代码替换掉便可。

利用 Chrome 调试 WebView

WebView 中 JavaScript 代码的调试直接使用 AndroidStudio 是没办法的,那么咱们怎样调试 HTML 页面呢?答案是用 Chrome 浏览器来调试:

  • USB 选项是打开的(AS 能调试应用就行)
  • Chrome 浏览器打开地址:chrome://inspect 或者 about:inspect
    打开待调试的 WebView 而后能够看到以下界面:

InspectPage
InspectPage

点击对应页面的 inspect 就能够进入调试页面:

DebugPage
DebugPage

接下里就能够像调试前端页面同样调试 WebView 中的内容了。

最后

详细使用代码请移步 PandaEye 查看

相关文章
相关标签/搜索