1.初始化

1.布局中添加webview控件

2.让webview支持js

webView.getSettings().setJavaScriptEnabled(true);

3.加载网页

webView.loadUrl(url);

4.让webview加载网页

id_webview.setWebChromeClient(new WebChromeClient());

2.原生调用JS方法

1.原生调用js不带返回值的方法
js带参数的方法 不带返回值
function nativeCallToJS(param) {
    alert(param);
}

//原生调用js 不带返回值
public void nativeCallToJS1(){
    js方法带参数的 参数为字符串需要加单引号 javascript:方法名 (参数名)
    id_webview.loadUrl("javascript:nativeCallToJS("+"'hello xiaocheng'"+")");
}

2.原生调用js带返回值的方法
js带返回值方法
function returnResult(){
    return 1 + 2;
}

//原生调用js 获取返回值 returnResult: js定义的方法 ()不能少
public void nativeCallToJS2(){
    id_webview.evaluateJavascript("returnResult()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            Toast.makeText(MainActivity.this,"我是调用js返回的数据:"+value,Toast.LENGTH_LONG).show();
        }
    });
}

3.JS调用原生方法

@JavascriptInterface注解表面这个方法是给js调用的

1. 通过addJavascriptInterface将MainActiviy所对应的对象mainActivity注入到WebView中了。

2. 查看js调用原生是否在主线程 因为原生只能在主线程更新ui

原生方法
@JavascriptInterface
public void jsCallNativeLookThread(String msg){
    Log.e("js调用原生方法是不是在主线程",Thread.currentThread().getName().equals("main")+"");
    Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
    id_webview.post(new Runnable() {
        @Override
        public void run() {
            id_webview.loadUrl("javascript:nativeCallToJS("+"'你好啊,小成哥!'"+")");
        }
    });
}

js中调用的方法 mainActivity必须与上面绑定的对象一样
function jsCallNativeLookThread(param) {
    window.mainActivity.jsCallNativeLookThread(param);
}

3. js调用原生获取原生返回值

原生方法
@JavascriptInterface
public int jsCallNativeGetResult(int num, int num1) {
    return num + num1;
}

js调用 把计算的结果显示出来
function jsCallNativeGetResult(num1,num2) {
   document.getElementById("font").innerText = "调用原生计算的结果:"+
   window.mainActivity.jsCallNativeGetResult(num1,num2);
}

4. js调用原生原生跳页传值

 原生方法
@JavascriptInterface
public void jsCallNativeToActivity(String msg){
    Intent intent = new Intent(this,SecondActivity.class);
    intent.putExtra("msg",msg);
    startActivity(intent);
}

js调用
function jsCallNativeToActivity(param){
    window.mainActivity.jsCallNativeToActivity(param);
}

5. js调用原生保存网络图片到sd卡

原生方法  Android6.0以上需要动态权限处理 同时需要在清单文件中添加sd卡读写权限和网络权限
private String imagUrl;
//Js调用原生方法保持图片到sd卡
@JavascriptInterface
public void jsCallNativeSaveImg(String imgUrl){

    this.imagUrl = imgUrl;
    boolean checkResult = PermissionsCheckUtils.checkPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE);
    if(!checkResult){
        Log.e("saveImgToSdcard","权限未通过");
requestPermissions(this,STORAGECODE,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE);
    }else {
        saveImage(imgUrl);
    }
}

 //安卓6.0以上需要动态获取权限
private  void requestPermissions(Activity activity, int requestCode,String... permissions){
    ActivityCompat.requestPermissions(activity,permissions,requestCode);
}

//权限处理请求返回值
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    //判断请求码,确定当前申请的权限
    if (requestCode == STORAGECODE) {
        //判断权限是否申请通过
        if (grantResults.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //授权成功
            saveImage(imagUrl);
        } else {
            //授权失败
        }
    } else {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

//保存图片方法
private void saveImage(String imgUrl) {
    Log.e("saveImg","图片地址:"+imgUrl);
    InputStream is = null;
    FileOutputStream fos = null;
    try {
        URL url = new URL(imgUrl);
        if(url != null){
            is = url.openStream();
        }
        if(is != null){
            Bitmap bitmap = BitmapFactory.decodeStream(is);
            if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
                    && !Environment.isExternalStorageRemovable()){
                File targetFile = new File(Environment.getExternalStorageDirectory(),"testImgs");
                if(!targetFile.exists()){
                    targetFile.mkdir();
                }
                File file = new File(targetFile.getAbsolutePath(), UUID.randomUUID().toString()+".jpg");
                fos = new FileOutputStream(file);
                //80代表压缩率为20%
                bitmap.compress(Bitmap.CompressFormat.JPEG,80,fos);
                fos.flush();
                fos.close();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        if(is != null){
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

js调用原生方法保存图片
function jsCallNativeSaveImg() {
    var imgUrl = "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3668554427,3084213941&fm=200&gp=0.jpg";
    window.mainActivity.jsCallNativeSaveImg(imgUrl);
}

6. html页面中点击事件处理

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Main</title>
    <link rel="stylesheet" href="./main.css" type="text/css" />
    <script src="./main.js"></script>
</head>
<body>
    <div class="layout">
        <h3 id="font" style="padding-top:10px">zlc</h3>
        <button class="button" onclick="jsCallNativeLookThread('测试线程 ')">js调用Native查看线程</button>
        <br/>
        <button class="button" onclick="jsCallNativeGetResult(518,2)">js调用Native获取返回值</button>
        <br/>
        <button class="button" onclick="jsCallNativeToActivity('100')">js调用Native跳页传值</button>
        <br/>
        <button class="button" onclick="jsCallNativeSaveImg()">js调用native保存图片</button>
    </div>
</body>
</html>

4.总结

其实android原生与js互调比想象中简单

5.下载地址

点击去下载