MyBridgeWebViewDemo【集成JsBridge開源庫的的封裝的webview】

版權聲明:本文爲HaiyuKing原創文章,轉載請註明出處!javascript

前言

使用的是第三方庫lzyzsd/JsBridge,可是不一樣的是,將本身封裝的MyBridgeWebView經過繼承BridgeWebView來使用,而不是使用第三方庫的com.github.lzyzsd.jsbridge.BridgeWebViewhtml

效果圖

代碼分析

1、自封裝的webview如何繼承BridgeWebView

一、自定義的MyBridgeWebView繼承BridgeWebView

二、自定義的MyBridgeWebViewClient繼承BridgeWebViewClient,並重寫shouldOverrideUrlLoading方法

    /**
     * 重寫此方法代表點擊網頁內的連接由本身處理,而不是新開Android的系統browser中響應該連接。
     */
    @Override
    public boolean shouldOverrideUrlLoading(WebView webView, String url) {
        Log.e(TAG,"{shouldOverrideUrlLoading}url="+url);
        if(url.startsWith("tel:")) {
            Intent intent = new Intent("android.intent.action.VIEW", Uri.parse(url));
            context.startActivity(intent);
            return true;
        }else{
            /*//view.loadUrl(url);//根據傳入的參數再去加載新的網頁
            return false;//表示當前的webview能夠處理打開新網頁的請求,不用藉助系統瀏覽器,【false 顯示frameset, true 不顯示Frameset】*/
            return super.shouldOverrideUrlLoading(webView,url);//爲了實現Bridge
        }
    }

 

2、本demo中Mainactivity.java、demo.html和JsBridge相關的最初始的代碼【在此基礎上根據實際狀況添加其餘代碼

一、demo.html文件

<html>
    <head>
        <meta content="text/html; charset=utf-8" http-equiv="content-type">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title>
            js和java互調
        </title>
    </head>
    
    <body>
        
    </body>
    <!--用於解析json數據-->
    <script type="text/javascript" src="json2.js"></script>
    <script>

/*=====================================JSBridge==================================================*/ //註冊事件監聽 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 Responds': 'js初始化響應!' }; responseCallback(data); }); //【Java調用的js方法】--用於js發送初始化後的消息給Java【由Java控制執行,在webviewClient的onPageFinished中執行】 //java執行onPageFinished後,調用這個方法;而後js發送消息給java;java接收並處理後回調js的initData()方法 bridge.registerHandler("sendMegToJavaFunctionInJs", function(data, responseCallback) { //發送消息(onPageFinished 能夠理解爲handle的message.what),告訴java,HTML頁面已經加載完成,能夠開始請求接口獲取數據了 window.WebViewJavascriptBridge.send( "onPageFinished" , function(responseData) { //responseData 能夠理解爲回調返回的字符串數據 initData(responseData); } ); responseCallback("js已發送消息給java");//java調用js方法,都要返回data數據,不過這裏由於是初始化的操做,因此返回空值便可。 }); }) /*=====webviewClient的onPageFinished執行後,js發送消息給java,而後java處理後回調js的方法======*/ function initData(data){ console.log("{initData}data="+data); //根據實際狀況,進行賦值;或者不作任何處理 } </script> </html>

二、MainActivity.java文件

package com.why.project.mybridgewebviewdemo;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.CallBackFunction;
import com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebView;
import com.why.project.mybridgewebviewdemo.customwebview.utils.WebviewGlobals;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    /**jsBridgeWebview*/
    private MyBridgeWebView myWebView;

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

        initViews();
        initDatas();
        initEvents();
    }

    private void initViews() {
        myWebView = findViewById(R.id.web_view);
    }

    private void initDatas() {
        myWebView.setDefaultHandler(new CustomBridgeHandler());//jsBridge //加載網址
        myWebView.loadLocalUrl("demo.html"); initJsBridge(); //實現webview只可滑動不可點擊【項目中須要用到的時候再解開註釋】 //http://blog.csdn.net/mjjmjc/article/details/47105001
        //http://blog.csdn.net/qq_32452623/article/details/52304628
        /*myWebView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { return true; } });*/
    }

    /*=================================jsBridge=================================*/
    /** * 自定義BridgeHandler【用於接收html發送給Java的消息(經過data的值區分是哪一個消息;function用於回調給js)】*/
    class CustomBridgeHandler implements BridgeHandler { @Override public void handler(String data, CallBackFunction function) { Log.i(TAG, "接收html發送給Java的消息(經過data的值區分是哪一個消息):" + data); if(data.equals("onPageFinished")){//onPageFinished 跟html中的保持一致 // TODO 請求接口獲取數據
                if(function != null){ function.onCallBack("這個是onPageFinished方法執行後js發送給java消息後,java回調給js的初始值"); } }else{  } } } //jsBridge 初始化一些事件監聽
    private void initJsBridge(){  } private void initEvents() {
        
    }

}

 

