Android WebView與 JS 的交互方式總結

越來越多的應用采用原生代碼與Html混合開發(fā)的方式,對于這種類型的應用导坟,Android如何與JS進行交互呢溃论?本篇就對交互方式進行總結。

這邊先列下各種交互方式:


image.png

一色解、WebView加載Html

加載Html的方式這里簡單列一下茂嗓,webview的設置這邊不做詳細講解。

        //加載assets里的test.html
        mWebView.loadUrl("file:///android_asset/test.html");
        //加載網(wǎng)頁
        mWebView.loadUrl("https://www.baidu.com/");

二科阎、Android調用Html里的JS方法

1述吸、通過WebView的loadUrl () 方法調用JS方法

調用方式:WebView.loadUrl("javascript:<方法名>(<有參數(shù)時傳參>)");
具體代碼:

public class MainActivity extends AppCompatActivity {

    WebView mWebView;
    Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWebView = findViewById(R.id.wv);
        mButton = findViewById(R.id.btn);

        // 獲取WebSetting對象
        WebSettings webSettings = mWebView.getSettings();
        // 設置支持javascript
        webSettings.setJavaScriptEnabled(true);
        // 設置允許JS彈窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        mWebView.setWebChromeClient(new WebChromeClient());

        //加載assets里的test.html
        mWebView.loadUrl("file:///android_asset/test.html");
        //加載網(wǎng)頁
        //mWebView.loadUrl("https://www.baidu.com/");
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //調用js要在webview加載完才可以調用
                mWebView.post(new Runnable() {
                    @Override
                    public void run() {
                        //方法名fucn1要寫對,傳入的參數(shù)要用單引號或雙引號引用锣笨,雙引號注意要用轉義字符
                        mWebView.loadUrl("javascript:func1('a1a')");
                    }
                });
            }
        });
    }
}

test.html代碼:

<html>
<body>
<script type="text/javascript">
document.write("<h1>Hello World!</h1>")
function func1(str){
      alert("Android調用了JS的func1方法--"+str);
}
</script>
</body>
</html>

該種方式簡單但是獲取JS返回值較麻煩蝌矛。

2道批、通過WebView的evaluateJavascript ()方法調用JS方法(可以獲取返回值)

只需要將loadUrl()換成下面該方法即可

mWebView.evaluateJavascript("javascript:func1('a1a')", new ValueCallback<String>() {
                                @Override
                                public void onReceiveValue(String value) {//value為 js 返回的值

                                }
                            });

該方法在android版本19以下不能使用,所以最好配合方法1使用朴读,如下:

if(Build.VERSION.SDK_INT<Build.VERSION_CODES.KITKAT) {
       //方法名fucn1要寫對屹徘,傳入的參數(shù)要用單引號或雙引號引用,雙引號注意要用轉義字符
      mWebView.loadUrl("javascript:func1('a1a')");
}else {

      mWebView.evaluateJavascript("javascript:func1('a1a')", new ValueCallback<String>() {
          @Override
          public void onReceiveValue(String value) {//value為 js 返回的值
          }
      });
}

三衅金、JS調用Android代碼

1噪伊、通過WebView的addJavascriptInterface () 進行對象映射

首先,定義一個要被JS調用的類氮唯,被調用的方法加@JavascriptInterface注解鉴吹。

public class CallByJS{
        // 被JS調用的方法必須加@JavascriptInterface注解
        @JavascriptInterface
        public void callByJS(String str) {
            Log.e("web_test",str);
        }
    }

然后在WebView里通過addJavascriptInterface()將Java對象映射到JS對象。

        // 通過addJavascriptInterface()將Java對象映射到JS對象
        mWebView.addJavascriptInterface(new CallByJS(), "androidObj");

接下來JS就可以通過androidObj調用CallByJS對象的方法了惩琉。

<html>
<body>
<script type="text/javascript">
<!--document.write("<h1>Hello World!</h1>")-->
function func1(str){
      alert("Android調用了JS的func1方法--"+str);
      return "jsjs";
}
function clickBtn(){
    androidObj.callByJS("JS調用了Android的方法");
}
</script>
<button type="button" id="btn" onclick="clickBtn()">點擊調用Android代碼</button>
</body>
</html>

運行豆励,點擊調用按鈕


image.png

Logcat里日志如下,說明JS調用了android的代碼瞒渠。


image.png

2良蒸、通過 WebViewClient 的shouldOverrideUrlLoading ()方法攔截 url。

這種方式就是Android通過 WebViewClient 的回調方法shouldOverrideUrlLoading ()攔截 url伍玖,解析該 url 的協(xié)議嫩痰,如果檢測到是預先約定好的協(xié)議,就執(zhí)行相應方法 窍箍。

 mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // 根據(jù)協(xié)議的參數(shù)進行攔截,下面攔截"callandroid://test"
                // 一般根據(jù)scheme & authority判斷
                Uri uri = Uri.parse(url);
                // 如果 scheme  = callAndroid串纺,即代表都符合約定的協(xié)議
                if (uri.getScheme().equals("callandroid")) {

                    // 如果 authority  = test,即代表都符合約定的協(xié)議
                    if (uri.getAuthority().equals("test")) {// 攔截url,下面開始執(zhí)行Android的方法

                        Toast.makeText(MainActivity.this, "js通過攔截調用了Android的方法", Toast.LENGTH_SHORT).show();
                        // 可以獲取參數(shù)
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> paramNames = uri.getQueryParameterNames();
                        for (String name : paramNames) {
                            params.put(name, uri.getQueryParameter(name));
                        }

                        Log.e("web-test", params.toString());

                    }

                    return true;
                }
                return super.shouldOverrideUrlLoading(view, url);

            }
        });

