Ứng dụng WebView dành cho nhà phát triển web

Ngày xuất bản: 28 tháng 2 năm 2014

Tìm hiểu cách tạo một Dự án Android mới, thêm một Webview, tải một URL từ xa và tải một trang HTML cục bộ.

Hướng dẫn này giả định rằng bạn là một nhà phát triển có ít hoặc không có kinh nghiệm về môi trường phát triển Android, nhưng có một số kinh nghiệm về Kotlin. Nếu đã quen thuộc với việc lập trình cho Android, bạn nên đọc bài viết Tạo ứng dụng web trong WebView trên trang web dành cho nhà phát triển Android.

Cài đặt Android Studio

Hướng dẫn này sử dụng Android Studio, IDE thiết kế và xây dựng dành cho Android.

Tạo dự án Android mới

Sau khi cài đặt, Android Studio sẽ chạy trình hướng dẫn thiết lập.

Cách tạo dự án mới:

  1. Nhấp vào Dự án mới.
  2. Nhấp vào mẫu Empty Activity (Hoạt động trống) để chọn mẫu đó cho dự án của bạn. Mẫu tạo cấu trúc của dự án và các tệp cần thiết để Android Studio tạo dự án cho bạn.
  3. Nhấp vào Next (Tiếp theo) để mở hộp thoại New Project (Dự án mới).
  4. Định cấu hình dự án. Nhập tên ứng dụng, tên gói và SDK mục tiêu. Sau đó nhấp vào Next (Tiếp theo).
  5. Đặt Minimum required SDK (SDK tối thiểu bắt buộc) thành API 24: Android 7.0 (Nougat).
  6. Nhấp vào Hoàn tất

Android Studio sẽ mở dự án mới.

Cấu trúc dự án

Dự án ban đầu do Android Studio tạo có mã nguyên mẫu để thiết lập ứng dụng. Sau đây là một số thư mục nhập khác:

  • src/main/java. Mã nguồn Java cho Android.
  • src/main/res. Tài nguyên mà ứng dụng sử dụng.
  • src/main/res/drawable. Tài nguyên hình ảnh mà ứng dụng sử dụng.
  • src/main/res/xml. Tệp bố cục XML xác định cấu trúc của các thành phần giao diện người dùng.
  • src/main/res/values. Phương diện, chuỗi và các giá trị khác mà bạn có thể không muốn mã hoá cứng trong ứng dụng.
  • src/main/AndroidManifest.xml. Tệp kê khai xác định nội dung có trong ứng dụng, chẳng hạn như các hoạt động, quyền và giao diện.

Thêm WebView