3、新增js發送消息給native的功能

一、在HTML界面中增長相似下面的代碼【綠色標記的是用來顯示java返回給js的數據

<html>
    <head>
        <meta content="text/html; charset=utf-8" http-equiv="content-type">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title>
            js和java互調
        </title>
    </head>
    
    <body>
        <p>
            <input type="text" id="show" style="width:100%;"/>
        </p>
        <p>
            <input type="button" id="enter" value="js發消息給Native" onclick="sendMegToJava();"
            />
        </p>
        
    </body>
    <!--用於解析json數據-->
    <script type="text/javascript" src="json2.js"></script>
    <script>


        //發消息給Native 按鈕的點擊事件
        //發送的消息是到BridgeHandler子類的handler方法中進行匹配
        function sendMegToJava() { //儘可能使用json數據
            var message = "getNewData";//消息數據(能夠直接是一個字符串,做爲消息類型(好比getNewData);也能夠是一個json字符串,根據key值進行判斷類型)
 window.WebViewJavascriptBridge.send( message , function(responseData) { document.getElementById("show").value = responseData; } ); }/*=====================================JSBridge==================================================*/
        //註冊事件監聽
        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 Responds': 'js初始化響應!'
                    };
              responseCallback(data);

            });
        })

        /*=====webviewClient的onPageFinished執行後,js發送消息給java,而後java處理後回調js的方法======*/
        function initData(data){
            console.log("{initData}data="+data);
            //根據實際狀況,進行賦值;或者不作任何處理
        }
    </script>

</html>

二、在java類中添加如下代碼

package com.why.project.mybridgewebviewdemo;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.CallBackFunction;
import com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebView;
import com.why.project.mybridgewebviewdemo.customwebview.utils.WebviewGlobals;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    /**jsBridgeWebview*/
    private MyBridgeWebView myWebView;

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

        initViews();
        initDatas();
        initEvents();
    }

    private void initViews() {
        myWebView = findViewById(R.id.web_view);
    }

    private void initDatas() {
        myWebView.setDefaultHandler(new CustomBridgeHandler());//jsBridge
        //加載網址
        myWebView.loadLocalUrl("demo.html");
        initJsBridge();

        //實現webview只可滑動不可點擊【項目中須要用到的時候再解開註釋】
        //http://blog.csdn.net/mjjmjc/article/details/47105001
        //http://blog.csdn.net/qq_32452623/article/details/52304628
        /*myWebView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });*/
    }

    /*=================================jsBridge=================================*/
    /**
     * 自定義BridgeHandler【用於接收html發送給Java的消息(經過data的值區分是哪一個消息;function用於回調給js)】*/
    class CustomBridgeHandler implements BridgeHandler {
        @Override
        public void handler(String data, CallBackFunction function) {
            Log.i(TAG, "接收html發送給Java的消息(經過data的值區分是哪一個消息):" + data);
            if(data.equals("onPageFinished")){//onPageFinished 跟html中的保持一致
                // TODO 請求接口獲取數據
                if(function != null){
                    function.onCallBack("這個是onPageFinished方法執行後js發送給java消息後,java回調給js的初始值");
                }
            }else{
                if(data.equals("getNewData")){ // TODO 請求接口獲取數據
                    if(function != null){ function.onCallBack("這個是js發送給java消息後返回的數據"); } }
            }
        }
    }

    //jsBridge 初始化一些事件監聽
    private void initJsBridge(){
    }

}

 

4、新增js調用native方法的功能

一、在HTML界面中增長相似下面的代碼【綠色標記的是用來顯示java返回給js的數據

<html>
    <head>
        <meta content="text/html; charset=utf-8" http-equiv="content-type">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title>
            js和java互調
        </title>
    </head>
    
    <body>
        <p>
            <input type="text" id="show" style="width:100%;"/>
        </p>
        <p>
            <input type="button" id="enter1" value="js調用Native的方法" onclick="callJavaMethod();"
            />
        </p>
    </body>
    <!--用於解析json數據-->
    <script type="text/javascript" src="json2.js"></script>
    <script>

