"مساعد Google" وتطبيقات الوسائط

يتيح لك "مساعد Google" استخدام الطلبات الصوتية للتحكّم في العديد من الأجهزة، مثل Google Home وهاتفك وغير ذلك ولديها قدرة مدمجة على فهم أوامر الوسائط ("تشغيل محتوى بصوت بيونسيه") ويدعم عناصر التحكّم في الوسائط (مثل الإيقاف المؤقت والتخطي والتقديم السريع وإبداء الإعجاب)

يتواصل "مساعد Google" مع تطبيقات الوسائط على Android باستخدام وسائط. . يمكنها استخدام الأهداف أو الخدمات فتح التطبيق وبدء التشغيل. للحصول على أفضل النتائج، يجب أن في تنفيذ جميع الميزات الموضحة في هذه الصفحة.

استخدام جلسة وسائط

يجب أن ينفذ كل تطبيق صوتي وفيديو جلسة وسائط عَلَشَانْ مُسَاعِدْ Google يِشْتَغَلْ عناصر التحكم في النقل بعد بدء التشغيل.

يُرجى ملاحظة أنّه على الرغم من أن المساعد لا يستخدم سوى الإجراءات المذكورة في هذا القسم، وأفضل الممارسات هي تنفيذ جميع واجهات برمجة التطبيقات للإعداد والتشغيل لضمان التوافق مع التطبيقات الأخرى. بالنسبة إلى أي إجراءات لا تدعمها، يمكن أن تؤدي استدعاءات جلسة الوسائط ببساطة إلى عرض خطأ باستخدام ERROR_CODE_NOT_SUPPORTED

يمكنك تفعيل عناصر التحكّم في الوسائط والنقل من خلال وضع هذه العلامات في قسم كائن MediaSession:

Kotlin

session.setFlags(
        MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or
        MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
)

Java

session.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
    MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

يجب أن توضّح جلسة الوسائط في تطبيقك الإجراءات التي يتيحها، وأن تنفّذ استدعاءات جلسة الوسائط المقابلة. يُرجى تعريف الإجراءات المتوافقة في setActions()

تشير رسالة الأشكال البيانية مشغِّل موسيقى Android العالمي نموذج المشروع هو مثال جيد على كيفية إعداد جلسة وسائط.

إجراءات التشغيل

لبدء التشغيل من خدمة، يجب أن تتضمّن جلسة الوسائط إجراءات PLAY هذه مع معاودة الاتصال بها:

الإجراء معاودة الاتصال
ACTION_PLAY onPlay()
ACTION_PLAY_FROM_SEARCH onPlayFromSearch()
ACTION_PLAY_FROM_URI (*) onPlayFromUri()

يجب أن تنفِّذ جلستك أيضًا إجراءات PREPARE هذه واستدعاءاتها:

الإجراء معاودة الاتصال
ACTION_PREPARE onPrepare()
ACTION_PREPARE_FROM_SEARCH onPrepareFromSearch()
ACTION_PREPARE_FROM_URI (*) onPrepareFromUri()

(*) لا تعمل الإجراءات المستندة إلى معرّف الموارد المنتظم (URI) في "مساعد Google" إلا مع الشركات. التي توفر معرفات الموارد المنتظمة (URI) إلى Google. مزيد من المعلومات عن وصف محتوى الوسائط لـ Google راجِع إجراءات الوسائط.

من خلال تنفيذ واجهات برمجة التطبيقات المخصّصة للتحضير، يكون وقت استجابة التشغيل بعد طلب صوتي. المخاطر. يمكن لتطبيقات الوسائط التي تريد تحسين وقت استجابة التشغيل استخدام المزيد من الوقت لبدء تخزين المحتوى في ذاكرة التخزين المؤقت وإعداد تشغيل الوسائط

تحليل طلبات البحث

عندما يبحث المستخدم عن محتوى وسائط معيّن، مثل "تشغيل موسيقى الجاز على [اسم تطبيقك]" أو "الاستماع إلى [عنوان الأغنية]"، onPrepareFromSearch() أو onPlayFromSearch() تتلقى طريقة رد الاتصال معلمة طلب بحث وحزمة إضافية.

