«دستیار Google» به شما امکان میدهد از فرمانهای صوتی برای کنترل کردن بسیاری از دستگاهها، مانند Google Home، تلفنتان، و غیره استفاده کنید. این برنامه قابلیت داخلی برای درک فرمانهای رسانه («آهنگی از بیانسه پخش کن») دارد و از کنترلهای رسانه (مثل مکث، رد شدن، جلو بردن سریع، رأی موافق) پشتیبانی میکند.
«دستیار» بااستفاده از جلسه رسانه با برنامههای رسانه Android ارتباط برقرار میکند. این برنامه میتواند از قصدها یا سرویسها برای راهاندازی برنامه شما و شروع بازپخش استفاده کند. برای دریافت بهترین نتایج، برنامهتان باید همه ویژگیهای شرحدادهشده در این صفحه را پیادهسازی کند.
استفاده از جلسه رسانه
هر برنامه صوتی و ویدیویی باید جلسه رسانه را پیادهسازی کند تا «دستیار» بتواند پساز شروع بازپخش، کنترلهای انتقال را اجرا کند.
توجه داشته باشید که اگرچه «دستیار» فقط از کنشهای فهرستشده در این بخش استفاده میکند،
بهترین روش این است که همه میاناهای برنامهسازی کاربردی آمادهسازی و بازپخش را پیادهسازی کنید تا
سازگاری با برنامههای دیگر تضمین شود. برای هر کنشی که پشتیبانی نمیکنید،
فراخوانیهای برگشتی جلسه رسانه میتواند بهسادگی بااستفاده از
ERROR_CODE_NOT_SUPPORTED خطایی را برگرداند.
با تنظیم این پرچمها در شیء MediaSession برنامهتان، کنترلهای رسانه و انتقال را فعال کنید:
کاتلین
session.setFlags( MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS )
جاوا
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 Media Actions را ببینید.
با پیادهسازی میاناهای برنامهسازی کاربردی آمادهسازی، تأخیر بازپخش پساز فرمان صوتی میتواند کاهش یابد. برنامههای رسانهای که میخواهند تأخیر بازپخش را بهبود بخشند میتوانند از زمان اضافی برای شروع ذخیره محتوا در حافظه نهان و آمادهسازی بازپخش رسانه استفاده کنند.
تجزیه پرسمانهای جستجو
وقتی کاربر فایل رسانهای خاصی را جستجو میکند، مثلاً «Play jazz on
[your app name]» یا «Listen to [song title]»، روش فراخوانی برگشتی
onPrepareFromSearch() یا
onPlayFromSearch()
پارامتر پُرسمان و بسته موارد اضافی را دریافت میکند.
برنامه شما باید پرسمان جستجوی گفتاری را تجزیه کند و با دنبال کردن این مراحل، بازپخش را شروع کند:
- از بسته موارد اضافی و رشته پُرسمان جستجوی برگرداندهشده از جستجوی گفتاری برای فیلتر کردن نتایج استفاده کنید.
- صف پخش براساس این نتایج ساخته شود.
- مرتبطترین فایل رسانهای را از نتایج پخش میکند.
روش onPlayFromSearch()
پارامتر extras را با اطلاعات دقیقتر از جستجوی گفتاری میگیرد. این موارد اضافی به شما کمک میکند محتوای صوتی را در برنامهتان برای بازپخش پیدا کنید.
اگر نتایج جستجو نتواند این دادهها را ارائه دهد، میتوانید منطقی را پیادهسازی کنید
تا پرسمان جستجوی خام را تجزیه کند و قطعههای مناسب را براساس
پرسمان پخش کند.
موارد اضافی زیر در «سیستمعامل Android Automotive» و Android Auto پشتیبانی میشوند:
تکهکد زیر نشان میدهد که چگونه روش onPlayFromSearch() را در پیادهسازی MediaSession.Callback خود لغو کنید تا پرسمان جستجوی گفتاری را تجزیه کنید و بازپخش را شروع کنید:
کاتلین
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 } }
جاوا
@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 } }
برای نمونهای دقیقتر درباره نحوه پیادهسازی جستجوی گفتاری برای پخش محتوای صوتی در برنامهتان، نمونه پخشکننده موسیقی Android جهانی را ببینید.
رسیدگی به پُرسمانهای خالی
اگر onPrepare()، onPlay()، onPrepareFromSearch()، یا onPlayFromSearch()
بدون پُرسمان جستجو فراخوانده شوند، برنامه رسانه شما باید رسانه «فعلی» را پخش کند. اگر رسانه فعلی وجود نداشته باشد، برنامه باید سعی کند چیزی پخش کند، مثلاً آهنگی از جدیدترین فهرست پخش یا صف تصادفی. وقتی کاربر بدون ارائه اطلاعات بیشتر درخواست میکند «موسیقی در [نام برنامه شما] پخش شود»، دستیار از این میاناهای برنامهسازی کاربردی استفاده میکند.
وقتی کاربر میگوید «Play music on [your app name]» (در [نام برنامه شما] موسیقی پخش کن)، «سیستمعامل 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>
کنترلهای حملونقل
پساز فعال شدن جلسه رسانه برنامه شما، «دستیار» میتواند فرمانهای صوتی صادر کند تا بازپخش را کنترل کند و فراداده رسانه را بهروز کند. برای اینکه این کار انجام شود، کد شما باید کنشهای زیر را فعال کند و فراخوانهای مربوطه را پیادهسازی کند:
| کنش | پاسخ تماس | شرح |
|---|---|---|
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() |
۳۰ ثانیه به عقب |
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تنظیم کند.
کنشهای گفتاری که پشتیبانی میکنید احتمالاً براساس نوع محتوا متفاوت خواهد بود.
| نوع محتوا | اقدامات لازم |
|---|---|
| موسیقی |
باید از این موارد پشتیبانی کند: پخش، مکث، توقف، پرش به بعدی، و پرش به قبلی بهشدت توصیه میشود از این موارد پشتیبانی شود: Seek To |
| پادکست |
باید پشتیبانی کند: پخش، مکث، توقف، و جستجو به توصیه میکنیم از این موارد پشتیبانی شود: «رفتن به بعدی» و «رفتن به قبلی» |
| کتاب صوتی | باید پشتیبانی کند: پخش، مکث، توقف، و جستجو به |
| رادیو | باید پشتیبانی کند: پخش، مکث، و توقف |
| اخبار | باید از این موارد پشتیبانی کند: پخش، مکث، توقف، پرش به بعدی، و پرش به قبلی |
| ویدیو |
باید از این موارد پشتیبانی کند: پخش، مکث، توقف، جستجو، عقب بردن، و جلو بردن سریع پشتیبانی از این موارد اکیداً توصیه میشود: «رفتن به بعدی» و «رفتن به قبلی» |
باید از هر تعداد کنش فهرستشده در بالا که محصولات پیشنهادیتان اجازه میدهد پشتیبانی کنید، اما همچنان به کنشهای دیگر بهطور مناسب پاسخ دهید. برای مثال، اگر فقط کاربران ممتاز بتوانند به مورد قبلی برگردند، اگر کاربر سطح رایگان از «دستیار» بخواهد به مورد قبلی برگردد، ممکن است خطایی ایجاد کنید. برای راهنمایی بیشتر، بخش رسیدگی به خطا را ببینید.
نمونه پُرسمانهای صوتی برای امتحان کردن
جدول زیر چند پُرسمان نمونه را که باید هنگام آزمایش پیادهسازیتان استفاده کنید نشان میدهد:
| فراخوانی MediaSession | عبارت «Ok Google» برای استفاده | |
|---|---|---|
onPlay() |
«پخش کن.» «ازسرگیری». |
|
onPlayFromSearch()
onPlayFromUri() |
موسیقی |
«موسیقی یا آهنگ در (نام برنامه) پخش کن.» این پُرسمان خالی است. «Play (song | artist | album | genre | playlist) on (app name).» ((آهنگ | هنرمند | آلبوم | ژانر | فهرست پخش) را در (نام برنامه) پخش کن.) |
| رادیو | «Play (frequency | station) on (app name).» ((فرکانس | ایستگاه) را در (نام برنامه) پخش کن.) | |
| کتاب صوتی |
«کتاب صوتیام را در (نام برنامه) بخوان.» «Read (audiobook) on (app name).» ((کتاب صوتی) را در (نام برنامه) بخوان.) |
|
| پادکستها | «Play (podcast) on (app name).» ((پادکست) را در (نام برنامه) پخش کن.) | |
onPause() |
«توقف موقت». | |
onStop() |
«Stop» (توقف). | |
onSkipToNext() |
«Next (song | episode | track).» ((ترانه | قسمت | قطعه) بعدی.) | |
onSkipToPrevious() |
«Previous (song | episode | track).» ([آهنگ | قسمت | قطعه] قبلی.) | |
onSeekTo() |
«بازراهاندازی». «## ثانیه جلو برو.» «Go back ## minutes.» (## دقیقه به عقب برگرد.) |
|
ناموجود (MediaMetadata خود را بهروز نگه دارید) |
«What’s playing?» (چه چیزی درحال پخش است؟) | |
خطاها
«دستیار» خطاهای جلسه رسانه را هنگام وقوع مدیریت میکند و آنها را به کاربران گزارش میدهد. مطمئن شوید که جلسه رسانه شما وضعیت انتقال و کد خطا را در PlaybackState بهدرستی بهروز میکند، همانطور که در کار با جلسه رسانه توضیح داده شده است. «دستیار»
همه کدهای خطای برگرداندهشده توسط
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» برای بازیابی محتوای نشانهگذاریشدهای که کنش تماشا را با پیوند ارائه میدهد استفاده کند.
- وقتی «دستیار» برنامه تلویزیونی را راهاندازی میکند، برنامه شما باید شامل
ارائهدهنده جستجوی تلویزیون
باشد تا URIهای محتوای رسانهای را نمایش دهد. «دستیار» پُرسمانی به ارائهدهنده محتوا ارسال میکند که باید قصدی حاوی URI برای پیوند عمیق و کنش اختیاری برگرداند.
اگر پُرسمان کنشی را در هدف برگرداند،
«دستیار» آن کنش و URI را به برنامهتان برمیگرداند.
اگر ارائهدهنده کنشی را مشخص نکرده باشد،
«دستیار»
ACTION_VIEWرا به «هدف» اضافه میکند.
«دستیار» EXTRA_START_PLAYBACK اضافی را با مقدار true به قصدی که به برنامهتان ارسال میکند اضافه میکند. برنامهتان باید وقتی قصدی با EXTRA_START_PLAYBACK دریافت میکند، بازپخش را شروع کند.
مدیریت کردن هدفها درحین فعال بودن
کاربران میتوانند از «دستیار» بخواهند چیزی را پخش کند، درحالیکه برنامه شما هنوز درحال پخش محتوای درخواست قبلی است. این یعنی برنامهتان میتواند هدفهای جدیدی برای شروع بازپخش دریافت کند، درحالیکه فعالیت بازپخش آن قبلاً راهاندازی و فعال شده است.
فعالیتهایی که از هدفها با پیوندهای عمیق پشتیبانی میکنند باید
onNewIntent()
را لغو کنند تا درخواستهای جدید را مدیریت کنند.
هنگام شروع بازپخش، «دستیار» ممکن است پرچمهای اضافی به قصدی که به برنامه شما ارسال میکند اضافه کند. بهویژه، ممکن است FLAG_ACTIVITY_CLEAR_TOP یا FLAG_ACTIVITY_NEW_TASK یا هر دو را اضافه کند. اگرچه کد شما
نیازی به رسیدگی به این پرچمها ندارد، سیستم Android به آنها پاسخ میدهد.
این امر ممکن است بر رفتار برنامهتان هنگام دریافت دومین درخواست بازپخش با شناسه منبع یکسان جدید
درحالیکه شناسه منبع یکسان قبلی هنوز درحال پخش است تأثیر بگذارد. بهتر است آزمایش کنید که برنامهتان در این مورد چگونه پاسخ میدهد. میتوانید از ابزار خط فرمان 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
داشته باشد که به اتصالات از «دستیار» اجازه دهد،
«دستیار» میتواند با برقراری ارتباط با
media session
سرویس، برنامه را شروع کند.
سرویس مرورگر رسانه هرگز نباید «فعالیتی» را راهاندازی کند.
«دستیار» «فعالیت» شما را براساس PendingIntent که با setSessionActivity() تعریف میکنید راهاندازی میکند.
هنگام راهاندازی سرویس مرورگر رسانه، حتماً MediaSession.Token را تنظیم کنید. بهخاطر داشته باشید که کنشهای بازپخش پشتیبانیشده را همیشه، ازجمله درطول مقداردهی اولیه، تنظیم کنید. «دستیار» انتظار دارد برنامه رسانه شما کنشهای بازپخش را قبلاز اینکه «دستیار» اولین فرمان بازپخش را ارسال کند تنظیم کند.
برای شروع از یک سرویس، «دستیار» میاناهای برنامهسازی کاربردی کارخواه مرورگر رسانه را پیادهسازی میکند. این برنامه تماسهای TransportControls را که بازخوانیهای کنش «پخش» را در جلسه رسانه برنامهتان راهاندازی میکند، اجرا میکند.
نمودار زیر ترتیب تماسهای ایجادشده توسط «دستیار» و فراخوانیهای برگشتی جلسه رسانه مربوطه را نشان میدهد. (فراخوانیهای آمادهسازی فقط درصورتی ارسال میشود که برنامهتان از آنها پشتیبانی کند.) همه تماسها ناهمگام هستند. «دستیار» منتظر هیچ پاسخی از برنامهتان نمیماند.

