Đơn giản hoá việc triển khai WebView bằng Jetpack Webkit

Hướng dẫn này mô tả các lợi ích của thư viện Jetpack Webkit, giải thích cách thư viện này hoạt động và cách bạn có thể triển khai thư viện này trong các dự án của mình.

Tổng quan

WebView là một phần thiết yếu trong quá trình phát triển Android, nhưng đôi khi bạn có thể gặp khó khăn trong việc quản lý do các tính năng không nhất quán trên nhiều phiên bản hệ điều hành Android. Mỗi phiên bản hệ điều hành Android đều cung cấp một bộ API WebView cố định. Vì Android được phát hành chậm hơn WebView, nên các API Android có thể không bao gồm mọi tính năng có sẵn của WebView. Điều này dẫn đến việc triển khai tính năng chậm hơn và tăng chi phí kiểm thử.

Jetpack Webkit giải quyết những vấn đề này bằng cách đóng vai trò là một lớp tương thích và tận dụng APK WebView mới nhất trên thiết bị của người dùng. Thư viện này cũng chứa các API mới và hiện đại chỉ có trong thư viện này.

Tại sao nên dùng Jetpack Webkit?

Ngoài việc cung cấp khả năng tương thích trên nhiều phiên bản, Jetpack Webkit còn cung cấp các API mới và hiện đại có thể đơn giản hoá quá trình phát triển và cải thiện chức năng của ứng dụng:

  • Cho phép xác thực hiện đại: WebView có thể xử lý liền mạch các tiêu chuẩn xác thực web hiện đại như WebAuthn, cho phép đăng nhập dựa trên khoá truy cập. Thư viện androidx.webkit giúp bạn kiểm soát hoàn toàn quá trình tích hợp này bằng phương thức WebSettingsCompat.setWebAuthenticationSupport(). Bạn có thể dùng phương thức này để định cấu hình mức độ hỗ trợ mà ứng dụng của bạn yêu cầu.

  • Cải thiện hiệu suất: Điều chỉnh hiệu suất của WebView cho các trường hợp sử dụng ứng dụng của bạn bằng các API như prefetchUrlAsync, prerenderUrlAsyncsetBackForwardCacheEnabled.

  • Tăng độ ổn định: Khôi phục các quy trình kết xuất bị treo hoặc không phản hồi mà không gặp sự cố. Để biết thêm thông tin, hãy xem WebViewRenderProcess#terminate().

  • Cung cấp chế độ kiểm soát chi tiết đối với dữ liệu duyệt web: Để xoá dữ liệu duyệt web do WebView lưu trữ cho các nguồn gốc cụ thể, hãy sử dụng lớp WebStorageCompat.

Tìm hiểu các thành phần

Để sử dụng Jetpack Webkit một cách hiệu quả, bạn phải hiểu mối quan hệ giữa các thành phần sau:

  • WebView của hệ thống Android: Đây là công cụ kết xuất dựa trên Chromium mà Google cập nhật thường xuyên thông qua Cửa hàng Google Play với cùng tần suất như Chrome. Thư viện này chứa các tính năng mới nhất và cung cấp mã triển khai cơ bản cho tất cả các API WebView.

  • Framework API (android.webkit): Đây là những API được cố định cho một phiên bản hệ điều hành Android cụ thể. Ví dụ: một ứng dụng trên Android 10 chỉ có thể truy cập vào các API có sẵn khi phiên bản đó được phát hành. Do đó, ứng dụng này không thể sử dụng các tính năng mới được thêm vào APK WebView trong các bản cập nhật gần đây hơn. Ví dụ: để xử lý một trình kết xuất không phản hồi bằng WebView#getWebViewRenderProcess(), bạn chỉ có thể gọi trình kết xuất này trên Android 10 trở lên.

  • Thư viện Jetpack Webkit (androidx.webkit): Đây là một thư viện nhỏ được đi kèm trong ứng dụng của bạn. Thư viện này đóng vai trò là cầu nối gọi vào APK WebView, thay vì gọi vào các API được xác định trong nền tảng Android có phiên bản hệ điều hành cố định. Bằng cách này, ngay cả khi một ứng dụng được cài đặt trên thiết bị chạy phiên bản hệ điều hành cũ như Android 10, ứng dụng đó vẫn có thể sử dụng các tính năng mới nhất của WebView. Ví dụ: WebViewCompat.getWebViewRenderProcess() hoạt động tương tự như Framework API, ngoại trừ việc API này cũng có thể được gọi trên tất cả các phiên bản hệ điều hành trước Android 10.