//調用Native方法 按鈕的點擊事件 //調用的java方法須要在activity界面中進行聲明,參考initJsBridge()方法中的聲明方法 function callJavaMethod() { //儘可能使用json數據 var dataObj = new Object(); dataObj.id = 153273; dataObj.title = "這是一個標題" dataObj.isNew = true; var dataObjStr = JSON.stringify(dataObj); //functionInJava : 在Activity界面的initJsBridge()中聲明的方法 window.WebViewJavascriptBridge.callHandler( 'functionInJava' , {'param': dataObjStr} , function(responseData) { document.getElementById("show").value = responseData; } ); }/*=====================================JSBridge==================================================*/ //註冊事件監聽 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 Responds': 'js初始化響應!' }; responseCallback(data); }); //【Java調用的js方法】--用於js發送初始化後的消息給Java【由Java控制執行,在webviewClient的onPageFinished中執行】 //java執行onPageFinished後,調用這個方法;而後js發送消息給java;java接收並處理後回調js的initData()方法 bridge.registerHandler("sendMegToJavaFunctionInJs", function(data, responseCallback) { //發送消息(onPageFinished 能夠理解爲handle的message.what),告訴java,HTML頁面已經加載完成,能夠開始請求接口獲取數據了 window.WebViewJavascriptBridge.send( "onPageFinished" , function(responseData) { //responseData 能夠理解爲回調返回的字符串數據 initData(responseData); } ); responseCallback("js已發送消息給java");//java調用js方法,都要返回data數據,不過這裏由於是初始化的操做,因此返回空值便可。 }); }) /*=====webviewClient的onPageFinished執行後,js發送消息給java,而後java處理後回調js的方法======*/ function initData(data){ console.log("{initData}data="+data); //根據實際狀況,進行賦值;或者不作任何處理 } </script> </html>

二、在java類中添加如下代碼

package com.why.project.mybridgewebviewdemo;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.CallBackFunction;
import com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebView;
import com.why.project.mybridgewebviewdemo.customwebview.utils.WebviewGlobals;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    /**jsBridgeWebview*/
    private MyBridgeWebView myWebView;

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

        initViews();
        initDatas();
        initEvents();
    }

    private void initViews() {
        myWebView = findViewById(R.id.web_view);
    }

    private void initDatas() {
        myWebView.setDefaultHandler(new CustomBridgeHandler());//jsBridge
        //加載網址
        myWebView.loadLocalUrl("demo.html");
        initJsBridge();

        //實現webview只可滑動不可點擊【項目中須要用到的時候再解開註釋】
        //http://blog.csdn.net/mjjmjc/article/details/47105001
        //http://blog.csdn.net/qq_32452623/article/details/52304628
        /*myWebView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });*/
    }

    /*=================================jsBridge=================================*/
    /**
     * 自定義BridgeHandler【用於接收html發送給Java的消息(經過data的值區分是哪一個消息;function用於回調給js)】*/
    class CustomBridgeHandler implements BridgeHandler {
        @Override
        public void handler(String data, CallBackFunction function) {
            Log.i(TAG, "接收html發送給Java的消息(經過data的值區分是哪一個消息):" + data);
            if(data.equals("onPageFinished")){//onPageFinished 跟html中的保持一致
                // TODO 請求接口獲取數據
                if(function != null){
                    function.onCallBack("這個是onPageFinished方法執行後js發送給java消息後,java回調給js的初始值");
                }
            }else{
            }
        }
    }

    //jsBridge 初始化一些事件監聽
    private void initJsBridge(){
        //【js調用Java的方法】必須和js中的調用函數名相同,註冊具體執行函數,相似java實現類。
        myWebView.registerHandler("functionInJava", new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { Log.i(TAG, "接收html發送給Java的數據:" + data); String callbackData = "這個是js調用java方法後返回的數據"; function.onCallBack(callbackData); } });
    }

    private void initEvents() {
    }

}

 

5、新增native調用js方法的功能

一、在HTML界面中增長相似下面的代碼【綠色標記的是用來顯示java返回給js的數據

<html>
    <head>
        <meta content="text/html; charset=utf-8" http-equiv="content-type">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title>
            js和java互調
        </title>
    </head>
    
    <body>
        <p>
            <input type="text" id="show" style="width:100%;"/>
        </p>
        
    </body>
    <!--用於解析json數據-->
    <script type="text/javascript" src="json2.js"></script>
    <script>