Tiếp theo, hãy thêm WebView vào bố cục của hoạt động chính.

  1. Mở tệp activity_main.xml trong thư mục src/main/res/xml nếu tệp này chưa mở. (Bạn cũng có thể thấy tệp fragment_main.xml. Bạn có thể bỏ qua bước này vì không bắt buộc phải làm trong hướng dẫn này.)

    Chọn thẻ Text (Văn bản) ở cuối trình chỉnh sửa activity_main.xml để xem mã đánh dấu XML.

    Tệp này xác định bố cục cho hoạt động chính và ngăn Xem trước hiển thị bản xem trước của hoạt động. Bố cục Hoạt động trống không bao gồm bất kỳ thành phần con nào. Bạn cần thêm WebView.

  2. Trong ngăn XML, hãy xoá dấu gạch chéo tự đóng ở cuối phần tử FrameLayout, đồng thời thêm phần tử <WebView> và thẻ đóng mới, như minh hoạ:

    <FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
        xmlns:tools="https://schemas.android.com/tools"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        tools:ignore="MergeRootFrame">
    
        <WebView
          android:id="@+id/activity_main_webview"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
    </FrameLayout>
    
  3. Để sử dụng WebView, bạn cần tham chiếu WebView đó trong Hoạt động. Mở tệp nguồn Java cho hoạt động chính, MainActivity.java trong thư mục src/main/java/<PackageName>.

    Thêm các dòng được in đậm.

    public class MainActivity extends Activity {
    
        private WebView mWebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mWebView = (WebView) findViewById(R.id.activity_main_webview);
    

    Mã hiện có trong phương thức onCreate thực hiện việc kết nối Hoạt động với bố cục. Các dòng được thêm sẽ tạo một biến thành phần mới, mWebView, để tham chiếu đến thành phần hiển thị web.

    Xoá mã sau:

    if (savedInstanceState == null) {
      getSupportFragmentManager().beginTransaction()
        .add(R.id.container, new PlaceholderFragment())
        .commit();
    }
    

    WebView được xác định bằng mã nhận dạng tài nguyên, được chỉ định bằng dòng này trong tệp bố cục:

    android:id="@+id/activity_main_webview"
    

    Sau khi thêm mã, bạn sẽ thấy một số thông báo cảnh báo ở lề của trình chỉnh sửa. Nguyên nhân là do bạn chưa nhập đúng lớp cho WebView. Rất may, Android Studio có thể giúp bạn điền vào các lớp bị thiếu. Cách dễ nhất để thực hiện việc này là nhấp và di chuột qua tên lớp không xác định rồi đợi một mô-đun hiển thị "sửa nhanh" – trong trường hợp này, hãy thêm câu lệnh import cho lớp WebView.

    Nhấn tổ hợp phím Alt + Enter (Option + Enter trên máy Mac) để chấp nhận bản sửa lỗi nhanh.

    Khi đã có WebView, bạn có thể chuyển sang thiết lập và tải một số nội dung web hấp dẫn.

Bật JavaScript

Theo mặc định, WebView không cho phép JavaScript. Để chạy một ứng dụng web trong WebView, bạn cần bật JavaScript một cách rõ ràng bằng cách thêm các dòng sau vào phương thức onCreate:

// Enable Javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

Tải URL từ xa

Nếu bạn định tải dữ liệu từ một URL từ xa, thì ứng dụng của bạn cần có quyền truy cập Internet. Bạn cần thêm quyền này vào tệp kê khai của ứng dụng.

  1. Mở tệp AndroidManifest.xml trong thư mục src/res. Thêm dòng được in đậm trước thẻ </manifest> đóng.

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ...>
    ...
     
      </application>
      <uses-permission android:name="android.permission.INTERNET" />
    </manifest>
    
  2. Bước tiếp theo là gọi phương thức loadUrl trên webview. Thêm dòng sau vào cuối phương thức onCreate.

    mWebView.loadUrl("[https://beta.html5test.com/][8]");
    

    Bây giờ, hãy thử chạy dự án. Nếu không có thiết bị, bạn có thể tạo trình mô phỏng (AVD hoặc Thiết bị Android ảo) bằng cách chuyển đến Tools (Công cụ) > Android (Android) > AVD Manager (Trình quản lý thiết bị ảo Android).

Xử lý thao tác điều hướng

Hãy thử thay đổi URL mà bạn đang tải thành https://www.css-tricks.com/ rồi chạy lại ứng dụng. Bạn sẽ nhận thấy điều gì đó lạ.

Nếu bạn chạy ứng dụng ngay bây giờ với một trang web có lệnh chuyển hướng như css-tricks.com, thì ứng dụng của bạn sẽ mở trang web đó trong trình duyệt trên thiết bị, chứ không phải trong WebView – có thể không phải là điều bạn mong đợi. Điều này là do cách WebView xử lý các sự kiện điều hướng.

Dưới đây là trình tự sự kiện:

  1. WebView cố gắng tải URL gốc từ máy chủ từ xa và được chuyển hướng đến một URL mới.
  2. WebView kiểm tra xem hệ thống có thể xử lý ý định xem cho URL hay không, nếu có thì hệ thống sẽ xử lý thao tác điều hướng URL, nếu không thì WebView sẽ điều hướng nội bộ (ví dụ: nếu người dùng không cài đặt trình duyệt trên thiết bị của họ).
  3. Hệ thống sẽ chọn ứng dụng mà người dùng ưu tiên để xử lý giao thức URL https://, tức là trình duyệt mặc định của người dùng. Nếu đã cài đặt nhiều trình duyệt, bạn có thể thấy một hộp thoại tại thời điểm này.

Nếu đang sử dụng WebView bên trong một ứng dụng Android để hiển thị nội dung (ví dụ: trang trợ giúp), thì đây có thể chính xác là điều bạn muốn làm. Tuy nhiên, đối với các ứng dụng phức tạp hơn, bạn nên tự xử lý các đường liên kết điều hướng.

Để xử lý thao tác điều hướng bên trong WebView, bạn cần ghi đè WebViewClient của WebView. Thao tác này sẽ xử lý nhiều sự kiện do WebView tạo ra. Bạn có thể sử dụng thuộc tính này để kiểm soát cách WebView xử lý các lượt nhấp vào đường liên kết và lệnh chuyển hướng trang.

Việc triển khai mặc định của WebViewClient sẽ khiến mọi URL mở trong WebView:

// Force links and redirects to open in the WebView instead of in a browser
mWebView.setWebViewClient(new WebViewClient());

Đây là một bước tiến tốt, nhưng nếu bạn chỉ muốn xử lý các đường liên kết cho trang web của mình, trong khi mở các URL khác trong trình duyệt thì sao?

Để làm được điều này, bạn cần mở rộng lớp WebViewClient và triển khai phương thức shouldOverrideUrlLoading. Phương thức này được gọi bất cứ khi nào WebView cố gắng điều hướng đến một URL khác. Nếu hàm này trả về giá trị false, thì WebView sẽ tự mở URL. (Quy trình triển khai mặc định luôn trả về false, đó là lý do tại sao quy trình này hoạt động trong ví dụ trước.)

Tạo một lớp mới:

  1. Nhấp chuột phải vào tên gói của ứng dụng rồi chọn New (Mới) > Java Class (Lớp Java)
  2. Nhập MyAppWebViewClient làm tên lớp rồi nhấp vào OK
  3. Trong tệp MyAppWebViewClient.java mới, hãy thêm mã sau (các thay đổi được in đậm):

    public class MyAppWebViewClient extends WebViewClient {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(Uri.parse(url).getHost().endsWith("css-tricks.com")) {
          return false;
        }
                   
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
      }
    }
    

    Mã mới xác định MyAppWebViewClient là lớp con của WebViewClient và triển khai phương thức shouldOverrideUrlLoading.

    Phương thức shouldOverrideUrlLoading được gọi bất cứ khi nào WebView sắp tải một URL. Phương thức triển khai này sẽ kiểm tra Chuỗi "css-tricks.com" ở cuối tên máy chủ của URL. Nếu chuỗi tồn tại, phương thức này sẽ trả về giá trị false, cho nền tảng biết không ghi đè URL mà sẽ tải URL đó trong WebView.

    Đối với mọi tên máy chủ khác, phương thức này sẽ gửi yêu cầu đến hệ thống để mở URL. Ứng dụng này thực hiện việc này bằng cách tạo một Ý định Android mới và sử dụng ý định đó để khởi chạy một hoạt động mới. Việc trả về true ở cuối phương thức sẽ ngăn URL tải vào WebView.

  4. Để sử dụng WebViewClient tuỳ chỉnh mới, hãy thêm các dòng sau vào lớp MainActivity:

    // Stop local links and redirects from opening in browser instead of WebView
    mWebView.setWebViewClient(new MyAppWebViewClient());
    

    Giờ đây, người dùng có thể nhấp vào bất kỳ đường liên kết nào của CSS Tricks và vẫn ở trong ứng dụng, nhưng các đường liên kết đến các trang web bên ngoài sẽ được mở trong trình duyệt.