Nếu có một API trong cả khung và Jetpack Webkit, bạn nên chọn phiên bản Jetpack Webkit. Điều này giúp đảm bảo hành vi nhất quán và khả năng tương thích trên nhiều thiết bị nhất có thể.

Tương tác giữa Jetpack Webkit và APK

Các API trong Jetpack Webkit được triển khai thành 2 phần:

  • Static Jetpack Webkit: Thư viện Static Jetpack Webkit chứa một phần nhỏ mã chịu trách nhiệm triển khai API.

  • APK WebView: APK WebView chứa hầu hết mã.

Ứng dụng của bạn gọi API Jetpack Webkit, sau đó gọi WebView APK.

Mặc dù kiểm soát phiên bản Jetpack Webkit trong ứng dụng của mình, nhưng bạn không thể kiểm soát các bản cập nhật WebView APK trên thiết bị của người dùng. Nhìn chung, hầu hết người dùng đều có các phiên bản mới nhất của WebView APK, nhưng ứng dụng của bạn vẫn phải thận trọng để không gọi vào các API mà phiên bản cụ thể đó của WebView APK không hỗ trợ.

Jetpack Webkit cũng loại bỏ nhu cầu kiểm tra phiên bản WebView theo cách thủ công. Để xác định xem một tính năng có được cung cấp hay không, hãy kiểm tra hằng số tính năng của tính năng đó. Ví dụ: WebViewFeature.WEB_AUTHENTICATION.

Cách các tính năng này phối hợp hoạt động

Jetpack Webkit thu hẹp khoảng cách giữa Framework API tĩnh và WebView APK thường xuyên được cập nhật. Khi bạn sử dụng Jetpack Webkit API với mẫu phát hiện tính năng, thư viện sẽ kiểm tra để xem tính năng đó có được WebView APK cài đặt trên thiết bị của người dùng hỗ trợ hay không. Điều này mang lại lợi ích là không cần kiểm tra phiên bản hệ điều hành Android (khung).

Nếu WebView APK là một phiên bản đủ mới, thì thư viện sẽ gọi tính năng này. Nếu không, phương thức này sẽ báo cáo rằng tính năng không dùng được, ngăn ứng dụng của bạn gặp sự cố và cho phép bạn xử lý tình huống một cách linh hoạt.

So sánh Jetpack Webkit và Framework API

Phần này so sánh các phương thức triển khai có và không có thư viện Jetpack Webkit:

Bật phương thức xác thực hiện đại (WebAuthn)

Không có Jetpack Webkit

Không thể thực hiện thông qua các API khung.

Với Jetpack Webkit

Tận dụng WebViewFeature.WEB_AUTHENTICATION để kiểm tra khả năng tương thích.

if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_AUTHENTICATION)) {
  WebSettingsCompat.setWebAuthenticationSupport(
      webView.settings,
      WebSettingsCompat.WEB_AUTHENTICATION_SUPPORT_FOR_APP
  )
}

Xoá dữ liệu cho một nguồn (bộ nhớ dành riêng cho trang web)

Không có Jetpack WebKit

Không có API trực tiếp để xoá dữ liệu gốc cụ thể. Thường cần xoá tất cả dữ liệu.

Với Jetpack WebKit

Sử dụng các API tương thích để xoá dữ liệu một cách chính xác. Bạn có thể sử dụng một trong hai cách sau:

WebStorageCompat.getInstance().deleteBrowsingData()

Hoặc

WebStorageCompat.getInstance().deleteBrowsingDataForSite()

Lấy phiên bản WebView

Không có Jetpack WebKit

Sử dụng lớp khung tiêu chuẩn.

