สร้างลำดับชั้นเนื้อหา

Android Auto และ Android Automotive OS (AAOS) จะเรียกใช้บริการเบราว์เซอร์สื่อของแอปเพื่อค้นหาเนื้อหาที่พร้อมใช้งาน หากต้องการรองรับฟีเจอร์นี้ คุณต้องใช้ เมธอดทั้ง 2 นี้ในบริการเบราว์เซอร์สื่อ

ใช้งาน onGetRoot

เมธอด onGetRoot ของบริการจะแสดงข้อมูลเกี่ยวกับโหนดรูท ของลำดับชั้นเนื้อหา Android Auto และ AAOS ใช้รูท โหนดนี้เพื่อขอเนื้อหาที่เหลือโดยใช้วิธีonLoadChildren ข้อมูลโค้ดนี้แสดงการใช้งานเมธอด 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);
}

ดูตัวอย่างโดยละเอียดของวิธีการนี้ได้ที่ onGetRoot ในแอปตัวอย่าง Universal Android Music Player บน GitHub

เพิ่มการตรวจสอบแพ็กเกจ

เมื่อมีการโทรไปยังเมธอด onGetRoot ของบริการ แพ็กเกจที่เรียกจะส่งข้อมูลระบุตัวตนไปยังบริการของคุณ บริการของคุณสามารถใช้ ข้อมูลนี้เพื่อพิจารณาว่าแพ็กเกจดังกล่าวเข้าถึงเนื้อหาของคุณได้หรือไม่

เช่น คุณสามารถจำกัดการเข้าถึงเนื้อหาของแอปให้เฉพาะแพ็กเกจที่ได้รับอนุมัติ ในรายการได้

  • เปรียบเทียบ clientPackageName กับรายการที่อนุญาต
  • ยืนยันใบรับรองที่ใช้ลงนาม APK สำหรับแพ็กเกจ

หากยืนยันแพ็กเกจไม่ได้ ให้กลับไปที่ null เพื่อปฏิเสธการเข้าถึงเนื้อหา

หากต้องการให้แอประบบ เช่น Android Auto และ AAOS เข้าถึงเนื้อหาของคุณได้ บริการของคุณต้องแสดงผลค่าที่ไม่ใช่ Null BrowserRoot เมื่อแอประบบเหล่านี้เรียกใช้เมธอด onGetRoot

ลายเซ็นของแอปของระบบ AAOS จะแตกต่างกันไปตาม ยี่ห้อและรุ่นของรถยนต์ โปรดตรวจสอบว่าได้อนุญาตการเชื่อมต่อจากแอประบบทั้งหมดเพื่อรองรับ AAOS

ข้อมูลโค้ดนี้แสดงวิธีที่บริการของคุณสามารถตรวจสอบได้ว่าแพ็กเกจที่เรียกใช้ เป็นแอประบบ

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
}

ข้อมูลโค้ดนี้เป็นข้อความที่ตัดตอนมาจากคลาส PackageValidator ใน แอปตัวอย่าง Universal Android Music Player บน GitHub ดูตัวอย่างที่ละเอียดยิ่งขึ้นเกี่ยวกับวิธีติดตั้งใช้งานการตรวจสอบแพ็กเกจสำหรับบริการของonGetRootในชั้นเรียนดังกล่าว

นอกเหนือจากการอนุญาตแอปของระบบแล้ว คุณต้องอนุญาตให้ Google Assistant เชื่อมต่อกับMediaBrowserServiceด้วย Google Assistant ใช้ชื่อแพ็กเกจแยกกัน สำหรับโทรศัพท์ ซึ่งรวมถึง Android Auto และ Android AAOS

ใช้ onLoadChildren

