Membuat hierarki konten

Android Auto dan Android Automotive OS (AAOS) memanggil layanan browser media aplikasi Anda untuk menemukan konten yang tersedia. Untuk mendukungnya, Anda mengimplementasikan dua metode ini di layanan browser media Anda.

Mengimplementasikan onGetRoot

Metode onGetRoot layanan Anda akan menampilkan informasi tentang node root hierarki konten Anda. Android Auto dan AAOS menggunakan node root ini untuk meminta konten Anda lainnya menggunakan metode onLoadChildren. Cuplikan kode ini menunjukkan penerapan metode 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);
}

Untuk contoh mendetail metode ini, lihat onGetRoot di aplikasi contoh Universal Android Music Player di GitHub.

Menambahkan validasi paket

Saat panggilan dilakukan ke metode onGetRoot layanan Anda, paket panggilan ini meneruskan informasi pengidentifikasi ke layanan Anda. Layanan Anda dapat menggunakan informasi ini untuk menentukan apakah paket tersebut dapat mengakses konten Anda atau tidak.

Misalnya, Anda dapat membatasi akses ke konten aplikasi ke daftar paket yang disetujui:

  • Bandingkan clientPackageName dengan daftar yang diberi akses Anda.
  • Verifikasi sertifikat yang digunakan untuk menandatangani APK untuk paket.

Jika paket tidak dapat diverifikasi, tampilkan null untuk menolak akses ke konten Anda.

Agar aplikasi sistem, seperti Android Auto dan AAOS, dapat mengakses konten Anda, layanan Anda harus menampilkan BrowserRoot non-null saat aplikasi sistem tersebut memanggil metode onGetRoot.

Tanda tangan aplikasi sistem AAOS bervariasi menurut merek dan model mobil. Pastikan untuk mengizinkan koneksi dari semua aplikasi sistem untuk mendukung AAOS.

Cuplikan kode ini menunjukkan cara layanan Anda dapat memvalidasi bahwa paket panggilan adalah aplikasi sistem:

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
}

Cuplikan kode ini adalah nukilan dari class PackageValidator di aplikasi contoh Universal Android Music Player di GitHub. Lihat class tersebut untuk melihat contoh yang lebih mendetail tentang cara menerapkan validasi paket untuk metode onGetRoot layanan Anda.

Selain mengizinkan aplikasi sistem, Anda harus mengizinkan Asisten Google terhubung ke MediaBrowserService Anda. Asisten Google menggunakan nama paket terpisah untuk ponsel, yang mencakup Android Auto dan Android AAOS.

Mengimplementasikan onLoadChildren

Setelah menerima objek node root Anda, Android Auto dan AAOS akan membuat menu level atas dengan memanggil onLoadChildren pada objek node root untuk memperoleh turunannya. Aplikasi klien membuat submenu dengan memanggil metode yang sama ini menggunakan objek node turunan.

Setiap node dalam hierarki konten Anda direpresentasikan oleh objek MediaBrowserCompat.MediaItem. Setiap item media ini diidentifikasi oleh string ID unik. Aplikasi klien memperlakukan string ID ini sebagai token buram.

Saat ingin menjelajah ke sebuah submenu, atau memutar item media, aplikasi klien akan meneruskan token ini. Aplikasi Anda bertanggung jawab untuk mengaitkan token dengan item media yang sesuai.

Cuplikan kode ini menunjukkan implementasi 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&lt;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&lt;List&lt;MediaBrowserCompat.MediaItem>> result) {

    // Assume for example that the music catalog is already loaded/cached.

    List&lt;MediaBrowserCompat.MediaItem> mediaItems = new ArrayList&lt;>();

    // 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);
}

Untuk melihat contoh metode ini, lihat onLoadChildren di aplikasi contoh Universal Android Music Player di GitHub.

Membuat struktur menu root

Android Auto dan Android Automotive OS memiliki batasan khusus terkait struktur menu root. Hal ini dikomunikasikan ke MediaBrowserService melalui petunjuk root, yang dapat dibaca melalui argumen Bundle yang diteruskan ke onGetRoot(). Jika diikuti, petunjuk ini memungkinkan sistem menampilkan konten root sebagai tab navigasi. Jika Anda tidak mengikuti petunjuk ini, beberapa konten root mungkin dihapus atau dibuat kurang mudah ditemukan oleh sistem.

Konten root yang ditampilkan sebagai tab navigasi

Gambar 1. Konten root yang ditampilkan sebagai tab navigasi.

Dengan menerapkan petunjuk ini, sistem akan menampilkan konten root sebagai tab navigasi. Jika Anda tidak menerapkan petunjuk ini, beberapa konten root mungkin dihapus atau dibuat kurang mudah ditemukan. Petunjuk ini dikirimkan:

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...
}

Anda dapat memilih untuk mencabangkan logika struktur hierarki konten berdasarkan nilai petunjuk ini, terutama jika hierarki Anda bervariasi di antara integrasi MediaBrowser di luar Android Auto dan AAOS.

Misalnya, jika Anda biasanya menampilkan item root yang dapat diputar, sebaiknya Anda menyarangkannya dalam item root yang dapat dijelajahi, karena nilai dari petunjuk tanda yang didukung.

Selain petunjuk root, gunakan panduan berikut untuk merender tab secara optimal:

  • Ikon monokrom (sebaiknya putih) untuk setiap item tab

  • Label yang singkat dan bermakna untuk setiap item tab (label yang singkat mengurangi kemungkinan label terpotong)