يجب أن يحلّل تطبيقك طلب البحث الصوتي وأن يبدأ التشغيل من خلال اتّباع الخطوات التالية: الخطوات:

  1. استخدام حزمة العناصر الإضافية وسلسلة طلب البحث التي يتم عرضها من البحث الصوتي لتصفية النتائج.
  2. إنشاء قائمة انتظار تشغيل استنادًا إلى هذه النتائج.
  3. تشغيل ملف الوسائط الأكثر صلة من النتائج

onPlayFromSearch() تأخذ الطريقة معلمة إضافية مع معلومات أكثر تفصيلاً من الصوت بحث. تساعدك هذه الميزات الإضافية في العثور على المحتوى الصوتي داخل تطبيقك لتشغيله. إذا لم تتمكّن نتائج البحث من تقديم هذه البيانات، يمكنك تطبيق الإجراءات المنطقية تحليل طلب البحث الأولي وتشغيل المسارات المناسبة بناءً على طلب البحث.

تتوفّر الميزات الإضافية التالية في نظامَي التشغيل Android Automotive وAndroid Auto:

يعرض مقتطف الرمز التالي كيفية إلغاء onPlayFromSearch() في MediaSession.Callback التطبيق لتحليل طلب البحث الصوتي وبدء التشغيل:

Kotlin

override fun onPlayFromSearch(query: String?, extras: Bundle?) {
    if (query.isNullOrEmpty()) {
        // The user provided generic string e.g. 'Play music'
        // Build appropriate playlist queue
    } else {
        // Build a queue based on songs that match "query" or "extras" param
        val mediaFocus: String? = extras?.getString(MediaStore.EXTRA_MEDIA_FOCUS)
        if (mediaFocus == MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) {
            isArtistFocus = true
            artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST)
        } else if (mediaFocus == MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) {
            isAlbumFocus = true
            album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM)
        }

        // Implement additional "extras" param filtering
    }

    // Implement your logic to retrieve the queue
    var result: String? = when {
        isArtistFocus -> artist?.also {
            searchMusicByArtist(it)
        }
        isAlbumFocus -> album?.also {
            searchMusicByAlbum(it)
        }
        else -> null
    }
    result = result ?: run {
        // No focus found, search by query for song title
        query?.also {
            searchMusicBySongTitle(it)
        }
    }

    if (result?.isNotEmpty() == true) {
        // Immediately start playing from the beginning of the search results
        // Implement your logic to start playing music
        playMusic(result)
    } else {
        // Handle no queue found. Stop playing if the app
        // is currently playing a song
    }
}

Java

@Override
public void onPlayFromSearch(String query, Bundle extras) {
    if (TextUtils.isEmpty(query)) {
        // The user provided generic string e.g. 'Play music'
        // Build appropriate playlist queue
    } else {
        // Build a queue based on songs that match "query" or "extras" param
        String mediaFocus = extras.getString(MediaStore.EXTRA_MEDIA_FOCUS);
        if (TextUtils.equals(mediaFocus,
                MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE)) {
            isArtistFocus = true;
            artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST);
        } else if (TextUtils.equals(mediaFocus,
                MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE)) {
            isAlbumFocus = true;
            album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM);
        }

        // Implement additional "extras" param filtering
    }

    // Implement your logic to retrieve the queue
    if (isArtistFocus) {
        result = searchMusicByArtist(artist);
    } else if (isAlbumFocus) {
        result = searchMusicByAlbum(album);
    }

    if (result == null) {
        // No focus found, search by query for song title
        result = searchMusicBySongTitle(query);
    }

    if (result != null && !result.isEmpty()) {
        // Immediately start playing from the beginning of the search results
        // Implement your logic to start playing music
        playMusic(result);
    } else {
        // Handle no queue found. Stop playing if the app
        // is currently playing a song
    }
}

للاطّلاع على مثال أكثر تفصيلاً حول كيفية تنفيذ البحث الصوتي لتشغيل محتوى صوتي المحتوى في تطبيقك، يُرجى مراجعة Universal Android Music Player كعينة.

