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

js和本地交互

最近项目要求用js和本地交互,所以就去看了下webview的一些api,发现只能满足一些简单的需求,而项目里面的需求是比较多的而且要用的功能也算有点复杂,所以想想去githup搜索了下,有大神已经把这些东西封装好了。基本能满足大部分需求了。接下来说下他的用法,只是用他的源码需要把WebViewJavascriptBridge.js这文件拷贝到你的assets资源文件目录下,这个类里面自己封装了一些用于消息处理的方法。看下他的项目结构Js与本地代码的交互的一些用法_第1张图片在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 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 uploadMsg, String AcceptType, String capture) {
                this.openFileChooser(uploadMsg);
            }

            @SuppressWarnings("unused")
            public void openFileChooser(ValueCallback uploadMsg, String AcceptType) {
                this.openFileChooser(uploadMsg);
            }

            public void openFileChooser(ValueCallback 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: "这是一个图片  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: "这是一个图片  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回调给本地的数据,这就是一个回调的过程,自己看注释,还是非常容易理解掌握的~!

好了,今天,就先到这里~大家有问题可以发我邮箱([email protected])或者留言。

你可能感兴趣的:(java基础知识)