Android Auto và Android Automotive OS (AAOS) gọi dịch vụ trình duyệt nội dung đa phương tiện của ứng dụng để khám phá nội dung có sẵn. Để hỗ trợ việc này, bạn triển khai 2 phương thức này trong dịch vụ trình duyệt nội dung đa phương tiện.
Triển khai onGetRoot
Phương thức onGetRoot
của dịch vụ sẽ trả về thông tin liên quan đến nút gốc trong hệ thống phân cấp nội dung. Android Auto và AAOS dùng nút gốc này để yêu cầu nội dung còn lại bằng phương thức onLoadChildren
. Đoạn mã này cho thấy cách triển khai phương thức onGetRoot
:
Kotlin
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): BrowserRoot? =
// Verify that the specified package is allowed to access your
// content. You'll need to write your own logic to do this.
if (!isValid(clientPackageName, clientUid)) {
// If the request comes from an untrusted package, return null.
// No further calls will be made to other media browsing methods.
null
} else MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null)
Java
@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
Bundle rootHints) {
// Verify that the specified package is allowed to access your
// content. You'll need to write your own logic to do this.
if (!isValid(clientPackageName, clientUid)) {
// If the request comes from an untrusted package, return null.
// No further calls will be made to other media browsing methods.
return null;
}
return new MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null);
}
Để biết ví dụ chi tiết về phương thức này, hãy xem onGetRoot
trong ứng dụng mẫu Universal Android Music Player trên GitHub.
Thêm phương thức xác thực gói
Khi bạn thực hiện lệnh gọi đến phương thức onGetRoot
của dịch vụ, gói gọi sẽ chuyển thông tin nhận dạng đến dịch vụ của bạn. Dịch vụ của bạn có thể dùng thông tin này để quyết định xem gói đó có thể truy cập vào nội dung của bạn hay không.
Ví dụ: bạn có thể chỉ cho phép các gói được phê duyệt truy cập vào nội dung của ứng dụng:
- So sánh
clientPackageName
với danh sách cho phép của bạn. - Xác minh chứng chỉ dùng để ký APK cho gói.
Nếu không thể xác minh gói, hãy trả về null
để từ chối quyền truy cập vào nội dung của bạn.
Để cấp cho các ứng dụng hệ thống (chẳng hạn như Android Auto và AAOS) quyền truy cập vào nội dung, dịch vụ của bạn phải trả về một BrowserRoot
khác rỗng khi các ứng dụng hệ thống này gọi phương thức onGetRoot
.
Chữ ký của ứng dụng hệ thống AAOS sẽ khác nhau tuỳ theo nhà sản xuất và mẫu xe ô tô. Hãy nhớ cho phép các kết nối từ tất cả ứng dụng hệ thống để hỗ trợ AAOS.
Đoạn mã này cho biết cách dịch vụ của bạn có thể xác thực rằng gói gọi là một ứng dụng hệ thống:
fun isKnownCaller(
callingPackage: String,
callingUid: Int
): Boolean {
...
val isCallerKnown = when {
// If the system is making the call, allow it.
callingUid == Process.SYSTEM_UID -> true
// If the app was signed by the same certificate as the platform
// itself, also allow it.
callerSignature == platformSignature -> true
// ... more cases
}
return isCallerKnown
}
Đoạn mã này là một đoạn trích từ lớp PackageValidator
trong ứng dụng mẫu Universal Android Music Player trên GitHub. Hãy xem lớp đó để biết ví dụ chi tiết hơn về cách triển khai tính năng xác thực gói cho phương thức onGetRoot
của dịch vụ.
Ngoài việc cho phép các ứng dụng hệ thống, bạn phải cho phép Trợ lý Google kết nối với MediaBrowserService
của mình. Trợ lý Google sử dụng tên gói riêng cho điện thoại (bao gồm cả Android Auto và Android Automotive OS).
Triển khai onLoadChildren
Sau khi nhận được đối tượng nút gốc, Android Auto và AAOS sẽ tạo trình đơn cấp cao nhất bằng cách gọi onLoadChildren
trên đối tượng nút gốc để lấy các phần tử con. Các ứng dụng khách xây dựng trình đơn con bằng cách gọi cùng một phương thức này thông qua đối tượng nút con.
Mỗi nút trong hệ thống phân cấp nội dung của bạn được biểu thị bằng một đối tượng MediaBrowserCompat.MediaItem
. Mỗi mục nội dung đa phương tiện này được xác định bằng một chuỗi mã nhận dạng duy nhất. Ứng dụng khách coi những chuỗi mã này là mã thông báo mờ.
Khi một ứng dụng khách muốn duyệt đến trình đơn con hoặc phát một mục nội dung đa phương tiện, ứng dụng đó sẽ chuyển mã thông báo. Ứng dụng của bạn chịu trách nhiệm liên kết mã thông báo với mục nội dung đa phương tiện thích hợp.
Đoạn mã này cho thấy cách triển khai onLoadChildren
Kotlin
override fun onLoadChildren(
parentMediaId: String,
result: Result<List<MediaBrowserCompat.MediaItem>>
) {
// Assume for example that the music catalog is already loaded/cached.
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
// Check if this is the root menu:
if (MY_MEDIA_ROOT_ID == parentMediaId) {
// Build the MediaItem objects for the top level
// and put them in the mediaItems list.
} else {
// Examine the passed parentMediaId to see which submenu we're at
// and put the descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems)
}
Java
@Override
public void onLoadChildren(final String parentMediaId,
final Result<List<MediaBrowserCompat.MediaItem>> result) {
// Assume for example that the music catalog is already loaded/cached.
List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();
// Check if this is the root menu:
if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) {
// Build the MediaItem objects for the top level
// and put them in the mediaItems list.
} else {
// Examine the passed parentMediaId to see which submenu we're at
// and put the descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems);
}
Để xem ví dụ về phương thức này, hãy xem onLoadChildren
trong ứng dụng mẫu Universal Android Music Player trên GitHub.
Cấu trúc trình đơn gốc
Android Auto và Android Automotive OS có những hạn chế cụ thể về cấu trúc của trình đơn gốc. Các hạn chế này được truyền đến MediaBrowserService
thông qua gợi ý gốc. Hệ thống có thể đọc gợi ý gốc thông qua đối số Bundle được truyền vào onGetRoot()
. Khi làm theo các gợi ý này, hệ thống có thể hiển thị nội dung gốc ở dạng thẻ điều hướng. Nếu bạn không làm theo các gợi ý này, hệ thống có thể bỏ hoặc ẩn bớt một số nội dung gốc.
Hình 1. Nội dung gốc xuất hiện ở dạng thẻ điều hướng.
Khi áp dụng các gợi ý này, hệ thống sẽ hiển thị nội dung gốc dưới dạng thẻ điều hướng. Nếu bạn không áp dụng các gợi ý này, hệ thống có thể bỏ hoặc ẩn bớt một số nội dung gốc. Các gợi ý này được truyền đi:
Giới hạn về số lượng phần tử con gốc: Trong hầu hết trường hợp, số lượng này thường là 4, tức là chỉ có thể hiển thị 4 thẻ (hoặc ít hơn).
Số cờ được hỗ trợ trên phần tử con gốc: Giá trị này thường là
MediaItem#FLAG_BROWSABLE
, nghĩa là chỉ các mục có thể xem (không phải mục có thể phát) mới có thể hiển thị ở dạng thẻ.Giới hạn về số lượng thao tác duyệt qua tuỳ chỉnh: Kiểm tra xem có bao nhiêu thao tác duyệt qua tuỳ chỉnh được hỗ trợ.
Kotlin
import androidx.media.utils.MediaConstants
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle
): BrowserRoot {
val maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
/* defaultValue= */ 4)
val supportedRootChildFlags = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ MediaItem.FLAG_BROWSABLE)
// Rest of method...
}
Java
import androidx.media.utils.MediaConstants;
// Later, in your MediaBrowserServiceCompat.
@Override
public BrowserRoot onGetRoot(
String clientPackageName, int clientUid, Bundle rootHints) {
int maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
/* defaultValue= */ 4);
int supportedRootChildFlags = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ MediaItem.FLAG_BROWSABLE);
// Rest of method...
}
Bạn có thể chọn phân nhánh logic cho cấu trúc của hệ phân cấp nội dung dựa trên giá trị của các gợi ý này, cụ thể là nếu hệ phân cấp của bạn thay đổi giữa các hoạt động tích hợp MediaBrowser
bên ngoài Android Auto và AAOS.
Ví dụ: nếu thường hiển thị một mục gốc có thể phát, bạn nên lồng mục đó vào một mục gốc có thể xem, do giá trị của gợi ý về cờ được hỗ trợ.
Ngoài gợi ý gốc, hãy sử dụng các nguyên tắc sau để hiển thị thẻ một cách tối ưu:
Biểu tượng đơn sắc (tốt nhất là màu trắng) cho từng mục trong thẻ
Nhãn ngắn gọn và dễ hiểu cho từng mục trên thẻ (nhãn ngắn giúp giảm khả năng nhãn có thể bị cắt bớt)