سلسله مراتب محتوای خود را بسازید

Android Auto و Android Automotive OS (AAOS) با سرویس مرورگر رسانه برنامه شما تماس می گیرند تا بفهمند کدام محتوا در دسترس است. برای پشتیبانی از این، شما این دو روش را در سرویس مرورگر رسانه خود پیاده سازی می کنید.

onGetRoot را پیاده سازی کنید

روش onGetRoot سرویس شما اطلاعات مربوط به گره ریشه سلسله مراتب محتوای شما را برمی گرداند. Android Auto و AAOS از این گره ریشه برای درخواست بقیه محتوای شما با استفاده از روش onLoadChildren استفاده می کنند. این قطعه کد پیاده سازی متد onGetRoot را نشان می دهد:

کاتلین

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)

جاوا

@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 در برنامه نمونه برنامه پخش موسیقی جهانی اندروید در GitHub مراجعه کنید.

اعتبار سنجی بسته را اضافه کنید

هنگامی که با روش onGetRoot سرویس شما تماس برقرار می شود، بسته تماس اطلاعات شناسایی را به سرویس شما ارسال می کند. سرویس شما می تواند از این اطلاعات برای تصمیم گیری در مورد اینکه آیا بسته می تواند به محتوای شما دسترسی داشته باشد استفاده کند.

به عنوان مثال، می توانید دسترسی به محتوای برنامه خود را به لیستی از بسته های تایید شده محدود کنید:

  • clientPackageName را با لیست مجاز خود مقایسه کنید.
  • گواهی مورد استفاده برای امضای APK بسته را تأیید کنید.

اگر بسته قابل تأیید نیست، برای جلوگیری از دسترسی به محتوای خود، null را برگردانید.

برای اینکه برنامه‌های سیستمی مانند Android Auto و AAOS به محتوای شما دسترسی داشته باشند، زمانی که این برنامه‌های سیستمی روش onGetRoot را فراخوانی می‌کنند، سرویس شما باید یک BrowserRoot غیر تهی را برگرداند.

امضای برنامه سیستم 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 در برنامه نمونه برنامه پخش موسیقی جهانی اندروید در GitHub است. برای مثال دقیق تر از نحوه پیاده سازی اعتبار سنجی بسته برای متد onGetRoot سرویس خود، آن کلاس را ببینید.

علاوه بر اجازه دادن به برنامه‌های سیستمی، باید به دستیار Google اجازه دهید به MediaBrowserService شما متصل شود. Google Assistant از نام‌های بسته جداگانه برای گوشی استفاده می‌کند که شامل Android Auto Android AAOS می‌شود.

پیاده سازی onLoadChildren

پس از دریافت شی گره ریشه، Android Auto و AAOS یک منوی سطح بالا را با فراخوانی روی onLoadChildren در شی گره ریشه ایجاد می کنند تا نوادگان آن را دریافت کنند. برنامه های سرویس گیرنده با فراخوانی همین روش با استفاده از اشیاء گره نسل، زیر منوها را می سازند.

هر گره در سلسله مراتب محتوای شما توسط یک شی MediaBrowserCompat.MediaItem نشان داده می شود. هر یک از این موارد رسانه ای با یک رشته ID منحصر به فرد شناسایی می شوند. برنامه های سرویس گیرنده با این رشته های شناسه به عنوان توکن های غیر شفاف برخورد می کنند.

هنگامی که یک برنامه مشتری می خواهد به یک منوی فرعی مرور کند یا یک آیتم رسانه را پخش کند، رمز را ارسال می کند. برنامه شما مسئول مرتبط کردن توکن با آیتم رسانه ای مناسب است.

این قطعه کد پیاده سازی onLoadChildren را نشان می دهد

کاتلین

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

جاوا

@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 در برنامه نمونه برنامه پخش موسیقی جهانی اندروید در GitHub مراجعه کنید.

ساختار منوی ریشه

Android Auto و Android Automotive OS محدودیت های خاصی در مورد ساختار منوی ریشه دارند. اینها از طریق راهنمایی ریشه به MediaBrowserService منتقل می شوند، که می توانند از طریق آرگومان Bundle که به onGetRoot() ارسال می شود، خوانده شوند. پس از دنبال کردن، این نکات به سیستم اجازه می‌دهد محتوای اصلی را به عنوان برگه‌های ناوبری نمایش دهد. اگر این نکات را دنبال نکنید، ممکن است برخی از محتوای ریشه حذف شود یا توسط سیستم کمتر قابل شناسایی باشد.

محتوای ریشه به عنوان برگه های ناوبری نمایش داده می شود

شکل 1. محتوای ریشه به عنوان برگه های ناوبری نمایش داده می شود.

با اعمال این نکات، سیستم محتوای ریشه را به عنوان برگه های ناوبری نمایش می دهد. با استفاده نکردن از این نکات، ممکن است برخی از محتوای ریشه حذف شوند یا کمتر قابل کشف شوند. این نکات مخابره می شود:

کاتلین

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

جاوا

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 متفاوت باشد.

به عنوان مثال، اگر به طور معمول یک آیتم قابل پخش ریشه را نشان می دهید، ممکن است بخواهید به جای آن، به دلیل ارزش اشاره پرچم های پشتیبانی شده، آن را زیر یک آیتم قابل مرور ریشه قرار دهید.

جدا از نکات ریشه، از این دستورالعمل ها برای رندر بهینه تب ها استفاده کنید:

  • نمادهای تک رنگ (ترجیحاً سفید) برای هر مورد برگه

  • برچسب‌های کوتاه و معنی‌دار برای هر مورد برگه (برچسب‌های کوتاه احتمال کوتاه شدن برچسب‌ها را کاهش می‌دهند)