Xử lý nút quay lại trên Android

Khi bạn bắt đầu khám phá và điều hướng các bài viết trên CSS Tricks, thao tác nhấp vào nút quay lại trên Android sẽ thoát khỏi ứng dụng.

Phương thức WebView canGoBack cho bạn biết liệu có bất kỳ nội dung nào trên ngăn xếp trang có thể bật lên hay không. Để phát hiện thao tác nhấn nút quay lại và xác định xem bạn có nên quay lại qua nhật ký của WebView hay cho phép nền tảng xác định hành vi chính xác, hãy thêm phương thức onBackPressed() vào MainActivity:

public class MainActivity extends Activity {

 private WebView mWebView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     ...
 }

    @Override
    public void onBackPressed() {
      if(mWebView.canGoBack()) {
        mWebView.goBack();
      } else {
        super.onBackPressed();
      }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
       ...
    }
}

Tải HTML từ hệ thống tệp

Một lợi thế lớn của việc sử dụng WebView bên trong một ứng dụng có thể cài đặt là bạn có thể lưu trữ các thành phần bên trong ứng dụng. Điều này cho phép ứng dụng của bạn hoạt động ngoại tuyến và cải thiện thời gian tải, vì WebView có thể truy xuất các thành phần trực tiếp từ hệ thống tệp cục bộ.

Để lưu trữ các tệp trên thiết bị, bao gồm cả HTML, JavaScript và CSS, hãy lưu trữ các tệp đó trong thư mục tài sản. Đây là thư mục dành riêng mà Android sử dụng cho các tệp thô. Ứng dụng của bạn cần có quyền truy cập vào thư mục này vì ứng dụng có thể cần giảm thiểu hoặc nén một số tệp nhất định.

  1. Tạo thư mục assets/www trong phần chính (src/main/assets/www).

    • Phương pháp hay nhất là lưu trữ các tệp web trong một thư mục con của /assets.
  2. Tải tất cả tệp lên thư mục.

  3. Tải tệp thích hợp:

    mWebView.loadUrl("file:///android_asset/www/index.html");
    
  4. Cập nhật phương thức shouldOverrideUrlLoading để mở trình duyệt cho các trang không phải trang cục bộ:

    public class MyAppWebViewClient extends WebViewClient {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(Uri.parse(url).getHost().length() == 0) {
          return false;
        }
    
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
      }
    }
    

Bây giờ, bạn đã sẵn sàng để xây dựng một ứng dụng WebView tuyệt vời.

Để biết các mẹo giúp hình ảnh vừa vặn, hãy xem phần Giao diện người dùng Pixel-Perfect trong WebView.

Nếu bạn gặp sự cố, hãy sử dụng Công cụ cho nhà phát triển Chrome. Hãy xem phần Gỡ lỗi từ xa trên Android để bắt đầu.