التعامل مع الطلبات الفارغة

إذا كانت onPrepare() أو onPlay() أو onPrepareFromSearch() أو onPlayFromSearch() بدون طلب بحث، فينبغي أن يشغّل تطبيق الوسائط "الحالي" الوسائط. إذا لم تكن هناك وسائط حالية، فينبغي أن يحاول التطبيق تشغيل محتوى، مثل كأغنية من أحدث قائمة تشغيل أو قائمة انتظار عشوائية يستخدم المساعد واجهات برمجة التطبيقات هذه عندما يطلب المستخدم "تشغيل الموسيقى على [اسم تطبيقك]" بدون معلومات إضافية.

عندما يقول المستخدم "تشغيل الموسيقى على [اسم تطبيقك]"، أو على نظام التشغيل Android Automotive، يحاول Android Auto تشغيل تطبيقك وتشغيل الصوت من خلال الاتصال برقم onPlayFromSearch() في تطبيقك. . ومع ذلك، بما أنّ المستخدم لم يذكر اسم عنصر الوسائط، تم استخدام onPlayFromSearch() على معلمة طلب بحث فارغة. في هذه الحالات، ينبغي أن الاستجابة من خلال تشغيل صوت على الفور، مثل أغنية من أحدث صوت قائمة تشغيل أو قائمة انتظار عشوائية

إعلان الدعم القديم للإجراءات الصوتية

في معظم الحالات، يؤدي التعامل مع إجراءات التشغيل الموضحة أعلاه إلى منح التطبيق كل وظيفة التشغيل التي يحتاجها. مع ذلك، تتطلّب بعض الأنظمة من تطبيقك يحتوي على فلتر الأهداف للبحث. يجب الإفصاح عن دعم لهدف Intent هذا. في ملفات بيان التطبيق.

أدرج هذا الرمز في ملف البيان لتطبيق الهاتف:

<activity>
    <intent-filter>
        <action android:name=
             "android.media.action.MEDIA_PLAY_FROM_SEARCH" />
        <category android:name=
             "android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

عناصر التحكم في النقل

بعد تفعيل جلسة الوسائط في التطبيق، يمكن لخدمة "مساعد Google" إصدار طلبات صوتية. للتحكم في التشغيل وتحديث البيانات الوصفية للوسائط. لكي ينجح ذلك، يجب تفعيل الإجراءات التالية وتنفيذ الإجراءات عمليات الاسترداد:

الإجراء معاودة الاتصال الوصف
ACTION_SKIP_TO_NEXT onSkipToNext() الفيديو التالي
ACTION_SKIP_TO_PREVIOUS onSkipToPrevious() الأغنية السابقة
ACTION_PAUSE, ACTION_PLAY_PAUSE onPause() إيقاف مؤقت
ACTION_STOP onStop() إيقاف
ACTION_PLAY onPlay() استئناف
ACTION_SEEK_TO onSeekTo() ترجيع الفيديو بمقدار 30 ثانية
ACTION_SET_RATING onSetRating(android.support.v4.media.RatingCompat) رائع/لا يعجبني.
ACTION_SET_CAPTIONING_ENABLED onSetCaptioningEnabled(boolean) تفعيل/إيقاف الشرح

ملاحظة:

  • ولكي تعمل أوامر البحث، يجب تحديث "PlaybackState" في state, position, playback speed, and update time. يجب أن يتصل التطبيق بـ setPlaybackState() عند تغيير الحالة.
  • يجب أن يحافظ تطبيق الوسائط أيضًا على تحديث البيانات الوصفية لجلسة الوسائط. يتوافق هذا الملف مع أسئلة مثل "ما عنوان الأغنية التي يتم تشغيلها؟". يجب أن يطلب التطبيق الاتصال بالرقم setMetadata() عند تغيير الحقول المعنية (مثل عنوان المقطع الصوتي والفنان والاسم).
  • يجب ضبط MediaSession.setRatingType() للإشارة إلى نوع التقييم المتوافق مع التطبيق، ويجب أن يستخدم التطبيق onSetRating(). إذا كان التطبيق لا يتيح استخدام التقييم، يجب ضبط نوع التقييم على "RATING_NONE".

