H5混合开发 js与java相互调用

介绍

  • 本篇主要介绍H5与android相互调用

1.Android中调用H5的js的实现

首先创建一个index页面


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>H5混合开发title>
    <script src="js/jquery.min.js">script>
head>
<body>
<p> 我是H5页面p>
body>
html>

在android中初始化webview加载上面网页的url

public class AndroidH5Activity extends AppCompatActivity {

    private WebView mWebview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_h5);

        initView();

        //webview设置
        setWebView();

        //在线模板:调试模式,当页面发生改变,客户端不需要重新编译运行,把工程创建在Tomacat下
        mWebview.loadUrl("http://10.0.3.2:8080/WebDemo/index.html");

    }

    private void setWebView() {
        WebSettings settings = mWebview.getSettings();
        //开启JS和android通信开关
        settings.setJavaScriptEnabled(true);
        //使用内置webview打开其他链接
        mWebview.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            //页面加载完成回调方法
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                //以json的方式传递数据 调用js方法: 对象.方法名(参数)
                //mWebview.loadUrl("javascript:方法名(参数)");
                //android 调用 js 代码
                JSONObject json = new JSONObject();
                try {
                    json.put("name", "android");
                    json.put("message", "你好H5,我是android!收到请回答!");
                    //调用js代码
                    mWebview.loadUrl("javascript:showMessage(" + json.toString() + ")");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });

        mWebview.setWebChromeClient(new WebChromeClient() {
            //加载进度
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
            }
        });

    }

    private void initView() {
        mWebview = (WebView) findViewById(R.id.webview);
    }
}

在上面webview初始化中mWebview.loadUrl(“javascript:showMessage(” + json.toString() + “)”);这行代码负责去调用js中的代码,主要方法名要与js中的方法名相同

H5中对android中的代码做出响应


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>H5混合开发title>
    <script src="js/jquery.min.js">script>
head>
<body>
<script>
    //android调用js代码
    var showMessage = function (json) {
        alert(JSON.stringify(json));
    };
script>
body>
html>

当跳转到H5界面就会显示以下内容

H5混合开发 js与java相互调用_第1张图片

H5实现对Android的调用

首先在H5中写js调用android方法


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>H5混合开发title>
    <script src="js/jquery.min.js">script>
    <style>
        button {
            width: 100%;
            height: 38px;
            color: white;
            border-style: none;
            font-size: 20px;
            border-radius: 6px;
            background-color: #50b2ff;
            margin-top: 10px;
        }

        button:active {
            background-color: #2e87ff;
        }
    style>
head>
<body>

<button id="btn1">js主动调用安卓button>

<script>

    //统一管理js调用android方法
    var invokeAndroid = function (json) {
        //调用android方法
        // window.映射字符串.方法名
        window.jsInterface.invokeMethods(JSON.stringify(json));
    };

    //JS调用android代码
    $("#btn1").on("click", function () {
        console.log("H5页面点击了按钮一");
        var json = {"name": "H5", "message": "你好!我是H5,收到!收到!", "action": "showToast"};
        invokeAndroid(json);
    });

    //android调用js代码
    var showMessage = function (json) {
        alert(JSON.stringify(json));
    };

script>
body>
html>

上面H5页面中是以一个按钮的点击形式,通过json字符串的形式传递给android客户端
window.jsInterface.invokeMethods(JSON.stringify(json));中的jsInterface是在android代码中定义的,下面会给出定义方式

public class AndroidH5Activity extends AppCompatActivity {

    private WebView mWebview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_h5);

        initView();

        //webview设置
        setWebView();

        //本地模板:为了优化WebView,正式上线可以使用,只要页面不经常改变,可以使用callback+本地模板,把工程创建在assets下
        mWebview.loadUrl("file:///android_asset/WebDemo/index.html");

        //在线模板:调试模式,当页面发生改变,客户端不需要重新编译运行,把工程创建在Tomacat下
        // mWebview.loadUrl("http://10.0.3.2:8080/WebDemo/index.html");

        //这是通信的桥梁类
        JavaScriptMethods javaScriptMethods = new JavaScriptMethods(this, mWebview);
        //设置H5和android通信接口:参数1-提供给js调用的对象,参数2-第1个参数的映射字符串(别名)
        mWebview.addJavascriptInterface(javaScriptMethods, "jsInterface");
    }

    private void setWebView() {
        WebSettings settings = mWebview.getSettings();
        //开启JS和android通信开关
        settings.setJavaScriptEnabled(true);
        //使用内置webview打开其他链接
        mWebview.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            //页面加载完成回调方法
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                //以json的方式传递数据 调用js方法: 对象.方法名(参数)
                //mWebview.loadUrl("javascript:方法名(参数)");
                //android 调用 js 代码
                JSONObject json = new JSONObject();
                try {
                    json.put("name", "android");
                    json.put("message", "你好H5,我是android!收到请回答!");
                    mWebview.loadUrl("javascript:showMessage(" + json.toString() + ")");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });

        mWebview.setWebChromeClient(new WebChromeClient() {
            //加载进度
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
            }
        });

    }


    private void initView() {
        mWebview = (WebView) findViewById(R.id.webview);
    }
}

定义android与H5之前的桥梁类