//java調用js方法實際執行的方法 function handleJavaData(dataObj){ document.getElementById("show").value = "用戶名=" + dataObj.username + ";密碼=" + dataObj.password; return "登陸成功呢"; } /*=====================================JSBridge==================================================*/ //註冊事件監聽 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 Responds': 'js初始化響應!' }; responseCallback(data); }); //【Java調用的js方法】--用於js發送初始化後的消息給Java【由Java控制執行,在webviewClient的onPageFinished中執行】 //java執行onPageFinished後,調用這個方法;而後js發送消息給java;java接收並處理後回調js的initData()方法 bridge.registerHandler("sendMegToJavaFunctionInJs", function(data, responseCallback) { //發送消息(onPageFinished 能夠理解爲handle的message.what),告訴java,HTML頁面已經加載完成,能夠開始請求接口獲取數據了 window.WebViewJavascriptBridge.send( "onPageFinished" , function(responseData) { //responseData 能夠理解爲回調返回的字符串數據 initData(responseData); } ); responseCallback("js已發送消息給java");//java調用js方法,都要返回data數據,不過這裏由於是初始化的操做,因此返回空值便可。 }); /*============================自定義java調用的js方法聲明【根據實際狀況聲明方法】===========================================*/ //【Java調用的js方法】 bridge.registerHandler("functionInJs", function(data, responseCallback) { //JSON.parse(jsonstr); //方法一:能夠將json字符串轉換成json對象 //JSON.stringify(jsonobj); //方法二:能夠將json對象轉換成json對符串 var dataObj = JSON.parse(data);//將發送過來的數據轉爲json對象 //通常都有一個配套的js方法,用於處理接收到的數據 var responseData = handleJavaData(dataObj); responseCallback(responseData); }); }) /*=====webviewClient的onPageFinished執行後,js發送消息給java,而後java處理後回調js的方法======*/ function initData(data){ console.log("{initData}data="+data); //根據實際狀況,進行賦值;或者不作任何處理 } </script> </html>

二、在java類中添加如下代碼

package com.why.project.mybridgewebviewdemo;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.CallBackFunction;
import com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebView;
import com.why.project.mybridgewebviewdemo.customwebview.utils.WebviewGlobals;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    /**jsBridgeWebview*/
    private MyBridgeWebView myWebView;

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

        initViews();
        initDatas();
        initEvents();
    }

    private void initViews() {
        myWebView = findViewById(R.id.web_view);
    }

    private void initDatas() {
        myWebView.setDefaultHandler(new CustomBridgeHandler());//jsBridge
        //加載網址
        myWebView.loadLocalUrl("demo.html");
        initJsBridge();

        //實現webview只可滑動不可點擊【項目中須要用到的時候再解開註釋】
        //http://blog.csdn.net/mjjmjc/article/details/47105001
        //http://blog.csdn.net/qq_32452623/article/details/52304628
        /*myWebView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });*/
    }

    /*=================================jsBridge=================================*/
    /**
     * 自定義BridgeHandler【用於接收html發送給Java的消息(經過data的值區分是哪一個消息;function用於回調給js)】*/
    class CustomBridgeHandler implements BridgeHandler {
        @Override
        public void handler(String data, CallBackFunction function) {
            Log.i(TAG, "接收html發送給Java的消息(經過data的值區分是哪一個消息):" + data);
            if(data.equals("onPageFinished")){//onPageFinished 跟html中的保持一致
                // TODO 請求接口獲取數據
                if(function != null){
                    function.onCallBack("這個是onPageFinished方法執行後js發送給java消息後,java回調給js的初始值");
                }
            }else{
            }
        }
    }

    //jsBridge 初始化一些事件監聽
    private void initJsBridge(){
    }

    private void initEvents() {
        findViewById(R.id.btn_calljsfunction).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Java調用js的方法 //發送給js的參數,使用Json格式
                String params = "{\"username\":\"why\",\"password\":\"123456\"}"; myWebView.callHandler("functionInJs",params, new CallBackFunction() { @Override public void onCallBack(String data) { // TODO Auto-generated method stub //處理html返回給Java的數據
                        Toast.makeText(MainActivity.this,data,Toast.LENGTH_SHORT).show(); } });
            }
        });
    }

}

 

6、選擇文件的功能

一、在HTML界面中增長相似下面的代碼

<html>
    <head>
        <meta content="text/html; charset=utf-8" http-equiv="content-type">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title>
            js和java互調
        </title>
    </head>
    
    <body>
        <p>
            <input type="file" value="打開文件" />
        </p>
    </body>
    <script>
</script>

</html>

二、在java類中添加如下代碼