หลังจากได้รับออบเจ็กต์โหนดรูทแล้ว Android Auto และ AAOS จะสร้างเมนูระดับบนสุดโดยเรียกใช้ onLoadChildren ในออบเจ็กต์โหนดรูท เพื่อรับออบเจ็กต์ลูกหลาน แอปไคลเอ็นต์สร้างเมนูย่อยโดยเรียกใช้เมธอดเดียวกันนี้ โดยใช้ออบเจ็กต์โหนดลูกหลาน

แต่ละโหนดในลำดับชั้นเนื้อหาจะแสดงด้วยออบเจ็กต์ MediaBrowserCompat.MediaItem โดยรายการสื่อแต่ละรายการจะมีสตริงรหัสที่ไม่ซ้ำกัน เป็นตัวระบุ แอปไคลเอ็นต์จะถือว่าสตริงรหัสเหล่านี้เป็นโทเค็นที่ไม่โปร่งใส

เมื่อแอปไคลเอ็นต์ต้องการเรียกดูเมนูย่อยหรือเล่นรายการสื่อ แอปจะส่งโทเค็น แอปของคุณมีหน้าที่เชื่อมโยงโทเค็นกับ รายการสื่อที่เหมาะสม

ข้อมูลโค้ดนี้แสดงการใช้งาน 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);
}

หากต้องการดูตัวอย่างของเมธอดนี้ โปรดดู onLoadChildren ใน แอปตัวอย่าง Universal Android Music Player บน GitHub

สร้างโครงสร้างเมนูหลัก

Android Auto และ Android Automotive OS มีข้อจำกัดเฉพาะเกี่ยวกับ โครงสร้างของเมนูรูท โดยจะสื่อสารกับ MediaBrowserService ผ่านคำแนะนำรูท ซึ่งอ่านได้ผ่านอาร์กิวเมนต์ Bundle ที่ส่งไปยัง onGetRoot() เมื่อทำตามคำแนะนำเหล่านี้ ระบบจะแสดงเนื้อหาระดับบนสุดเป็นแท็บนำทาง หากไม่ปฏิบัติตามคำแนะนำเหล่านี้ ระบบอาจทิ้งเนื้อหาระดับบนสุดบางรายการหรือทำให้ค้นพบได้ยากขึ้น

เนื้อหาระดับรูทจะแสดงเป็นแท็บการนำทาง

รูปที่ 1 เนื้อหาระดับบนสุดจะแสดงเป็นแท็บการนำทาง

เมื่อใช้คำแนะนำเหล่านี้ ระบบจะแสดงเนื้อหาระดับบนสุดเป็นแท็บการนำทาง หากไม่ใช้คำแนะนำเหล่านี้ ระบบอาจทิ้งเนื้อหาระดับรูทบางรายการหรือทำให้ค้นพบได้ยากขึ้น ระบบจะส่งคำใบ้เหล่านี้

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

คุณเลือกที่จะแยกตรรกะสำหรับโครงสร้างของลำดับชั้นเนื้อหาได้ โดยอิงตามค่าของคำแนะนำเหล่านี้ โดยเฉพาะอย่างยิ่งหากลำดับชั้นแตกต่างกันในMediaBrowserการผสานรวมภายนอก Android Auto และ AAOS

เช่น หากปกติคุณแสดงไอเทมที่เล่นได้ระดับรูท คุณอาจต้องการซ้อนไอเทมดังกล่าว ไว้ใต้ไอเทมที่เรียกดูได้ระดับรูทแทน เนื่องจากค่าของแฟล็กที่รองรับ คำแนะนำ

นอกเหนือจากคำแนะนำรูทแล้ว ให้ใช้หลักเกณฑ์ต่อไปนี้เพื่อแสดงแท็บอย่างเหมาะสม

  • ไอคอนขาวดำ (สีขาวจะดีที่สุด) สำหรับรายการในแต่ละแท็บ

  • ป้ายกำกับที่สั้นและมีความหมายสำหรับรายการในแต่ละแท็บ (ป้ายกำกับสั้นๆ จะช่วยลดโอกาสที่ระบบจะตัดป้ายกำกับ)