Android 與 WebView 中的 Javascript 相互溝通

最近的一個 app 需要讓 Android 可以呼叫 WebView 中的 Javascript,並且按下 WebView 中的按鈕時,也可以呼叫 Android 內部的方法,這篇文章記錄一下大概的做法,免得下次遇到又忘記 …

這個 app 需要做到的功能很簡單,在 Android 端希望可以點選「字體放大」、「字體縮小」的按鈕來呼叫 WebView 中的 Javascript;並且點選 WebView 中的行事曆按鈕後,可以開啟 Android 內建的 Google 行事曆。

透過 Android 本身的按鈕來達到呼叫 Javascript 的功能很簡單,以小蛙的例子是用 fragment 中放置一個 WebView

01
02
03
04
05
06
07
08
09
10
11
12
// 取得 WebView 物件
WebView wv = (WebView) v.findViewById(R.id.webView1);
// 設定此 WebView 支援 Javascript
wv.getSettings().setJavaScriptEnabled(true);
// 取得按鈕物件
Button b = (Button) v.findViewById(R.id.button1);
b.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
                wv.loadUrl("javascript:fontSize('+')");
    }
});

上面的程式碼只寫出個大概,取得 WebView 後設定支援 Javascript,並且設定按鈕來執行 Javascript,上面例子小蛙 WebView 中有一個字體放大的 Javascript 叫做 fontSize(‘+’),因此直接使用 wv.loadUrl(‘要呼叫的 Javascript’); 即可!

  • 從 WebView 呼叫 Android Function

這個部分就比較複雜一些些,首先必須先建立一個 JavascriptInterface 物件,設定好要執行的相對應功能。例如:

01
02
03
04
05
06
07
08
09
10
public class JavaScriptInterface {
       private Activity activity;
       public JavaScriptInterface(Activity activiy) {
               this.activity = activiy;
       }
       @JavascriptInterface
       public void showToast(){
               Toast.makeText(activity, "我被從WebView呼叫了", Toast.LENGTH_SHORT).show();
       }
}

這邊要注意的是如果 targetSdkVersion 設定為 17 以上,就必須在每個可以被 Javascript 呼叫的方法前面加上 @JavascriptInterface,否則會出現以下錯誤

1
Uncaught TypeError: Object [object Object] has no method 'showToast'

將設定好的 JavaScriptInterface 設定給 WebView 物件

1
wv.addJavascriptInterface(new JavaScriptInterface(getActivity()), "JSInterface");

後面的參數名字可以自己取,小蛙這邊使用 JSInterface,這個名字是讓 Javascript 可以知道透過哪個物件來呼叫。Android 這邊完成後接著在 html 中加入相對應的動作,例如:

1
2
3
4
5
6
7
<input type='button' value='按我' onclick='javascript:showToast();'>
<script type='text/javascript'>
function showToast(){
    if(JSInterface)
        JSInterface.showToast();
}
</script>

設定一個 button 讓使用者點選時執行 function showToast(),而 showToast 方法中倘若存在 JSInterface 物件 (這個物件是上面 wv.addJavascriptInterface 時設定的),就執行 JSInterface.showToast() 的方法 (這一步就會對應到我們自訂的 JavaScriptInterface 類別中的 public void showToast()),在 app 中顯示 Toast 訊息。
到這邊,從 Android 呼叫 Javascript 以及從 Javascript 呼叫 Android 方法都已經完成,但是在 Android 2.3.x 版本中會發生一些錯誤,造成當機無法正確執行,解決方法請參考 Android 2.3 @JavascriptInterface Issue

    發佈留言

    發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

    這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料