public class JavaScriptMethods {
    private static final String TAG = "JavaScriptMethods";
    private Activity mActivity;
    private WebView mWebView;
    private Handler mHandler = new Handler();

    public JavaScriptMethods(Activity activity, WebView webView) {
        mActivity = activity;
        mWebView = webView;
    }

    /**
     * 统一管理所有H5和安卓通信方法,相当于入口函数
     */
    // 自定义H5+android通信协议规则:为了安全
    /*安全:android17以上,如果不加上该注解,H5无法调用安卓方法,谷歌为了安全,因为低版本js能够通过反射调用android系统功能*/
    @JavascriptInterface
    public void invokeMethods(String json) {
        //解析动作字符串 js中定义的"action"
        try {
            JSONObject jsJSON = new JSONObject(json);
            String action = jsJSON.optString("action");

            Log.e(TAG, "invokeMethods: " + action);

            if ("showToast".equals(action)) {
                showToast(json);
            } 

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private void showToast(String json) {
        Toast.makeText(mActivity, "" + json, Toast.LENGTH_SHORT).show();
    }
}

不难看出桥梁类中是通过js中的方法,传递json字符串给客户端,然后通过json中的action字段的类型,来判断需要做什么操作
H5混合开发 js与java相互调用_第2张图片

3.上面两种已经实现了android与H5的交互,下面callback的形式实现解耦,并且更安全

首先看index页面


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>H5混合开发title>
    <script src="js/jquery.min.js">script>
    <style>
        button {
            width: 100%;
            height: 38px;
            color: white;
            border-style: none;
            font-size: 20px;
            border-radius: 6px;
            background-color: #50b2ff;
            margin-top: 10px;
        }

        button:active {
            background-color: #2e87ff;
        }
    style>
head>
<body>

<button id="btn1">js主动调用安卓button>
<button id="btn2">js callback式回调androidbutton>

<script>

    //统一管理js调用android方法
    var invokeAndroid = function (json) {
        //调用android方法
        // window.映射字符串.方法名
        window.jsInterface.invokeMethods(JSON.stringify(json));
    };

    //JS调用android代码
    $("#btn1").on("click", function () {
        console.log("H5页面点击了按钮一");
        var json = {"name": "H5", "message": "你好!我是H5,收到!收到!", "action": "showToast"};
        invokeAndroid(json);
    });

    //JS调用android代码
    $("#btn2").on("click", function () {
        //js调用ajax获取服务器返回数据,但是有的公司客户端已经完成网络通信框架,这时候如果H5在写一套网络通信框架,
        // 可以用callback避免H5编写过多代码

        //1.先主动调用Android方法
        var json = {"callback": "receiveData", "action": "getJSData"};
        invokeAndroid(json);
    });

    var receiveData = function (json) {
        //2.android 回调给 js ,
        alert("接受到Android回传数据=" + JSON.stringify(json));
    };

    //android调用js代码
    var showMessage = function (json) {
        alert(JSON.stringify(json));
    };

script>
body>
html>

这边主要是桥梁类做出了变化

public class JavaScriptMethods {
    private static final String TAG = "JavaScriptMethods";
    private Activity mActivity;
    private WebView mWebView;
    private Handler mHandler = new Handler();

    public JavaScriptMethods(Activity activity, WebView webView) {
        mActivity = activity;
        mWebView = webView;
    }

    /**
     * 统一管理所有H5和安卓通信方法,相当于入口函数
     */
    // 自定义H5+android通信协议规则:为了安全
    /*安全:android17以上,如果不加上该注解,H5无法调用安卓方法,谷歌为了安全,因为低版本js能够通过反射调用android系统功能*/
    @JavascriptInterface
    public void invokeMethods(String json) {
        //解析动作字符串 js中定义的"action"
        try {
            JSONObject jsJSON = new JSONObject(json);
            String action = jsJSON.optString("action");

            Log.e(TAG, "invokeMethods: " + action);

            if ("showToast".equals(action)) {
                showToast(json);
            } else if ("getJSData".equals(action)) {
                getJSData(json);
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private void getJSData(String json) {
        //模拟网络请求数据,以json的格式返回
        Log.e(TAG, "getJSData: " + json);

        JSONObject backJson = new JSONObject();
        try {
            //添加数据,这边是假数据,一般都是网络请求
            backJson.put("name", "kevinyang");
            backJson.put("age", "25");
            backJson.put("address", "广东省深圳市");
            backJson.put("email", "[email protected]");

            //解析获取js callback方法名
            JSONObject jsJson = new JSONObject(json);
            String callBack = jsJson.optString("callback");

            callbackJs(callBack, backJson);
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    private void callbackJs(final String callback, final JSONObject json) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                //回传酒店数据给H5页面:调用js方法,必须在主线程
                //当前方式H5和按安卓耦合度过高,方法名写死
                //mWebView.loadUrl("javascript:receiveData("+backJson.toString()+")");
                //使用callback机制,解耦
                mWebView.loadUrl("javascript:" + callback + "(" + json.toString() + ")");
            }
        });
    }


    private void showToast(String json) {
        Toast.makeText(mActivity, "" + json, Toast.LENGTH_SHORT).show();
    }
}

H5混合开发 js与java相互调用_第3张图片

你可能感兴趣的:(web开发)