package com.why.project.mybridgewebviewdemo;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.CallBackFunction;
import com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebView;
import com.why.project.mybridgewebviewdemo.customwebview.utils.WebviewGlobals;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    /**jsBridgeWebview*/
    private MyBridgeWebView myWebView;

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

        initViews();
        initDatas();
        initEvents();
    }

    private void initViews() {
        myWebView = findViewById(R.id.web_view);
    }

    private void initDatas() {
        myWebView.setDefaultHandler(new CustomBridgeHandler());//jsBridge
        //加載網址
        myWebView.loadLocalUrl("demo.html");
        initJsBridge();

        //實現webview只可滑動不可點擊【項目中須要用到的時候再解開註釋】
        //http://blog.csdn.net/mjjmjc/article/details/47105001
        //http://blog.csdn.net/qq_32452623/article/details/52304628
        /*myWebView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });*/
    }

    /*=================================jsBridge=================================*/
    /**
     * 自定義BridgeHandler【用於接收html發送給Java的消息(經過data的值區分是哪一個消息;function用於回調給js)】*/
    class CustomBridgeHandler implements BridgeHandler {
        @Override
        public void handler(String data, CallBackFunction function) {
            Log.i(TAG, "接收html發送給Java的消息(經過data的值區分是哪一個消息):" + data);
            if(data.equals("onPageFinished")){//onPageFinished 跟html中的保持一致
                // TODO 請求接口獲取數據
                if(function != null){
                    function.onCallBack("這個是onPageFinished方法執行後js發送給java消息後,java回調給js的初始值");
                }
            }else{
            }
        }
    }

    //jsBridge 初始化一些事件監聽
    private void initJsBridge(){
    }

    private void initEvents() {
    }

    /*=========================================實現webview調用選擇文件的功能==============================================*/ @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.w(TAG, "{onActivityResult}resultCode="+resultCode); Log.w(TAG, "{onActivityResult}requestCode="+requestCode); Log.w(TAG, "{onActivityResult}data="+data); if (resultCode == Activity.RESULT_OK) { //webview界面調用打開本地文件管理器選擇文件的回調
            if (requestCode == WebviewGlobals.CHOOSE_FILE_REQUEST_CODE ) { Uri result = data == null ? null : data.getData(); Log.w(TAG,"{onActivityResult}文件路徑地址:" + result.toString()); //若是mUploadMessage或者mUploadCallbackAboveL不爲空,表明是觸發input[type]類型的標籤
                if (null != myWebView.getMyBridgeWebChromeClient().getmUploadMessage() || null != myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL()) { if (myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL() != null) { onActivityResultAboveL(requestCode, data);//5.0++
                    } else if (myWebView.getMyBridgeWebChromeClient().getmUploadMessage() != null) { myWebView.getMyBridgeWebChromeClient().getmUploadMessage().onReceiveValue(result);//將文件路徑返回去,填充到input中
                        myWebView.getMyBridgeWebChromeClient().setmUploadMessage(null); } }else{ //此處代碼是處理經過js方法觸發的狀況
                    Log.w(TAG,"{onActivityResult}文件路徑地址(js):" + result.toString()); } } }else if(resultCode == RESULT_CANCELED){//resultCode == RESULT_CANCELED 解決不選擇文件,直接返回後沒法再次點擊的問題
            if (myWebView.getMyBridgeWebChromeClient().getmUploadMessage() != null) { myWebView.getMyBridgeWebChromeClient().getmUploadMessage().onReceiveValue(null); myWebView.getMyBridgeWebChromeClient().setmUploadMessage(null); } if (myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL() != null) { myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL().onReceiveValue(null); myWebView.getMyBridgeWebChromeClient().setmUploadCallbackAboveL(null); } } } //5.0以上版本,因爲api不同,要單獨處理
 @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void onActivityResultAboveL(int requestCode, Intent data) { if (myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL() == null) { return; } Uri result = null; if (requestCode == WebviewGlobals.CHOOSE_FILE_REQUEST_CODE) {//打開本地文件管理器選擇圖片
            result = data == null ? null : data.getData(); } Log.w(TAG,"{onActivityResultAboveL}文件路徑地址:"+result.toString()); myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL().onReceiveValue(new Uri[]{result});//將文件路徑返回去,填充到input中
        myWebView.getMyBridgeWebChromeClient().setmUploadCallbackAboveL(null); return; }

}

 

使用步驟

1、項目組織結構圖

注意事項:java

一、  導入類文件後須要change包名以及從新import R文件路徑android

二、  Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),若是項目中存在,則複製裏面的內容,不要整個覆蓋git

2、導入步驟

