Android 和Js 交互的小demo

作者: Ad大成 | 来源:发表于2019-10-22 21:00 被阅读0次
/**
 * jsBridge原理
 * https://www.jianshu.com/p/2ec3f06d6087
 */

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.webView)
    WebView webView;
    @BindView(R.id.txt_msg)
    TextView txtMsg;
    @BindView(R.id.btn_show)
    Button btnShow;
    @BindView(R.id.btn_webview)
    Button btnWebview;
    @BindView(R.id.btn_net)
    Button btnNet;
    @BindView(R.id.btns)
    LinearLayout btns;
    @BindView(R.id.btn_test)
    Button btnTest;
    @BindView(R.id.img)
    ImageView img;
    @BindView(R.id.btn_execute)
    Button btnExecute;
    @BindView(R.id.jsBridge)
    BridgeWebView jsBridge;
    @BindView(R.id.btn_bridge)
    Button btnBridge;

    private Context context;

    //如果是本地的html文件用webView打开
    private String local_url = "file:////android_asset/user_info.html";
    //layabox3d 测试地址
    //private String local_url = "http://layaair.ldc.layabox.com/demo/h5/demo.html?category=3d&group=particle&name=Particle_EternalLight&lib=core,webgl,ani,d3";
    //如果是网络地址用默认浏览器打开
    private String net_url = "http://www.baidu.com";


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

        ButterKnife.bind(this);
        context = this;

        showUrl(local_url);

        //初始化Bridge
        initBridge();
    }

    private void initBridge(){
        jsBridge.setDefaultHandler(new DefaultHandler());
        jsBridge.setWebChromeClient(new WebChromeClient());
        jsBridge.loadUrl(local_url);
        //注册给js调用的方法
       jsBridge.registerHandler("submitFromWeb", new BridgeHandler() {

           //function js回调
           @Override
           public void handler(String data, CallBackFunction function) {
               Toast.makeText(context,"js返回:"+data,Toast.LENGTH_SHORT).show();
               function.onCallBack("android接收到数据了回传给js");
           }
       });

    }

    /**
     * 根据参数显示对应的内容
     */
    private void showUrl(String url) {
        if (url.indexOf("http") != -1 || url.indexOf("https") != -1) {
            loadNetHtml();
        } else {
            initLoadHtml();
        }
    }

    /**
     * https://www.jianshu.com/p/0d7d429bd216   WebSettings设置的属性介绍
     */
    private void initLoadHtml() {
        //local_url = "http://layaair.ldc.layabox.com/demo/h5/demo.html?category=3d&group=particle&name=Particle_EternalLight&lib=core,webgl,ani,d3";
        webView.loadUrl(local_url);
        //设置编码
        WebSettings webSettings = webView.getSettings();
        webSettings.setDefaultTextEncodingName("utf-8");
        //支持js
        webSettings.setJavaScriptEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        MyJavaScript myObj = new MyJavaScript();
        //设置本地调用对象及其接口
        webView.addJavascriptInterface(myObj, "myObj");
        //判断webview中是否能回退页面
        //webView.goBack();
        //webView.canGoBack();

        webView.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                //页面加载完成
                if(newProgress == 100){
                    //callJavascriptFun();
                    callJsFun();
                }
            }
        });
    }

    /**
     * 通过evaluateJavascript的方式访问接口
     */
    private void callJavascriptFun(){
        webView.evaluateJavascript("javascript:callByAndroid('from android data!')", new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String value) {
                Toast.makeText(context, value, Toast.LENGTH_SHORT).show();
            }
        });
    }


    /**
     * 用默认的浏览器打开对应的网页
     * 除了默认的浏览器可以打开,还可以用指定的浏览器打开
     * uc浏览器":"com.uc.browser", "com.uc.browser.ActivityUpdate“
     *   opera:"com.opera.mini.android", "com.opera.mini.android.Browser"
     *   qq浏览器:"com.tencent.mtt", "com.tencent.mtt.MainActivity"
     */
    private void loadNetHtml() {
        Intent intent = new Intent();
        intent.setAction("android.intent.action.VIEW");
        Uri content_url = Uri.parse(net_url);
        intent.setData(content_url);
        intent.setClassName("com.tencent.mtt", "com.tencent.mtt.MainActivity");
        startActivity(intent);
    }


    @OnClick({R.id.btn_show, R.id.btn_test, R.id.btn_net, R.id.btn_webview,R.id.btn_execute,R.id.btn_bridge})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.btn_show:
                webView.loadUrl("javascript:showMsg('from Android')");
                break;
            case R.id.btn_net:
                showUrl(net_url);
                break;
            case R.id.btn_webview:
                showUrl(local_url);
                break;
            case R.id.btn_test:
                PackageManager pg = MyApp.app.getPackageManager();
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("xl://login:8888/loginPage?username=张三"));
                List<ResolveInfo> activities = pg.queryIntentActivities(intent, 0);
                boolean isValid = !activities.isEmpty();
                if (isValid) {
                    startActivity(intent);
                }
                break;
            case R.id.btn_execute:
                callJsFun();
                break;
            case R.id.btn_bridge:
                callJsBridge();
                break;
        }

    }

    /**
     * android 4.4以后才有,调用不会刷新整个页面
     * 必须在html加载完成以后才能调用
     * execute javascript function
     */
    private void callJsFun(){
        webView.evaluateJavascript("javascript:fromAndroidCall('hello android')", new ValueCallback<String>() {
            //如果没有设置返回值value = null
            @Override
            public void onReceiveValue(String value) {
                Toast.makeText(context, value, Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * 访问js的Bridge
     */
    private void callJsBridge(){

        jsBridge.callHandler("callJs", "Android调用js", new CallBackFunction() {
            @Override
            public void onCallBack(String data) {
                Toast.makeText(context,data,Toast.LENGTH_SHORT).show();
            }
        });
    }


    /**
     * android与js接口调用的通信类
     */
    class MyJavaScript {

        /**
         *
         * Android4.2以下的addJavascriptInterface存在安全漏洞
         * Android4.2之后用@JavascriptInterface代替了
         * 给到Javascript调用
         *
         * @param msg js传过来的参数
         */
        @JavascriptInterface
        public void showTipsFromJs(String msg) {
            Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
            if (!TextUtils.isEmpty(msg)) {
                txtMsg.setText(msg);
            }
        }

        /**
         * 显示js传送过来的图片数据
         *
         * @param imgData
         */
        @JavascriptInterface
        public void showImgFromJs(String imgData) {
            imgData = imgData.replace("data:image/png;base64,","");
            final Bitmap bmp = stringToBmp(imgData);
            if(bmp != null) {
                img.post(new Runnable() {
                    @Override
                    public void run() {
                        img.setImageBitmap(bmp);
                    }
                });
            }
        }

    }

    /**
     * base64 转 bitmap
     *
     * @param content
     * @return
     */
    private Bitmap stringToBmp(String content) {
        Bitmap bitmap = null;
        try {
            byte[] bytes;
            bytes = Base64.decode(content, Base64.DEFAULT);
            bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }
}

js

<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body onload="pageOnload()">
        <div>输入内容提供给android显示:<input type="input" name="user_name" id="txt_input"></div>
        <div>显示来至android内容:<input type="text" name="show_msg" id="txt_showmsg"></div>

        <div name="div_name">
            <input type="button" name="submit" id="submit" onclick="submitAndroid()" value="提交到android">
        </div>
        <div name="div_name">
            <a href="xl://login:8888/loginPage?username=李四">打开android登录页面</a>
        </div>
        
        <div style="background-color:#ff0000">
            <img id="img_icon" style="width:100px;height:100px;background-color:#cccccc">
        </div>
        <div>
            <input type="button" value="img base64传入到android" onclick="sendImgToAndroid()">
        </div>
        <div>
            <input type="button" value="jsBridge 调用" onclick="callBridge()">
        </div>
        <!--脚本-->
        <script type="text/javascript">



            //同步回调
            function fromAndroidCall(str){
                alert(str);
            }

            //调用bridge
            function callBridge(){
                //参数1调用java中注册的方法,submitFromWeb是方法名
                //参数2返回给Android端的数据,可以String
                //参数3js接收android端回传的数据
                window.WebViewJavascriptBridge.callHandler(
                    "submitFromWeb",
                    {"param":"JS接收数据"},
                    function(responseData){
                        alert(responseData);
                    }
                );
            }

            //创建被android调用的方法
            function connectWebViewJavascriptBridge(callback){
                if(window.WebViewJavascriptBridge){
                    callback(WebViewJavascriptBridge);
                }else{
                    document.addEventListener(
                        "WebViewJavascriptBridgeReady",
                        function(){
                            callback(WebViewJavascriptBridge)
                        },
                        false
                    );
                }
            }

            //注册回调函数,初始化调用初始化函数
            connectWebViewJavascriptBridge(function(bridge){
                //初始化
                bridge.init(function(message,responseCallback){
                    var data = {
                        "Javascript Respond":"Bridge"
                    };
                    alert("alert bridge");
                    responseCallback(data);
                });

                //注册给android调用的方法
                bridge.registerHandler("callJs",function(data,responseCallback){
                    alert(data);
                    responseCallback("callJs回调给anroid");
                });
            });



            //传递数据到android
            function submitAndroid(){
                var str = document.getElementById("txt_input").value;
                //把window看作webview  myObj用着js调用android的内部类
                window.myObj.showTipsFromJs(str);
            }

            //给Android调用的接口
            function showMsg(msg){
                var txt_msg = document.getElementById("txt_showmsg");
                txt_msg.value = msg;
            }

            //android调用的方法
            function callByAndroid(msg){
                var txt_msg = document.getElementById("txt_showmsg");
                txt_msg.value = msg;
                return "调用完成";
            }

            //把img转成base64传入android
            function getBase64Img(img){
                var cas = document.createElement("canvas");
                cas.width = img.width;
                cas.height = img.height;
                var ctx = cas.getContext("2d");
                ctx.drawImage(img,0,0,img.width,img.height);
                //格式可以是 image/png image/jpeg
                var img_data = cas.toDataURL("image/jpg");
                window.myObj.showImgFromJs(img_data);
            }

            function sendImgToAndroid(){
                var img = document.getElementById("img_icon");
                getBase64Img(img);
            }

            function pageOnload(){
                var divs = document.getElementsByName("div_name");
                var img = document.getElementById("img_icon");
                img.setAttribute('crossOrigin', 'anonymous');
                img.src = "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3660681135,2179565665&fm=26&gp=0.jpg";
            }

        </script>

    </body>

</html>

相关文章

网友评论

    本文标题:Android 和Js 交互的小demo

    本文链接:https://www.haomeiwen.com/subject/zcucvctx.html