من المحتمل أن تختلف الإجراءات الصوتية التي تتيحها حسب نوع المحتوى.

نوع المحتوى الإجراءات المطلوبة
الموسيقى

ضرورة الدعم: التشغيل والإيقاف المؤقت والإيقاف والتخطّي إلى التالي والتخطّي إلى السابق

أوصي بشدة بالحصول على الدعم لـ: البحث عن

بودكاست

ضرورة التشغيل: التشغيل والإيقاف المؤقت والإيقاف والتقديم

اقتراح الدعم لـ: التخطّي إلى التالي والتخطّي إلى السابق

كتاب مسموع ضرورة التشغيل: التشغيل والإيقاف المؤقت والإيقاف والتقديم
راديو ضرورة التشغيل: التشغيل والإيقاف المؤقت والإيقاف
الأخبار ضرورة الدعم: التشغيل والإيقاف المؤقت والإيقاف والتخطّي إلى التالي والتخطّي إلى السابق
فيديو

ضرورة التشغيل: التشغيل والإيقاف المؤقت والإيقاف والعرض والترجيع والتقديم السريع

يُنصح بشدة بدعمي لـ: "التخطّي إلى التالي" و"التخطّي إلى السابق"

يجب أن تتيح أكبر عدد من الإجراءات المذكورة أعلاه كعروض منتجاتك. والسماح بها، مع الاستمرار في الاستجابة بشكل رشيق لأي إجراءات أخرى. على سبيل المثال، إذا كان يتمكن المستخدمون المتميزون من العودة إلى العنصر السابق، ويمكنك رفع ستظهر رسالة خطأ إذا طلب مستخدم من المستوى المجاني من "مساعد Google" العودة إلى العنصر السابق. راجِع قسم معالجة الأخطاء للحصول على مزيد من الإرشادات.

نماذج طلبات بحث صوتية يمكنك تجربتها

يوضح الجدول التالي بعض نماذج الاستعلامات التي يجب أن تستخدمها أثناء لاختبار عملية التنفيذ:

معاودة الاتصال بجلسة MediaSession استخدام عبارة "Ok Google"
onPlay()

"تشغيل"

"استئناف التشغيل"

onPlayFromSearch()
onPlayFromUri()
الموسيقى

"تشغيل الموسيقى أو الأغاني على (اسم التطبيق)" هذا طلب بحث فارغ.

"تشغيل (أغنية | فنان | ألبوم | نوع | قائمة تشغيل) على (اسم التطبيق)"

الراديو "تشغيل (التردد | المحطة) على (اسم التطبيق)"
كتاب مسموع

"أريد قراءة الكتاب المسموع على (اسم التطبيق)"

"قراءة (كتاب مسموع) على (اسم التطبيق)"

Podcasts "تشغيل (بودكاست) على (اسم التطبيق)"
onPause() "الإيقاف مؤقّتًا"
onStop() "إيقاف"
onSkipToNext() "التالي (الأغنية | الحلقة | المقطع الصوتي)"
onSkipToPrevious() "السابق (الأغنية | الحلقة | المقطع الصوتي)"
onSeekTo()

"إعادة التشغيل"

"تخطّي ## ثانية"

"الرجوع ## دقيقة"

لا ينطبق (احرص على MediaMetadata تحديث) "ما الذي يتم تشغيله الآن؟"

الأخطاء

يعالج "مساعد Google" الأخطاء الناتجة عن جلسة وسائط عند حدوثها، ويبلغ عن هذه الأخطاء. للمستخدمين. احرص على أن تعمل جلسة الوسائط على تحديث حالة النقل رمز الخطأ في PlaybackState بشكل صحيح، كما هو موضح في العمل باستخدام جلسة وسائط. مساعد Google جميع رموز الأخطاء التي تم إرجاعها بواسطة getErrorCode()

الحالات التي يُساء التعامل معها بشكل شائع

