Chủ Nhật, 26 tháng 8, 2018

Bài 4: Master WebView trong Android (Phần 3)

Bài 4: Master WebView trong Android (Phần 3)

Trong phần 1 và phần 2 của chuyên mục thì chúng tôi đã giới thiệu cách load một trang web tĩnh được lưu trực tiếp trong Assets đổ vào WebView. Hôm nay, chúng tôi sẽ tiếp tục trình bày phần cuối cùng, gọi hàm Java từ Javascript trong WebView.


Mục đích chính của việc này là giúp các bạn làm một Help Activity để chứa phần Trợ giúp trong ứng dụng của các bạn. Thực chất bạn vẫn có thể dùng các Views để bố trí chúng, nhưng đối với phần có nội dung phức tạp thì việc làm một trang HTML sẽ dễ dàng hơn rất nhiều. Bạn cũng có thể thiết kế toàn bộ giao diện ứng dụng bằng Web rồi bắt sự kiện onclick trên các HTML elements gọi các hàm trong Java, chẳng hạn như tôi sẽ trình bày dưới đây.
Đầu tiên tôi có 1 trang index.html đơn giản như sau:

<!DOCTYPE HTML>
<html>
     <head><title>Mod Android Groups</title></head>
     <body style="text-align: center">
          <button style="background: transparent; border: 1px solid black; color: black; margin: auto; top: 20px;">SHOW TOAST FROM HTML</button>
          <script>
               var button = document.getElementsByTagName("button")[0];
               function showToast(toast) { } // Empty function 
               button.onclick = function() { showToast("Cộng Đồng Mod Android Trên Facebook"); }
          </script>
     </body>
</html>

Bây giờ, tôi sẽ cho gọi Toast qua button đó. Mà bạn biết rồi, Toast.makeText(…) trong Java chứ không phải Javascript. Do đó, tôi sẽ phải kết nối giữa phần JS trong Webview và Java trong phần logic của tôi qua một Javascript Interface. Giả sử Activity của tôi có code sau:
class MainActivity extends Activity {
      WebView mWebView;

      void onCreate(Bundle b) {
          super.onCreate(b);
          setContentView(R.id.activity_main);
          mWebView = (WebView) findViewById(R.id.webview);
          mWebView.loadUrl("file:///android_asset/index.html"); 
      }
     class JsInterface extends Object {
     }

}


Mặc định thì toàn bộ phần scripts sẽ bị tắt khi WebView load một Url, bất kể đó là Url từ internet hay assets. Do đó bạn phải bật JS lên:

WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);


Tiếp theo là bạn tạo một JsInterface (tôi đã tạo trong phần trên). Trong đó, tôi định nghĩa hàm showToast như sau:

class JsInterface extends Object {
     @JavascriptInterface
     public void showToast(String toast) {
          Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
     }
}


Lưu ý là bạn phải có JavascriptInterface annotation thì mới gọi được hàm. Còn không thì mọi công sức của bạn sẽ “chỉ để ngắm”. Bây giờ ta sẽ liên kết JsInterface và mWebView qua một interface. Thực tế thì tên gì cũng được, nhưng tốt hơn bạn đặt tên là “Android” để cho dễ bảo trì:

mWebView.addJavascriptInterface(new JsInterface(), "Android");

Cuối cùng, tôi quay lại phần JS trong HTML và code lại hàm showToast(toast) như sau. Lưu ý là String interface phải giống nhau:

function showToast(toast) {
     Android.showToast(toast); // <- Chữ "Android" là từ tham số thứ hai trong mWebView.addJavascriptInterface(new JsInterface(), "Android")

}

Xong xuôi, và bây giờ bạn có thể cho showToast, với sự kiện onclick nằm trong HTML button chứ không còn là Button widget của Android nữa. Tuy nhiên, hãy cẩn trọng, chỉ nên cho phép và gọi hàm Java/Javascript đối với trang web bạn tự tạo và lưu trong assets, không nên làm thao tác này đối với 1 trang web trên internet vì lí do bảo mật. Chúc các bạn thành công.