废话不多说直接开始

 1.安卓调用JS(这里我们采用的都是本地资源)

WebSettings webSettings = webview.getSettings();

        // 设置与Js交互的权限
        webSettings.setJavaScriptEnabled(true);
        // 设置允许JS弹窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

接下来就是加载与交互了。。。。。。

Android调用JS代码的方法有2种:

  1. 通过WebViewloadUrl()
  2. 通过WebViewevaluateJavascript()

  第一种:使用方便  不需要获取返回值,性能低

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

  第二种:效率高  但是只能是4.4以上使用

webview.evaluateJavascript("javascript:callJS('" + msg + "')", new ValueCallback<String>() {
                            @Override
                            public void onReceiveValue(String value) {
                                Log.e("TAG","是"+value);
                            }});

但是发现第二种返回值为null  网上找了白天也没有找到原因,希望大佬告诉我

为了兼容使用建议结合使用(JS返回 的值是 webview.setWebChromeClient里面)

if (version < 18) {
    mWebView.loadUrl("javascript:callJS()");
} else {
    mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            //此处为 js 返回的结果
        }
    });

 webview.setWebChromeClient(new WebChromeClient() {

            @Override
            public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
                AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this);
                b.setTitle("alert1");
                
                //JS 返回来的值
                b.setMessage(message);
                
                b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //关闭窗口JS调用
                        result.confirm();
                    }
                });
                b.setCancelable(false);
                b.create().show();
                return true;
            }
        });

html代码如下

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Carson_Ho</title>

    // JS代码
    <script>
// 如果这个方法设置参数 那么他就是android 传过来的值
   function callJS(msg){
      alert("你好"+msg);
   }
</script>

</head>

</html>

2 JS调用安卓代码

android调用js方法并传参数 android webview调用js_android调用js方法并传参数

我先把html三种方式的html都贴出来

<html>
<body>
<script type="text/javascript">
<!--document.write("<h1>Hello World!</h1>")-->
function func1(str){
      alert("Android调用了JS的func1方法--"+str);
      return "jsjs";
}
function clickBtn(){
    <!--通过这个可以给安卓传值  callByJS是接受值的方法名-->
    androidObj.callByJS("JS调用了Android的方法");
}
function clickBtn2(){
<!--通过这个可以给安卓传值  location相当于拦截信息 如果一致则拦截-->
    document.location = "callandroid://test?arg1=abc&arg2=202";
}

function clickBtn3(){
    <!--这边会被拦截,可以取得返回值  与方法二大同小异-->
    var str = prompt("callandroid://test?arg1=btn3");
    alert(str);
}
</script>
<button type="button" id="btn" onclick="clickBtn()">点击调用Android代码</button>
<Br/>
<Br/>
<button type="button" id="btn2" onclick="clickBtn2()">通过拦截调用Android代码</button>
<Br/>
<Br/>
<button type="button" id="btn3" onclick="clickBtn3()">拦截prompt</button>
</body>
</html>

 

方式1:通过 WebViewaddJavascriptInterface()进行对象映射

实现定义一个JS对象映射关系的Android类

public class CallByJS{
    // 被JS调用的方法必须加@JavascriptInterface注解
    @JavascriptInterface
    public void callByJS(String str) {
        Log.e("web_test",str);
    }
}

将需要调用的JS代码放到src/main/assets文件夹里(查看最上面的html方法一)

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

// 设置与Js交互的权限
        webSettings.setJavaScriptEnabled(true);
private void web1() {
        // 通过addJavascriptInterface()将Java对象映射到JS对象
        //参数1:Javascript对象名
        //参数2:Java对象名
        // 通过addJavascriptInterface()将Java对象映射到JS对象
        webview2.addJavascriptInterface(new CallByJS(), "androidObj");

        // 加载JS代码
        // 格式规定为:file:///android_asset/文件名.html
        webview2.loadUrl("file:///android_asset/js.html");
    }

方式2:通过shouldOverrideUrlLoading ()拦截 url

首先在JS约定所需要的Url协议(查看html)/*约定的url协议为:js://webview?arg1=111&arg2=222*/

然后复写shouldOverrideUrlLoading ()