في ما يلي بعض الأمثلة على حالات الخطأ التي يجب التأكّد من معالجتها بشكل صحيح:

  • على المستخدم تسجيل الدخول.
    • اضبط رمز الخطأ PlaybackState على ERROR_CODE_AUTHENTICATION_EXPIRED.
    • اضبط رسالة الخطأ PlaybackState.
    • إذا لزم الأمر للتشغيل، اضبط الحالة PlaybackState على STATE_ERROR، الاحتفاظ ببقية PlaybackState كما هي.
  • يطلب المستخدم اتخاذ إجراء غير متاح.
    • اضبط رمز الخطأ PlaybackState بشكلٍ مناسب. على سبيل المثال، اضبط قيمة من PlaybackState إلى ERROR_CODE_NOT_SUPPORTED إذا لم يكن الإجراء متاحًا أو ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED إذا كان الإجراء محميًا من تسجيل الدخول.
    • اضبط رسالة الخطأ PlaybackState.
    • سيتم الاحتفاظ ببقية بيانات "PlaybackState" كما هي.
  • يطلب المستخدم الحصول على محتوى غير متوفّر في التطبيق.
    • اضبط رمز الخطأ PlaybackState بشكلٍ مناسب. على سبيل المثال، استخدم ERROR_CODE_NOT_AVAILABLE_IN_REGION
    • اضبط رسالة الخطأ PlaybackState.
    • يمكنك ضبط حالة PlaybackSate على STATE_ERROR لإيقاف التشغيل. الاحتفاظ ببقية PlaybackState كما هي.
  • يطلب المستخدم محتوًى لا تتوفّر فيه المطابقة التامة. على سبيل المثال، مستخدم ذي الفئة المجانية يطلب تقديم محتوى يتوفر فقط لمستخدمي الفئة المميزة.
    • ننصحك بعدم عرض رسالة خطأ، ووضع الأولوية بدلاً من ذلك العثور على شيء مشابه للعب. سيتعامل "مساعد Google" بأكبر قدر من التحدّث استجابة صوتية ذات صلة قبل بدء التشغيل.

تشغيل المحتوى لغرض معيّن

يمكن للمساعد تشغيل تطبيق صوت أو فيديو وبدء التشغيل من خلال إرسال نية الشراء باستخدام رابط لصفحة في التطبيق.

يمكن أن يكون القصد والرابط لصفحة معيّنة خاصة به من مصادر مختلفة:

  • عندما يكون "مساعد Google" مفعلاً عند بدء تشغيل تطبيق جوال، يمكنه استخدام بحث Google لاسترداد المحتوى المرمز الذي إجراء مشاهدة مع رابط.
  • عندما يشغِّل "مساعد Google" أحد تطبيقات التلفزيون، يجب أن يتضمّن التطبيق مقدِّم خدمة البحث عن برامج تلفزيونية لكشف معرفات الموارد المنتظمة (URI) لمحتوى الوسائط. يُرْسِلْ مُسَاعِدْ Google طَلَبًا إِلَى موفِّر المحتوى الذي يجب أن يعرض هدفًا يحتوي على عنوان URI للرابط لصفحة في التطبيق إجراء اختياري. إذا عرض الاستعلام إجراءً في intent، يرسل المساعد هذا الإجراء ومعرّف الموارد المنتظم (URI) مرة أخرى إلى التطبيق. إذا لم يحدده مزود الخدمة إجراء، سيضيف "مساعد Google" الرمز ACTION_VIEW إلى الهدف.

يضيف "مساعد Google" ميزة "EXTRA_START_PLAYBACK" الإضافية بقيمة true. إلى الغرض الذي يرسله المستخدم إلى تطبيقك. من المفترض أن يبدأ تطبيقك التشغيل عندما تتلقّى هدفًا مع EXTRA_START_PLAYBACK.

التعامل مع الأهداف أثناء النشاط

يمكن للمستخدمين أن يطلبوا من "مساعد Google" تشغيل محتوى معيّن عندما يكون تطبيقك لا يزال قيد التشغيل. محتوى من طلب سابق. يعني ذلك أنّ تطبيقك يمكن أن يتلقّى أغراضًا جديدة بدء التشغيل عندما يكون نشاط التشغيل قيد التشغيل ونشطًا بالفعل.