一、在app的build.gradle文件中引用JsBridge第三方庫

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.why.project.mybridgewebviewdemo"
        minSdkVersion 16
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
//jsbridge repositories{ //jsBridge maven { url "https://jitpack.io" } }

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    //jsBridge compile 'com.github.lzyzsd:jsbridge:1.0.4'
}

二、將assets文件夾複製到項目中

demo.html【用於演示選擇文件、js發消息給native、js調用native的方法、native調用js方法的功能】github

<html>
    <head>
        <meta content="text/html; charset=utf-8" http-equiv="content-type">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title>
            js和java互調
        </title>
    </head>
    
    <body>
        <p>
            <input type="text" id="show" style="width:100%;"/>
        </p>
        <p>
            <input type="button" id="enter" value="js發消息給Native" onclick="sendMegToJava();"
            />
        </p>
        <p>
            <input type="button" id="enter1" value="js調用Native的方法" onclick="callJavaMethod();"
            />
        </p>
        <p>
            <input type="file" value="打開文件" />
        </p>
    </body>
    <!--用於解析json數據-->
    <script type="text/javascript" src="json2.js"></script>
    <script>


        //發消息給Native 按鈕的點擊事件
        //發送的消息是到BridgeHandler子類的handler方法中進行匹配
        function sendMegToJava() {
            //儘可能使用json數據
            var message = "getNewData";//消息數據(能夠直接是一個字符串,做爲消息類型(好比getNewData);也能夠是一個json字符串,根據key值進行判斷類型)
            window.WebViewJavascriptBridge.send(
                message
                , function(responseData) {
                    document.getElementById("show").value = responseData;
                }
            );
        }

        //調用Native方法  按鈕的點擊事件
        //調用的java方法須要在activity界面中進行聲明,參考initJsBridge()方法中的聲明方法
        function callJavaMethod() {
            //儘可能使用json數據
            var dataObj = new Object();
            dataObj.id = 153273;
            dataObj.title = "這是一個標題"
            dataObj.isNew = true;
            var dataObjStr = JSON.stringify(dataObj);

            //functionInJava : 在Activity界面的initJsBridge()中聲明的方法
            window.WebViewJavascriptBridge.callHandler(
                'functionInJava'
                , {'param': dataObjStr}
                , function(responseData) {
                    document.getElementById("show").value = responseData;
                }
            );
        }

        //java調用js方法實際執行的方法
        function handleJavaData(dataObj){
            document.getElementById("show").value = "用戶名=" + dataObj.username + ";密碼=" + dataObj.password;
            return "登陸成功呢";
        }

        /*=====================================JSBridge==================================================*/
        //註冊事件監聽
        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 Responds': 'js初始化響應!'
                    };
              responseCallback(data);

            });

            //【Java調用的js方法】--用於js發送初始化後的消息給Java【由Java控制執行,在webviewClient的onPageFinished中執行】
            //java執行onPageFinished後,調用這個方法;而後js發送消息給java;java接收並處理後回調js的initData()方法
            bridge.registerHandler("sendMegToJavaFunctionInJs", function(data, responseCallback) {
                //發送消息(onPageFinished 能夠理解爲handle的message.what),告訴java,HTML頁面已經加載完成,能夠開始請求接口獲取數據了
                window.WebViewJavascriptBridge.send(
                    "onPageFinished"
                    , function(responseData) {
                        //responseData 能夠理解爲回調返回的字符串數據
                        initData(responseData);
                    }
                );
                responseCallback("js已發送消息給java");//java調用js方法,都要返回data數據,不過這裏由於是初始化的操做,因此返回空值便可。
            });

            /*============================自定義java調用的js方法聲明【根據實際狀況聲明方法】===========================================*/
            //【Java調用的js方法】
            bridge.registerHandler("functionInJs", function(data, responseCallback) {
                //JSON.parse(jsonstr); //方法一:能夠將json字符串轉換成json對象
                //JSON.stringify(jsonobj); //方法二:能夠將json對象轉換成json對符串

                var dataObj = JSON.parse(data);//將發送過來的數據轉爲json對象

                //通常都有一個配套的js方法,用於處理接收到的數據
                var responseData = handleJavaData(dataObj);

                responseCallback(responseData);
            });
        })

        /*=====webviewClient的onPageFinished執行後,js發送消息給java,而後java處理後回調js的方法======*/
        function initData(data){
            console.log("{initData}data="+data);
            //根據實際狀況,進行賦值;或者不作任何處理
            document.getElementById("show").value = data;
        }
    </script>

</html>
demo.html

