Android 11 đã đưa ra những thay đổi về cách ứng dụng có thể tương tác với các ứng dụng khác mà người dùng đã cài đặt trên thiết bị. Bạn có thể đọc thêm về những thay đổi đó trên tài liệu Android.
Khi một ứng dụng Android sử dụng Thẻ tuỳ chỉnh nhắm đến SDK cấp 30 trở lên, bạn có thể cần thực hiện một số thay đổi. Bài viết này trình bày những thay đổi có thể cần thiết đối với các ứng dụng đó.
Trong trường hợp đơn giản nhất, bạn có thể chạy Thẻ tuỳ chỉnh bằng một dòng như sau:
new CustomTabsIntent.Builder().build()
.launchUrl(this, Uri.parse("https://www.example.com"));
Các ứng dụng chạy ứng dụng bằng phương pháp này hoặc thậm chí thêm các tuỳ chỉnh giao diện người dùng như thay đổi màu thanh công cụ, thêm nút hành động sẽ không cần thực hiện bất kỳ thay đổi nào trong ứng dụng.
Ưu tiên ứng dụng gốc
Tuy nhiên, nếu bạn đã làm theo các phương pháp hay nhất, thì có thể bạn sẽ phải thực hiện một số thay đổi.
Phương pháp hay nhất liên quan đầu tiên là các ứng dụng nên ưu tiên ứng dụng gốc để xử lý ý định thay vì Thẻ tuỳ chỉnh nếu đã cài đặt một ứng dụng có thể xử lý ý định đó.
Trên Android 11 trở lên
Android 11 giới thiệu một cờ Ý định mới, FLAG_ACTIVITY_REQUIRE_NON_BROWSER
. Đây là cách nên dùng để thử mở một ứng dụng gốc, vì ứng dụng không cần khai báo bất kỳ truy vấn nào của trình quản lý gói.
static boolean launchNativeApi30(Context context, Uri uri) {
Intent nativeAppIntent = new Intent(Intent.ACTION_VIEW, uri)
.addCategory(Intent.CATEGORY_BROWSABLE)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER);
try {
context.startActivity(nativeAppIntent);
return true;
} catch (ActivityNotFoundException ex) {
return false;
}
}
Giải pháp là cố gắng chạy Ý định và sử dụng FLAG_ACTIVITY_REQUIRE_NON_BROWSER
để yêu cầu Android tránh trình duyệt khi khởi chạy.
Nếu không tìm thấy ứng dụng gốc có thể xử lý Ý định này, thì hệ thống sẽ gửi ra một ActivityNotFoundException
.
Trước Android 11
Mặc dù ứng dụng có thể nhắm đến Android 11 hoặc API cấp 30, nhưng các phiên bản Android trước đó sẽ không hiểu cờ FLAG_ACTIVITY_REQUIRE_NON_BROWSER
, vì vậy, chúng ta cần phải truy vấn Trình quản lý gói trong những trường hợp đó:
private static boolean launchNativeBeforeApi30(Context context, Uri uri) {
PackageManager pm = context.getPackageManager();
// Get all Apps that resolve a generic url
Intent browserActivityIntent = new Intent()
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.fromParts("http", "", null));
Set<String> genericResolvedList = extractPackageNames(
pm.queryIntentActivities(browserActivityIntent, 0));
// Get all apps that resolve the specific Url
Intent specializedActivityIntent = new Intent(Intent.ACTION_VIEW, uri)
.addCategory(Intent.CATEGORY_BROWSABLE);
Set<String> resolvedSpecializedList = extractPackageNames(
pm.queryIntentActivities(specializedActivityIntent, 0));
// Keep only the Urls that resolve the specific, but not the generic
// urls.
resolvedSpecializedList.removeAll(genericResolvedList);
// If the list is empty, no native app handlers were found.
if (resolvedSpecializedList.isEmpty()) {
return false;
}
// We found native handlers. Launch the Intent.
specializedActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(specializedActivityIntent);
return true;
}
Phương pháp được sử dụng ở đây là truy vấn Trình quản lý gói cho các ứng dụng hỗ trợ ý định http
chung. Những ứng dụng đó có thể là trình duyệt.
Sau đó, hãy truy vấn các ứng dụng xử lý các mục cho URL cụ thể mà chúng ta muốn khởi chạy. Thao tác này sẽ trả về cả chế độ thiết lập trình duyệt và ứng dụng gốc để xử lý URL đó.
Bây giờ, hãy xoá tất cả trình duyệt có trong danh sách đầu tiên khỏi danh sách thứ hai và chúng ta sẽ chỉ còn lại các ứng dụng gốc.
Nếu danh sách này trống, chúng ta biết rằng không có trình xử lý gốc nào và trả về giá trị false. Nếu không, chúng ta sẽ chạy ý định cho trình xử lý gốc.
Kết hợp kiến thức đã học
Chúng ta cần đảm bảo sử dụng phương thức phù hợp cho từng trường hợp:
static void launchUri(Context context, Uri uri) {
boolean launched = Build.VERSION.SDK_INT >= 30 ?
launchNativeApi30(context, uri) :
launchNativeBeforeApi30(context, uri);
if (!launched) {
new CustomTabsIntent.Builder()
.build()
.launchUrl(context, uri);
}
}
Build.VERSION.SDK_INT
cung cấp thông tin chúng ta cần. Nếu giá trị này bằng hoặc lớn hơn 30, Android sẽ biết FLAG_ACTIVITY_REQUIRE_NON_BROWSER
và chúng ta có thể thử chạy một ứng dụng gốc bằng phương pháp mới. Nếu không, chúng ta sẽ thử chạy bằng phương pháp cũ.
Nếu không khởi chạy được ứng dụng gốc, chúng ta sẽ khởi chạy Thẻ tuỳ chỉnh.
Phương pháp hay nhất này có một số mã nguyên mẫu. Chúng tôi đang nỗ lực đơn giản hoá việc này bằng cách đóng gói độ phức tạp trong một thư viện. Hãy chú ý theo dõi các bản cập nhật cho thư viện hỗ trợ android-browser-helper.
Phát hiện trình duyệt hỗ trợ Thẻ tuỳ chỉnh
Một mẫu phổ biến khác là sử dụng PackageManager để phát hiện trình duyệt nào hỗ trợ Thẻ tuỳ chỉnh trên thiết bị. Các trường hợp sử dụng phổ biến cho việc này là đặt gói trên Ý định để tránh hộp thoại phân định ứng dụng hoặc chọn trình duyệt nào sẽ kết nối khi kết nối với dịch vụ Thẻ tuỳ chỉnh.
Khi nhắm đến API cấp 30, nhà phát triển sẽ cần thêm một phần truy vấn vào Tệp kê khai Android, khai báo một bộ lọc ý định khớp với các trình duyệt có hỗ trợ Thẻ tuỳ chỉnh.
<queries>
<intent>
<action android:name=
"android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
Khi có mã đánh dấu, mã hiện có dùng để truy vấn các trình duyệt hỗ trợ Thẻ tuỳ chỉnh sẽ hoạt động như mong đợi.
Câu hỏi thường gặp
Hỏi: Mã tìm kiếm các nhà cung cấp Thẻ tuỳ chỉnh truy vấn các ứng dụng có thể xử lý ý định https://
, nhưng bộ lọc truy vấn chỉ khai báo truy vấn android.support.customtabs.action.CustomTabsService
. Không phải bạn phải khai báo truy vấn cho ý định https://
sao?
Đáp: Khi khai báo bộ lọc truy vấn, bộ lọc này sẽ lọc các phản hồi cho một truy vấn đến PackageManager, chứ không phải chính truy vấn đó. Vì các trình duyệt hỗ trợ Thẻ tuỳ chỉnh khai báo việc xử lý CustomTabsService, nên các trình duyệt này sẽ không bị lọc ra. Các trình duyệt không hỗ trợ Thẻ tuỳ chỉnh sẽ bị lọc ra.
Kết luận
Đó là tất cả các thay đổi cần thiết để điều chỉnh chế độ tích hợp Thẻ tuỳ chỉnh hiện có cho phù hợp với Android 11. Để tìm hiểu thêm về cách tích hợp Thẻ tuỳ chỉnh vào ứng dụng Android, hãy bắt đầu với hướng dẫn triển khai, sau đó xem các phương pháp hay nhất để tìm hiểu cách xây dựng tính năng tích hợp hàng đầu.
Hãy cho chúng tôi biết nếu bạn có câu hỏi hoặc ý kiến phản hồi!