يجب إلغاء الأنشطة التي تدعم الأهداف التي تتضمّن روابط لصفحات معيّنة onNewIntent() لمعالجة الطلبات الجديدة.

عند بدء التشغيل، قد يضيف "مساعد Google" العلامة إلى الغرض الذي يرسله المستخدم إلى تطبيقك. على وجه الخصوص، قد تضيف FLAG_ACTIVITY_CLEAR_TOP أو FLAG_ACTIVITY_NEW_TASK أو كليهما. وعلى الرغم من أن التعليمات البرمجية لا يحتاج إلى معالجة هذه المشاكل، وسيستجيب نظام Android لها. وقد يؤثِّر ذلك في سلوك تطبيقك عند تلقّي طلب تشغيل ثانٍ يتضمّن معرّف موارد منتظم (URI) جديد. بينما لا يزال عنوان URI السابق قيد التشغيل. ومن الأفضل اختبار طريقة استجابة تطبيقك في هذه الحالة. يمكنك استخدام الأمر adb سطر الأداة لمحاكاة الموقف (القيم 0x14000000 الثابت هو استخدام OR على مستوى البت المنطقي لكلتا العلامتين):

adb shell 'am start -a android.intent.action.VIEW --ez android.intent.extra.START_PLAYBACK true -d "<first_uri>"' -f 0x14000000
adb shell 'am start -a android.intent.action.VIEW --ez android.intent.extra.START_PLAYBACK true -d "<second_uri>"' -f 0x14000000

التشغيل من خدمة

إذا كان تطبيقك يحتوي على media browser service تسمح بالاتصالات من "مساعد Google" يمكن للمساعد تشغيل التطبيق من خلال التواصل مع media session لا يجب أبدًا تشغيل أي نشاط من خلال خدمة متصفح الوسائط. سيشغِّل "مساعد Google" نشاطك استنادًا إلى "PendingIntent" الذي تحدّده. باستخدام setSessionActivity().

تأكد من تحديد MediaSession.Token عند إعداد خدمة متصفِّح الوسائط لا تنسَ ضبط إجراءات التشغيل المتوافقة. في جميع الأوقات، بما في ذلك أثناء عملية الإعداد. يتوقّع "مساعد Google" عرض الوسائط التطبيق لضبط إجراءات التشغيل قبل أن يرسل "مساعد Google" أول عملية تشغيل الأمر.

للبدء من إحدى الخدمات، ينفِّذ "مساعد Google" واجهات برمجة التطبيقات لعميل متصفِّح الوسائط. يتم إجراء مكالمات TransportControls التي تؤدي إلى تنفيذ طلبات معاودة الاتصال بإجراء PLAY على جلسة وسائط التطبيق.

يوضّح المخطّط التالي ترتيب المكالمات التي أنشأها "مساعد Google" استدعاءات جلسة الوسائط المقابلة. (يتم إرسال استدعاءات التجهيز فقط إذا كان تطبيقك يتيحها). جميع المكالمات غير متزامنة. لا يستجيب "مساعد Google" انتظر أي رد من التطبيق.

بدء التشغيل باستخدام جلسة وسائط

عندما يُصدر المستخدم طلبًا صوتيًا لتشغيله، يستجيب "مساعد Google" بإعلان قصير. بعد اكتمال الإعلان، يصدر "مساعد Google" إجراءً في PLAY. وهي لا تنتظر أي حالة تشغيل محدّدة.

إذا كان تطبيقك يتيح تنفيذ إجراءات "ACTION_PREPARE_*"، يطلب "مساعد Google" الإجراء PREPARE قبل بدء الإشعار.

الاتصال بخدمة MediaBrowserService

لبدء استخدام خدمة ما، يجب أن يتمكّن "مساعد Google" من الاتصال بتطبيق MediaBrowserService في التطبيق. لاسترداد MediaSession.Token الخاصة به. تتم معالجة طلبات الاتصال في واجهة برمجة تطبيقات onGetRoot() . تتوفّر طريقتان للتعامل مع الطلبات:

  • قبول جميع طلبات الربط
  • قبول طلبات الربط من تطبيق "مساعد Google" فقط