三、將customwebview包複製到項目中

四、將mybridgewebview_progress_dialog_img_drawable.xml複製到項目中

<?xml version="1.0" encoding="utf-8"?>
<!-- WebView使用的進度加載對話框進度圓圈 -->
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/mybridgewebview_progress_dialog_img"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromDegrees="0.0"
    android:toDegrees="360.0"
    android:repeatMode="restart"
     />
mybridgewebview_progress_dialog_img_drawable.xml

五、將mybridgewebview_progress_dialog_img.png圖片複製到項目中

六、將mybridgewebview_dialog_webviewprogress.xml複製到項目中

<?xml version="1.0" encoding="utf-8"?>
<!-- WebView使用的進度加載對話框佈局文件 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialog_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <!-- 自定義圓形進度條 -->
    <!-- android:indeterminateDrawable自定義動畫圖標 -->
    <ProgressBar
        android:id="@+id/loadProgressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:indeterminateDrawable="@drawable/mybridgewebview_progress_dialog_img_drawable"
        />

</RelativeLayout>
mybridgewebview_dialog_webviewprogress.xml

七、在styles.xml文件中添加如下代碼

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <!-- ==================MyBridgeWebView========網頁加載時的進度對話框========================== -->
    <style name="mybridgewebview_loading_style" parent="android:style/Theme.Dialog">
        <!-- Dialog的windowFrame框爲無 -->
        <item name="android:windowFrame">@null</item>
        <!-- 是否顯示title -->
        <item name="android:windowNoTitle">true</item>
        <!-- 是否浮如今activity之上 -->
        <item name="android:windowIsFloating">true</item>
        <!-- 設置dialog的背景:#00000000透明色 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- 半透明 -->
        <item name="android:windowIsTranslucent">true</item>
        <!-- 背景變灰:整個屏幕變灰,配合setCanceledOnTouchOutside(false) -->
        <item name="android:backgroundDimEnabled">false</item>
        <!-- 對話框是否有遮蓋 -->
        <item name="android:windowContentOverlay">@null</item>
    </style>

</resources>

八、在AndroidManifest.xml中添加如下代碼

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.why.project.mybridgewebviewdemo">

    <!-- ======================(MyBridgeWebView)========================== -->
    <!-- 容許程序打開網絡套接字 -->
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

3、使用方法

在佈局文件activity_main.xml中聲明【實際項目中實際新的完整路徑

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#bbbcbc"
    android:orientation="vertical">

    <!-- button 演示Java調用web -->
    <Button
        android:id="@+id/btn_calljsfunction"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:text="Native調用Js方法"
        />

    <com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

</LinearLayout>

在Activity中使用以下