وقتی کاربر فرمان صوتی برای پخش میدهد، «دستیار» با اعلامی کوتاه پاسخ میدهد. بهمحض اینکه اعلامیه کامل شد، «دستیار» کنش «پخش» را صادر میکند. منتظر هیچ وضعیت بازپخش خاصی نمیماند.
اگر برنامهتان از کنشهای ACTION_PREPARE_* پشتیبانی میکند، «دستیار» قبلاز شروع اعلام، کنش PREPARE را فراخوانی میکند.
درحال اتصال به MediaBrowserService
برای استفاده از سرویس جهت راهاندازی برنامه، «دستیار» باید بتواند به MediaBrowserService برنامه متصل شود و
MediaSession.Token آن را بازیابی کند. درخواستهای اتصال در روش
onGetRoot()
سرویس مدیریت میشود. دو روش برای رسیدگی به درخواستها وجود دارد:
- پذیرفتن همه درخواستهای اتصال
- پذیرفتن درخواستهای اتصال فقط از برنامه «دستیار»
پذیرفتن همه درخواستهای اتصال
برای اینکه به «دستیار» اجازه دهید به جلسه رسانه شما فرمان ارسال کند، باید BrowserRoot را برگردانید. سادهترین راه این است که به همه برنامههای MediaBrowser اجازه دهید به MediaBrowserService شما متصل شوند. باید BrowserRoot غیرتهی برگردانید. کد مربوطه از Universal Music Player در اینجا آمده است:
کاتلین
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... }
جاوا
@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... }
پذیرفتن بسته و امضای برنامه «دستیار»
میتوانید با بررسی نام بسته و امضای سرویس مرورگر رسانه، صریحاً به «دستیار» اجازه دهید به آن متصل شود. برنامهتان نام بسته را در روش onGetRoot از MediaBrowserService شما دریافت خواهد کرد. برای اینکه به «دستیار» اجازه دهید به جلسه رسانه شما فرمان ارسال کند، باید BrowserRoot را برگردانید. نمونه 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>