قبول جميع طلبات الربط

يجب عرض BrowserRoot للسماح لـ "مساعد Google" بإرسال الأوامر إلى جلسة الوسائط. أسهل طريقة هي السماح لجميع تطبيقات MediaBrowser بالاتصال بخدمة MediaBrowserService. يجب عرض BrowserRoot غير فارغ. إليك الرمز الساري من Universal Music Player:

Kotlin

override fun onGetRoot(
        clientPackageName: String,
        clientUid: Int,
        rootHints: Bundle?
): BrowserRoot? {

    // To ensure you are not allowing any arbitrary app to browse your app's contents, you
    // need to check the origin:
    if (!packageValidator.isCallerAllowed(this, clientPackageName, clientUid)) {
        // If the request comes from an untrusted package, return an empty browser root.
        // If you return null, then the media browser will not be able to connect and
        // no further calls will be made to other media browsing methods.
        Log.i(TAG, "OnGetRoot: Browsing NOT ALLOWED for unknown caller. Returning empty "
                + "browser root so all apps can use MediaController. $clientPackageName")
        return MediaBrowserServiceCompat.BrowserRoot(MEDIA_ID_EMPTY_ROOT, null)
    }

    // Return browser roots for browsing...
}

Java

@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid,
                             Bundle rootHints) {

    // To ensure you are not allowing any arbitrary app to browse your app's contents, you
    // need to check the origin:
    if (!packageValidator.isCallerAllowed(this, clientPackageName, clientUid)) {
        // If the request comes from an untrusted package, return an empty browser root.
        // If you return null, then the media browser will not be able to connect and
        // no further calls will be made to other media browsing methods.
        LogHelper.i(TAG, "OnGetRoot: Browsing NOT ALLOWED for unknown caller. "
                + "Returning empty browser root so all apps can use MediaController."
                + clientPackageName);
        return new MediaBrowserServiceCompat.BrowserRoot(MEDIA_ID_EMPTY_ROOT, null);
    }

    // Return browser roots for browsing...
}

قبول توقيع وحزمة تطبيق "مساعد Google"

يمكنك السماح لخدمة "مساعد Google" بشكل صريح بالاتصال بخدمة متصفّح الوسائط من خلال التحقّق من اسم الحزمة وتوقيعها. سيتلقّى تطبيقك اسم الحزمة في طريقة onGetRoot في MediaBrowserService. يجب عرض BrowserRoot للسماح لـ "مساعد Google" بإرسال الأوامر إلى جلسة الوسائط. تشير رسالة الأشكال البيانية Universal Music Player يحتفظ النموذج بقائمة بأسماء وتوقيعات الحزمة المعروفة. في ما يلي أسماء الحِزم والتوقيعات التي يستخدمها "مساعد Google".

<signature name="Google" package="com.google.android.googlequicksearchbox">
    <key release="false">19:75:b2:f1:71:77:bc:89:a5:df:f3:1f:9e:64:a6:ca:e2:81:a5:3d:c1:d1:d5:9b:1d:14:7f:e1:c8:2a:fa:00</key>
    <key release="true">f0:fd:6c:5b:41:0f:25:cb:25:c3:b5:33:46:c8:97:2f:ae:30:f8:ee:74:11:df:91:04:80:ad:6b:2d:60:db:83</key>
</signature>

<signature name="Google Assistant on Android Automotive OS" package="com.google.android.carassistant">
    <key release="false">17:E2:81:11:06:2F:97:A8:60:79:7A:83:70:5B:F8:2C:7C:C0:29:35:56:6D:46:22:BC:4E:CF:EE:1B:EB:F8:15</key>
    <key release="true">74:B6:FB:F7:10:E8:D9:0D:44:D3:40:12:58:89:B4:23:06:A6:2C:43:79:D0:E5:A6:62:20:E3:A6:8A:BF:90:E2</key>
</signature>