val webViewPackage = WebView.getCurrentWebViewPackage()

Với Jetpack WebKit

Sử dụng lớp tương thích để truy xuất an toàn hơn.

val webViewPackage = WebViewCompat.getCurrentWebViewPackage()

Xử lý trình kết xuất không phản hồi (ứng dụng kết xuất)

Không có Jetpack WebKit

Sử dụng phương thức khung tiêu chuẩn.

webView.setWebViewRenderProcessClient(myClient)

Với Jetpack WebKit

Sử dụng WebViewCompat và một quy trình kiểm tra tính năng để thiết lập ứng dụng.

if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE)) {
  WebViewCompat.setWebViewRenderProcessClient(webView, myClient)
}

Để biết thêm thông tin, hãy xem tài liệu tham khảo về androidx.webkit.

Tích hợp Jetpack Webkit vào mã của bạn

Việc sử dụng Jetpack Webkit sẽ tăng cường các chức năng của lớp WebView tiêu chuẩn, nhưng không thay thế hoàn toàn lớp WebView ban đầu.

Bạn có thể tiếp tục sử dụng lớp android.webkit.WebView. Bạn có thể thêm thành phần này vào bố cục XML và nhận được thông tin tham chiếu đến thực thể trong mã của mình. Để truy cập vào các tính năng của khung tiêu chuẩn, bạn vẫn có thể gọi trực tiếp các phương thức trên thực thể WebView hoặc đối tượng cài đặt của thực thể đó.

Để truy cập vào các tính năng hiện đại, bạn có thể sử dụng các phương thức trợ giúp tĩnh do Jetpack Webkit cung cấp, chẳng hạn như WebViewCompatWebSettingsCompat. Bạn sẽ truyền phiên bản WebView hiện có của mình vào các phương thức này.

Kotlin

import android.webkit.WebView
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature

// You still get your WebView instance the standard way.
val webView: WebView = findViewById(R.id.my_webview)

// To enable a modern feature, you pass that instance to a Jetpack Webkit helper.
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON)
}

Java

import android.webkit.WebView;
import androidx.webkit.WebSettingsCompat;
import androidx.webkit.WebViewFeature;

// You still get your WebView instance the standard way.
WebView webView = findViewById(R.id.my_webview);

// To enable a modern feature, you pass that instance to a Jetpack Webkit helper.
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON);
}

Triển khai Jetpack Webkit

Để triển khai Jetpack Webkit, hãy sử dụng quy trình sau.

Bước 1: Thêm phần phụ thuộc

Trong tệp build.gradle.kts hoặc build.gradle của mô-đun, hãy thêm phần phụ thuộc sau để thêm Jetpack Webkit:

Groovy

dependencies {
    implementation "androidx.webkit:webkit:1.14.0"
}

Kotlin

dependencies {
    implementation("androidx.webkit:webkit:1.14.0")
}

Jetpack Webkit chứa các trình bao bọc mỏng, nên tác động đến kích thước của ứng dụng là không đáng kể.

Bước 2: Áp dụng mẫu phát hiện tính năng

Để tránh sự cố khi gọi các API không có sẵn, hãy sử dụng các chế độ kiểm tra tính năng. Bạn nên bao quanh mỗi lệnh gọi API bằng một quy trình kiểm tra tính năng và có thể cân nhắc logic dự phòng khi API không hoạt động.

Bạn nên sử dụng mẫu sau đây để dùng API WebView hiện đại:

import android.webkit.WebView
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature

// In your Kotlin code where you configure your WebView
val webView: WebView = findViewById(R.id.my_webview)

// Before you use a modern API, first check if it is supported.
if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    // If the check passes, it is safe to call the API.
    WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON)
} else {
    // Optionally, provide a fallback for older WebView versions.
}

Mẫu này giúp đảm bảo ứng dụng hoạt động ổn định. Vì quy trình kiểm tra tính năng chạy trước, nên ứng dụng sẽ không gặp sự cố nếu tính năng không có sẵn. Mức hao tổn hiệu suất của quy trình kiểm tra WebViewFeature#isFeatureSupported() là không đáng kể.