package com.why.project.mybridgewebviewdemo;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.CallBackFunction;
import com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebView;
import com.why.project.mybridgewebviewdemo.customwebview.utils.WebviewGlobals;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    /**jsBridgeWebview*/
    private MyBridgeWebView myWebView;

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

        initViews();
        initDatas();
        initEvents();
    }

    private void initViews() {
        myWebView = findViewById(R.id.web_view);
    }

    private void initDatas() {
        myWebView.setDefaultHandler(new CustomBridgeHandler());//jsBridge
        //加載網址
        myWebView.loadLocalUrl("demo.html");
        initJsBridge();

        //實現webview只可滑動不可點擊【項目中須要用到的時候再解開註釋】
        //http://blog.csdn.net/mjjmjc/article/details/47105001
        //http://blog.csdn.net/qq_32452623/article/details/52304628
        /*myWebView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });*/
    }

    /*=================================jsBridge=================================*/
    /**
     * 自定義BridgeHandler【用於接收html發送給Java的消息(經過data的值區分是哪一個消息;function用於回調給js)】*/
    class CustomBridgeHandler implements BridgeHandler {
        @Override
        public void handler(String data, CallBackFunction function) {
            Log.i(TAG, "接收html發送給Java的消息(經過data的值區分是哪一個消息):" + data);
            if(data.equals("onPageFinished")){//onPageFinished 跟html中的保持一致
                // TODO 請求接口獲取數據
                if(function != null){
                    function.onCallBack("這個是onPageFinished方法執行後js發送給java消息後,java回調給js的初始值");
                }
            }else{
                if(data.equals("getNewData")){
                    // TODO 請求接口獲取數據
                    if(function != null){
                        function.onCallBack("這個是js發送給java消息後返回的數據");
                    }
                }
            }
        }
    }

    //jsBridge 初始化一些事件監聽
    private void initJsBridge(){
        //【js調用Java的方法】必須和js中的調用函數名相同,註冊具體執行函數,相似java實現類。
        myWebView.registerHandler("functionInJava", new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {
                Log.i(TAG, "接收html發送給Java的數據:" + data);

                String callbackData = "這個是js調用java方法後返回的數據";
                function.onCallBack(callbackData);
            }
        });
    }

    private void initEvents() {
        findViewById(R.id.btn_calljsfunction).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Java調用js的方法
                //發送給js的參數,使用Json格式
                String params = "{\"username\":\"why\",\"password\":\"123456\"}";
                myWebView.callHandler("functionInJs",params, new CallBackFunction() {
                    @Override
                    public void onCallBack(String data) {
                        // TODO Auto-generated method stub
                        //處理html返回給Java的數據
                        Toast.makeText(MainActivity.this,data,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

    /*=========================================實現webview調用選擇文件的功能==============================================*/
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.w(TAG, "{onActivityResult}resultCode="+resultCode);
        Log.w(TAG, "{onActivityResult}requestCode="+requestCode);
        Log.w(TAG, "{onActivityResult}data="+data);
        if (resultCode == Activity.RESULT_OK) {
            //webview界面調用打開本地文件管理器選擇文件的回調
            if (requestCode == WebviewGlobals.CHOOSE_FILE_REQUEST_CODE ) {
                Uri result = data == null ? null : data.getData();
                Log.w(TAG,"{onActivityResult}文件路徑地址:" + result.toString());

                //若是mUploadMessage或者mUploadCallbackAboveL不爲空,表明是觸發input[type]類型的標籤
                if (null != myWebView.getMyBridgeWebChromeClient().getmUploadMessage() || null != myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL()) {
                    if (myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL() != null) {
                        onActivityResultAboveL(requestCode, data);//5.0++
                    } else if (myWebView.getMyBridgeWebChromeClient().getmUploadMessage() != null) {
                        myWebView.getMyBridgeWebChromeClient().getmUploadMessage().onReceiveValue(result);//將文件路徑返回去,填充到input中
                        myWebView.getMyBridgeWebChromeClient().setmUploadMessage(null);
                    }
                }else{
                    //此處代碼是處理經過js方法觸發的狀況
                    Log.w(TAG,"{onActivityResult}文件路徑地址(js):" + result.toString());
                }
            }
        }else if(resultCode == RESULT_CANCELED){//resultCode == RESULT_CANCELED 解決不選擇文件,直接返回後沒法再次點擊的問題
            if (myWebView.getMyBridgeWebChromeClient().getmUploadMessage() != null) {
                myWebView.getMyBridgeWebChromeClient().getmUploadMessage().onReceiveValue(null);
                myWebView.getMyBridgeWebChromeClient().setmUploadMessage(null);
            }
            if (myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL() != null) {
                myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL().onReceiveValue(null);
                myWebView.getMyBridgeWebChromeClient().setmUploadCallbackAboveL(null);
            }
        }
    }

    //5.0以上版本,因爲api不同,要單獨處理
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void onActivityResultAboveL(int requestCode, Intent data) {

        if (myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL() == null) {
            return;
        }
        Uri result = null;
        if (requestCode == WebviewGlobals.CHOOSE_FILE_REQUEST_CODE) {//打開本地文件管理器選擇圖片
            result = data == null ? null : data.getData();
        }
        Log.w(TAG,"{onActivityResultAboveL}文件路徑地址:"+result.toString());
        myWebView.getMyBridgeWebChromeClient().getmUploadCallbackAboveL().onReceiveValue(new Uri[]{result});//將文件路徑返回去,填充到input中
        myWebView.getMyBridgeWebChromeClient().setmUploadCallbackAboveL(null);
        return;
    }

}

混淆配置

注意:根據實際項目的路徑修改下面表紅色的文字web

# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

#====WebView + js==== -keepclassmembers class com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebView { public *; } -keepclassmembers class com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebChromeClient { public *; } -keepclassmembers class com.why.project.mybridgewebviewdemo.customwebview.jsbridgewebview.MyBridgeWebViewClient { public *; } # keep 使用 webview 的類 -keepclassmembers class com.why.project.mybridgewebviewdemo.MainActivity { public *; } -keepattributes *Annotation* #解決:android sdk api >= 17 時須要加@JavascriptInterface」所出現的問題。 -keepattributes *JavascriptInterface*

參考資料

JsBridgejson

項目demo下載地址

https://github.com/haiyuKing/MyBridgeWebViewDemoapi

相關文章
相關標籤/搜索