接下來在Html里調用椰棘,下面的clickBtn2()方法:

<html>
<body>
<script type="text/javascript">
<!--document.write("<h1>Hello World!</h1>")-->
function func1(str){
      alert("Android調用了JS的func1方法--"+str);
      return "jsjs";
}
function clickBtn(){
    androidObj.callByJS("JS調用了Android的方法");
}
function clickBtn2(){
    document.location = "callandroid://test?arg1=abc&arg2=202";
}

</script>
<button type="button" id="btn" onclick="clickBtn()">點擊調用Android代碼</button>
<button type="button" id="btn2" onclick="clickBtn2()">通過攔截調用Android代碼</button>
</body>
</html>

運行程序纺棺,點擊第二個按鈕,執(zhí)行shouldOverrideUrlLoading方法邪狞,鏈接被攔截祷蝌,開始執(zhí)行對應的業(yè)務邏輯代碼:


image.png

也可以獲取參數(shù),Logcat打印出參數(shù)如下:


image.png

該方法JS無法直接獲取android代碼的返回值帆卓,需要android調用JS方法的方式把返回值傳給JS杆逗。

3、通過 WebChromeClient 的onJsAlert ()鳞疲、onJsConfirm ()、onJsPrompt ()方法攔截JS對話框alert ()蠕蚜、confirm ()尚洽、prompt ()消息

該方式就是Android通過 WebChromeClient 的onJsAlert()、onJsConfirm()靶累、onJsPrompt()方法分別攔截JS的alert()腺毫,confirm()癣疟,prompt()彈出框。

下面寫個onJsPrompt()攔截prompt()的例子潮酒。
首先重寫onJsPrompt方法睛挚,攔截方式與方式2類似。

mWebView.setWebChromeClient(new WebChromeClient(){
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                return super.onJsConfirm(view, url, message, result);
            }

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                // 根據(jù)協(xié)議的參數(shù)進行攔截,下面攔截"callandroid://test"
                // 一般根據(jù)scheme & authority判斷
                Uri uri = Uri.parse(message);//message是由JS的prompt()傳來的
                // 如果 scheme  = callAndroid急黎,即代表都符合約定的協(xié)議
                if (uri.getScheme().equals("callandroid")) {

                    // 如果 authority  = test扎狱,即代表都符合約定的協(xié)議
                    if (uri.getAuthority().equals("test")) {// 攔截url,下面開始執(zhí)行Android的方法

                        // 可以獲取參數(shù)
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> paramNames = uri.getQueryParameterNames();
                        for (String name : paramNames) {
                            params.put(name, uri.getQueryParameter(name));
                        }
                        //將返回值返回給JS
                        result.confirm("攔截Prompt成功啦,傳進來的參數(shù)是:"+params.toString());
                    }
                    return true;
                }
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }
        });

接下來在Html用JS調用

<html>
<body>
<script type="text/javascript">
<!--document.write("<h1>Hello World!</h1>")-->
function func1(str){
      alert("Android調用了JS的func1方法--"+str);
      return "jsjs";
}
function clickBtn(){
    androidObj.callByJS("JS調用了Android的方法");
}
function clickBtn2(){
    document.location = "callandroid://test?arg1=abc&arg2=202";
}
function clickBtn3(){
    <!--這邊會被攔截,可以取得返回值-->
    var str = prompt("callandroid://test?arg1=btn3");
    alert(str);
}

</script>
<button type="button" id="btn" onclick="clickBtn()">點擊調用Android代碼</button>
<button type="button" id="btn2" onclick="clickBtn2()">通過攔截調用Android代碼</button>
<Br/>
<button type="button" id="btn3" onclick="clickBtn3()">攔截prompt</button>
</body>
</html>

執(zhí)行代碼勃教,點擊按鈕3:


image.png

其他兩個方法攔截也類似淤击,只不過alert ()沒有返回值,confirm ()返回值是boolean類型故源。

項目源碼地址:https://gitee.com/wiggins/WebviewJsTest.git

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末污抬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子绳军,更是在濱河造成了極大的恐慌印机,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件门驾,死亡現(xiàn)場離奇詭異射赛,居然都是意外死亡,警方通過查閱死者的電腦和手機猎唁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門咒劲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诫隅,你說我怎么就攤上這事腐魂。” “怎么了逐纬?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵蛔屹,是天一觀的道長。 經(jīng)常有香客問我豁生,道長兔毒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任甸箱,我火速辦了婚禮育叁,結果婚禮上,老公的妹妹穿的比我還像新娘芍殖。我一直安慰自己豪嗽,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著龟梦,像睡著了一般隐锭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上计贰,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天钦睡,我揣著相機與錄音,去河邊找鬼躁倒。 笑死荞怒,一個胖子當著我的面吹牛,可吹牛的內容都是我干的樱溉。 我是一名探鬼主播挣输,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼福贞!你這毒婦竟也來了撩嚼?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤挖帘,失蹤者是張志新(化名)和其女友劉穎完丽,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拇舀,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡逻族,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了骄崩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片聘鳞。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖要拂,靈堂內的尸體忽然破棺而出抠璃,到底是詐尸還是另有隱情,我是刑警寧澤脱惰,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布搏嗡,位于F島的核電站,受9級特大地震影響拉一,放射性物質發(fā)生泄漏采盒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一蔚润、第九天 我趴在偏房一處隱蔽的房頂上張望磅氨。 院中可真熱鬧,春花似錦嫡纠、人聲如沸悍赢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽左权。三九已至,卻和暖如春痴颊,著一層夾襖步出監(jiān)牢的瞬間赏迟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工蠢棱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锌杀,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓泻仙,卻偏偏與公主長得像糕再,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子玉转,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355