Js与本地代码的交互的一些用法

来源:互联网 发布:程序员教程(第4版) 编辑:程序博客网 时间:2024/06/05 01:16

js和本地交互

最近项目要求用js和本地交互,所以就去看了下webview的一些api,发现只能满足一些简单的需求,而项目里面的需求是比较多的而且要用的功能也算有点复杂,所以想想去githup搜索了下,有大神已经把这些东西封装好了。基本能满足大部分需求了。接下来说下他的用法,只是用他的源码需要把WebViewJavascriptBridge.js这文件拷贝到你的assets资源文件目录下,这个类里面自己封装了一些用于消息处理的方法。看下他的项目结构这里写图片描述在model里面就是一个user实体了,后面有用到,接着看MainActivity.java

package com.lyk.jsbridge;import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.support.design.widget.FloatingActionButton;import android.support.design.widget.Snackbar;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.Toolbar;import android.util.Log;import android.view.View;import android.webkit.ValueCallback;import android.webkit.WebChromeClient;import android.widget.Toast;import com.github.lzyzsd.jsbridge.BridgeHandler;import com.github.lzyzsd.jsbridge.BridgeWebView;import com.github.lzyzsd.jsbridge.BridgeWebViewClient;import com.github.lzyzsd.jsbridge.CallBackFunction;import com.github.lzyzsd.jsbridge.DefaultHandler;import com.google.gson.Gson;import com.lyk.jsbridge.modle.User;public class MainActivity extends AppCompatActivity {    private BridgeWebView mWebView;    ValueCallback<Uri> mUploadMessage;    int RESULT_CODE = 0;    private static final String TAG = "MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);        setSupportActionBar(toolbar);        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);        fab.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)                        .setAction("Action", null).show();            }        });        mWebView = (BridgeWebView) findViewById(R.id.webView);        initWebView();    }    private void initWebView() {        // 设置具体WebViewClient        mWebView.setWebViewClient(new MyWebViewClient(mWebView));        // set HadlerCallBack        mWebView.setDefaultHandler(new myHadlerCallBack());        // setWebChromeClient        mWebView.setWebChromeClient(new WebChromeClient() {            @SuppressWarnings("unused")            public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType, String capture) {                this.openFileChooser(uploadMsg);            }            @SuppressWarnings("unused")            public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType) {                this.openFileChooser(uploadMsg);            }            public void openFileChooser(ValueCallback<Uri> uploadMsg) {                mUploadMessage = uploadMsg;                pickFile();            }        });        mWebView.loadUrl("file:///android_asset/demo.html");        //必须和js函数名字一致,注册好具体执行回调函数,类似java实现类。        mWebView.registerHandler("submitFromWeb", new BridgeHandler() {            @Override            public void handler(String data, CallBackFunction function) {                String str = "这是html返回给java的数据:" + data;                // 例如你可以对原始数据进行处理                str = str + ",Java经过处理后截取了一部分:" + str.substring(0, 5);                Log.i(TAG, "handler = submitFromWeb, data from web = " + data);                Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();                //回调返回给Js                function.onCallBack(str + ",Java经过处理后截取了一部分:" + str.substring(0, 5));            }        });        mWebView.registerHandler("functionOpen",  new BridgeHandler() {            @Override            public void handler(String data, CallBackFunction function) {                Toast.makeText(MainActivity.this, "网页在打开你的下载文件预览", Toast.LENGTH_SHORT).show();                pickFile();            }        });        //模拟用户信息 获取本地位置,用户名返回给html        User user = new User();        user.setLocation("上海");        user.setName("Bruce");        // 回调 "functionInJs"        mWebView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() {            @Override            public void onCallBack(String data) {                Toast.makeText(MainActivity.this, "网页在获取你的位置,"+ data, Toast.LENGTH_SHORT).show();            }        });        mWebView.send("hello");    }    /**     * 自定义的WebViewClient     */    class MyWebViewClient extends BridgeWebViewClient {        public MyWebViewClient(BridgeWebView webView) {            super(webView);        }    }    /**     * 自定义回调     */    class myHadlerCallBack extends DefaultHandler {        @Override        public void handler(String data, CallBackFunction function) {            if(function != null){                Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show();            }        }    }    public void pickFile() {        Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);        chooserIntent.setType("image/*");        startActivityForResult(chooserIntent, RESULT_CODE);    }    @Override    public void onActivityResult(int requestCode, int resultCode, Intent intent) {        if (requestCode == RESULT_CODE) {            if (null == mUploadMessage) {                return;            }            Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData();            mUploadMessage.onReceiveValue(result);            mUploadMessage = null;        }    }}
  • js里面的代码:
html><head>    <meta content="text/html; charset=utf-8" http-equiv="content-type">    <title>        js调用java    </title></head><body><p>    <xmp id="show">    </xmp></p><p>    <xmp id="init">    </xmp></p><p>    <input type="text" id="text1" value="用户名(username)"/></p><p>    <input type="text" id="text2" value="password"/></p><p>    <input type="button" id="enter" value="发消息给Native" onclick="testClick();"            /></p><p>    <input type="button" id="enter1" value="调用Native方法" onclick="testClick1();"            /></p><p>    <input type="button" id="enter2" value="显示源代码" onclick="testDiv();"/></p><p>    <input type="file" id="open" value="打开文件" onclick="onOpen();"/></p></body><script>        function onOpen() {           var str1 = document.getElementById("text1").value;            var str2 = document.getElementById("text2").value;            var data = "name=" + str1 + ",pass=" + str2;            //call native method            window.WebViewJavascriptBridge.callHandler(                'functionOpen'                , {'param': data }                , function(responseData) {                    //document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData;                }            );        }        function testDiv() {            document.getElementById("show").innerHTML = document.getElementsByTagName("html")[0].innerHTML;        }        function testClick() {            var str1 = document.getElementById("text1").value;            var str2 = document.getElementById("text2").value;            //发送消息给java本地代码            var data = {id: 1, content: "这是一个图片 <img src=\"a.png\"/> test\r\nhahaha"};            window.WebViewJavascriptBridge.send(                data                , function(responseData) {                    document.getElementById("show").innerHTML = "repsonseData from java, data = " + responseData                }            );        }        function testClick1() {            var str1 = document.getElementById("text1").value;            var str2 = document.getElementById("text2").value;            var data = "name=" + str1 + ",pass=" + str2;            //call native method            window.WebViewJavascriptBridge.callHandler(                'submitFromWeb'                , {'param': data }                , function(responseData) {                    document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData                }            );        }        function bridgeLog(logContent) {            document.getElementById("show").innerHTML = logContent;        }        function connectWebViewJavascriptBridge(callback) {            if (window.WebViewJavascriptBridge) {                callback(WebViewJavascriptBridge)            } else {                document.addEventListener(                    'WebViewJavascriptBridgeReady'                    , function() {                        callback(WebViewJavascriptBridge)                    },                    false                );            }        }       // 第一连接时初始化bridage        connectWebViewJavascriptBridge(function(bridge) {            bridge.init(function(message, responseCallback) {                console.log('JS got a message', message);                var data = {                    'Javascript Responds': '测试中文!'                };                console.log('JS responding with', data);                responseCallback(data);            });            // 注册一个"functionInJs",            bridge.registerHandler("functionInJs", function(data, responseCallback) {                document.getElementById("show").innerHTML = ("data from Java: = " + data);                var responseData = "Javascript Says  我要你的地址!";                // response层                responseCallback(responseData);            });        })        bridge.init(function(message, responseCallback) {        console.log('JS got a message', message);        var data = {            'Javascript Responds': 'Wee!'        };        console.log('JS responding with', data);        responseCallback(data);    });</script></html>

首先看下js里面的代码,可以看到有button,对应俩个点击事件onclick(),onclick1(); 再看下面的代码找到这个俩个方法的实现,

//第一个实现function testClick() {            var str1 = document.getElementById("text1").value;            var str2 = document.getElementById("text2").value;            //发送消息给java本地代码            var data = {id: 1, content: "这是一个图片 <img src=\"a.png\"/> test\r\nhahaha"};            window.WebViewJavascriptBridge.send(                data                , function(responseData) {                    document.getElementById("show").innerHTML = "repsonseData from java, data = " + responseData                }            );        }//这里是第二个实现        function testClick1() {            var str1 = document.getElementById("text1").value;            var str2 = document.getElementById("text2").value;            var data = "name=" + str1 + ",pass=" + str2;            //call native method            window.WebViewJavascriptBridge.callHandler(                'submitFromWeb'                , {'param': data }                , function(responseData) {                    document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData                }            );        }

可以看到俩个方法里面都有
//call native method
window.WebViewJavascriptBridge.callHandler(
‘submitFromWeb’之类的写法,这里就是开始调用本地的方法,注释里面写的很清楚,注意这里的单引号的字符串就是对应java中的别名,所以只要到java本地代码中去看看,找到这别名就知道他的调用了。go~go~go!

        //必须和js函数名字一致,注册好具体执行回调函数,类似java实现类。        mWebView.registerHandler("submitFromWeb", new BridgeHandler() {            @Override            public void handler(String data, CallBackFunction function) {                String str = "这是html返回给java的数据:" + data;                // 例如你可以对原始数据进行处理                str = str + ",Java经过处理后截取了一部分:" + str.substring(0, 5);                Log.i(TAG, "handler = submitFromWeb, data from web = " + data);                Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();                //回调返回给Js                function.onCallBack(str + ",Java经过处理后截取了一部分:" + str.substring(0, 5));            }        });

找到了,上面的代码就是到这webview 标上’submitFromWeb’别名,注册一个回调,看注释,其中data是点击js中的button给我的数据,而就是通过这个类CallBackFunction 将本地java的数据回调给js的: function.onCallBack(str + “,Java经过处理后截取了一部分:” + str.substring(0, 5)); 一定要注意这里的别名一定要写的跟js中的一致,不然找不到的,关于原理,其实是他内部用了一个结合将这个别名和接口装载,然后js获取的时候会根据这别名找到对应的接口也就是这个BrigeHandler,然后回调里面的数据,要弄清楚里面的细节可以自己看源码,这个过程就是js调用本地的一种,再看看本地调用js的。

 //模拟用户信息 获取本地位置,用户名返回给html        User user = new User();        user.setLocation("上海");        user.setName("Bruce");        // 回调 "functionInJs"        mWebView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() {            @Override            public void onCallBack(String data) {                Toast.makeText(MainActivity.this, "网页在获取你的位置,"+ data, Toast.LENGTH_SHORT).show();            }        });        mWebView.send("hello");

然后找到js中别名部分的代码:

// 注册一个"functionInJs",            bridge.registerHandler("functionInJs", function(data, responseCallback) {                document.getElementById("show").innerHTML = ("data from Java: = " + data);                var responseData = "Javascript Says  我要你的地址!";                // response层                responseCallback(responseData);            });

注释非常清楚,可以看的出来,本地java将一个data user数据传过去了,而js中通过responseCallback回调给本地的数据,这就是一个回调的过程,自己看注释,还是非常容易理解掌握的~!

好了,今天,就先到这里~大家有问题可以发我邮箱(593769469@qq.com)或者留言。

1 0