private void web2() {
        webview2.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // 根据协议的参数进行拦截,下面拦截"callandroid://test"
                // 一般根据scheme & authority判断

                Uri uri = Uri.parse(url);
                // 如果 scheme  = callAndroid,即代表都符合约定的协议
                if (uri.getScheme().equals("callandroid")) {

                    // 如果 authority  = test,即代表都符合约定的协议
                    if (uri.getAuthority().equals("test")) {
                        // 拦截url,下面开始执行Android的方法

                        Toast.makeText(Main2Activity.this, "js通过拦截调用了Android的方法", Toast.LENGTH_SHORT).show();
                        // 可以获取参数
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> paramNames = uri.getQueryParameterNames();
                        for (String name : paramNames) {
                            params.put(name, uri.getQueryParameter(name));
                        }

                        Log.e("web_test", "是"+params.toString());

                    }

                    return true;
                }
                return super.shouldOverrideUrlLoading(view, url);

            }
        });
    }

方式3:通过 WebChromeClient 的onJsAlert()onJsConfirm()onJsPrompt()方法回调拦截JS对话框alert()confirm()prompt() 消息

private void web3() {
        webview2.setWebChromeClient(new WebChromeClient(){
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                return super.onJsConfirm(view, url, message, result);
            }

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                // 根据协议的参数进行拦截,下面拦截"callandroid://test"
                // 一般根据scheme & authority判断
                Uri uri = Uri.parse(message);//message是由JS的prompt()传来的
                // 如果 scheme  = callAndroid,即代表都符合约定的协议
                if (uri.getScheme().equals("callandroid")) {

                    // 如果 authority  = test,即代表都符合约定的协议
                    if (uri.getAuthority().equals("test")) {// 拦截url,下面开始执行Android的方法

                        // 可以获取参数
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> paramNames = uri.getQueryParameterNames();
                        for (String name : paramNames) {
                            params.put(name, uri.getQueryParameter(name));
                        }
                        //将返回值返回给JS
                        result.confirm("拦截Prompt成功啦,传进来的参数是:"+params.toString());
                    }
                    return true;
                }
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }
        });
    }

参考来自 Carson_Ho

 

二 WebView的回退与回退刷新

1实现是回退(就是返回上一个页面而不是退出Activity)

    只需要实现onKeyDown即可(代码如下)

@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode==KeyEvent.KEYCODE_BACK){
            if(webview3.canGoBack()){
                //这个是缓存策略
                webview3.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
                //后退上一个页面
                webview3.goBack();
                return true;
            }else {
                //如果没有页面了关闭Acitvity
                finish();
            }
        }
        return false;
    }

2解决刷新问题

    其实就是改变WebView的缓存策略 一共有五个在这里就不多说了,直接上代码了

webview3.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
                view.loadUrl(url);
                return super.shouldOverrideUrlLoading(view, url);
            }
        });

  @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode==KeyEvent.KEYCODE_BACK){
            if(webview3.canGoBack()){
                webview3.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
                webview3.goBack();
                return true;
            }else {
                finish();
            }
        }
        return false;
    }

 

三. 给WebView添加自定义的加载控件(我这里使用Toast)

 

webview3.setWebViewClient(new WebViewClient(){
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                // 页面(url)开始加载
                Toast.makeText(Main4Activity.this, "开始加载", Toast.LENGTH_SHORT).show();
                //这个显示加载控件
            }
            @Override
            public void onPageFinished(WebView view, String url) {
                // 页面(url)完成加载
                这个回调并不稳  页面加载完也不一定回调 所以换给思路
            }

        });

我们可以监听WebView自带的加载进度回调

webview3.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                //会触发多次
                if (newProgress==100){
                    Toast.makeText(Main4Activity.this, "完成加载", Toast.LENGTH_SHORT).show();

                这里写 控件加载完毕 
                }
            }
        });

四 WebView下拉刷新实现


SwipeRefreshLayout即可实现 xml如下


<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout 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"
    android:id="@+id/swrl"
    tools:context=".Main5Activity">

    <WebView
        android:layout_width="match_parent"
        android:id="@+id/webView5"
        android:layout_height="match_parent">

    </WebView>
</android.support.v4.widget.SwipeRefreshLayout>

 

代码中继续使用

swrl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                loadurl();
            }
        });

        webView5.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                //会触发多次
                if (newProgress==100){
                    swrl.setRefreshing(false);
                }
            }
        });

源码下载     点我

我只上传了xml  和代码   与html  可以复制使用