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 nào có sẵn. Để hỗ trợ việc này, bạn hãy triển khai 2 phương thức sau 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ã sau đâ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ể hạn chế quyền truy cập vào nội dung của ứng dụng đối với danh sách các gói đã được phê duyệt:
- So sánh
clientPackageNamevới danh sách cho phép. - Xác minh chứng chỉ dùng để ký APK cho gói.
Nếu không xác minh được 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 thay đổi 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ừ mọi ứng dụng hệ thống để hỗ trợ AAOS.
Đoạn mã sau đây minh hoạ 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à phần trích dẫn 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. Trợ lý Google sử dụng các tên gói khác nhau
cho ứng dụng dành cho thiết bị di động và ứng dụng AAOS.
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 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
MediaBrowserCompat.MediaItem đối tượng. 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ã sau đâ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, thì một số nội dung gốc có thể bị hệ thống loại bỏ hoặc khó tìm thấy hơn.

Hình 1. Nội dung gốc xuất hiện ở dạng thẻ điều hướng.
Bằng cách áp dụng các gợi ý này, hệ thống sẽ hiển thị nội dung gốc ở dạng thẻ điều hướng. Nếu không áp dụng các gợi ý này, thì một số nội dung gốc có thể bị loại bỏ hoặc khó tìm thấy hơn. Các gợi ý này được truyền:
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 thường là 4, nghĩa là chỉ có thể hiển thị 4 thẻ (hoặc ít hơn).
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 mới có thể hiển thị ở dạng thẻ, còn các mục có thể phát thì không.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 trong thẻ (nhãn ngắn giúp giảm khả năng nhãn có thể bị cắt bớt)