Google Assistant ให้คุณใช้คำสั่งเสียงเพื่อควบคุมอุปกรณ์ต่างๆ ได้ เช่น Google Home, โทรศัพท์ของคุณ และอีกมากมาย มีความสามารถในตัว เข้าใจคำสั่งสื่อ ("เปิดอะไรก็ตามของ Beyoncé") และรองรับ การควบคุมสื่อ (เช่น หยุดชั่วคราว ข้าม กรอไปข้างหน้า ยกนิ้วโป้ง)
Assistant สื่อสารกับแอปสื่อของ Android โดยใช้สื่อ เซสชัน สามารถใช้ ความตั้งใจหรือบริการในการ เปิดแอปของคุณและเริ่มเล่น เพื่อผลลัพธ์ที่ดีที่สุด แอปของคุณควร ใช้ฟีเจอร์ทั้งหมดที่อธิบายในหน้านี้
ใช้เซสชันสื่อ
แอปเสียงและวิดีโอทุกแอปต้องใช้ เซสชันสื่อ เพื่อให้ Assistant ทำงานได้ ตัวควบคุมการส่งเมื่อการเล่นเริ่มต้นขึ้น
โปรดทราบว่าแม้ Assistant จะใช้เฉพาะการดำเนินการที่ระบุไว้ในส่วนนี้
แนวทางปฏิบัติที่ดีที่สุดคือการใช้ API การเตรียมความพร้อมและการเล่นทั้งหมด
ความสามารถในการใช้งานร่วมกันกับแอปพลิเคชันอื่น สำหรับการดำเนินการใดก็ตามที่คุณไม่รองรับ
Callback ของเซสชันสื่อสามารถแสดงผลข้อผิดพลาดได้โดยใช้
ERROR_CODE_NOT_SUPPORTED
เปิดใช้ตัวควบคุมสื่อและการนำส่งโดยการตั้งค่า Flag เหล่านี้ในแอป
ออบเจ็กต์ 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);
เซสชันสื่อของแอปต้องประกาศการดำเนินการที่รองรับ และใช้
Callback ของเซสชันสื่อที่เกี่ยวข้อง ประกาศการดำเนินการที่รองรับใน
setActions()
โปรแกรมเล่นเพลง Android สากล โปรเจ็กต์ตัวอย่างเป็นตัวอย่างที่ดีของวิธีตั้งค่าเซสชันสื่อ
การเล่น
ในการเริ่มเล่นจากบริการ เซสชันสื่อต้องมีการดำเนินการ PLAY
ต่อไปนี้และ Callback
การทำงาน | การติดต่อกลับ |
---|---|
ACTION_PLAY |
onPlay() |
ACTION_PLAY_FROM_SEARCH |
onPlayFromSearch() |
ACTION_PLAY_FROM_URI (*) |
onPlayFromUri() |
เซสชันของคุณควรใช้การดำเนินการ PREPARE
ต่อไปนี้และ Callback
การทำงาน | การติดต่อกลับ |
---|---|
ACTION_PREPARE |
onPrepare() |
ACTION_PREPARE_FROM_SEARCH |
onPrepareFromSearch() |
ACTION_PREPARE_FROM_URI (*) |
onPrepareFromUri() |
การใช้ API ที่จัดเตรียมจะทำให้เวลาในการตอบสนองการเล่นหลังจากคำสั่งเสียง สามารถลดขนาดลงได้ แอปสื่อที่ต้องการปรับปรุงเวลาในการตอบสนองของการเล่นสามารถใช้ มีเวลามากขึ้นในการเริ่มแคชเนื้อหาและเตรียมการเล่นสื่อ
แยกวิเคราะห์คำค้นหา
เมื่อผู้ใช้ค้นหารายการสื่อที่เฉพาะเจาะจง เช่น "เปิดเพลงแจ๊สใน
[ชื่อแอปของคุณ]" หรือ "ฟัง [ชื่อเพลง]"
onPrepareFromSearch()
หรือ
onPlayFromSearch()
Callback Method จะได้รับพารามิเตอร์การค้นหาและ Bundles เพิ่มเติม
แอปของคุณควรแยกวิเคราะห์คำค้นหาด้วยเสียง และเริ่มเล่นโดยทำตามวิธีต่อไปนี้ ขั้นตอน:
- ใช้กลุ่มเพิ่มเติมและสตริงข้อความค้นหาที่แสดงผลจากการค้นหาด้วยเสียง เพื่อกรองผลลัพธ์
- สร้างคิวการเล่นจากผลลัพธ์เหล่านี้
- เล่นรายการสื่อที่เกี่ยวข้องมากที่สุดจากผลการค้นหา
onPlayFromSearch()
วิธีรับพารามิเตอร์เพิ่มเติมที่มีข้อมูลโดยละเอียดมากขึ้นจากเสียงพูด
ค้นหา บริการเพิ่มเติมเหล่านี้ช่วยให้คุณค้นหาเนื้อหาเสียงในแอปสำหรับการเล่นได้
หากผลการค้นหาไม่สามารถให้ข้อมูลนี้ คุณสามารถใช้ตรรกะได้
แยกวิเคราะห์คำค้นหาดิบ และเล่นแทร็กที่เหมาะสมตาม
คำถาม
Android Automotive OS และ 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()
ถูกเรียกโดยไม่มีคำค้นหา แอปสื่อของคุณควรเล่นปุ่ม "ปัจจุบัน"
สื่อ หากไม่มีสื่อปัจจุบัน แอปควรพยายามเปิดสื่อ เช่น
เป็นเพลงจากเพลย์ลิสต์ล่าสุดหรือคิวแบบสุ่ม Assistant ใช้
API เหล่านี้เมื่อผู้ใช้ขอให้ "เปิดเพลงใน [ชื่อแอปของคุณ]" โดยไม่มี
ข้อมูลเพิ่มเติม
เมื่อผู้ใช้พูดว่า "เปิดเพลงใน [ชื่อแอปของคุณ]" Android Automotive OS หรือ
Android Auto พยายามเปิดแอปและเล่นเสียงโดยโทรหา onPlayFromSearch()
ของแอป
แต่เนื่องจากผู้ใช้ไม่ได้พูดชื่อรายการสื่อ onPlayFromSearch()
จะได้รับพารามิเตอร์การค้นหาที่ว่างเปล่า ในกรณีเหล่านี้ แอปของคุณควร
โต้ตอบด้วยการเล่นเสียงทันที เช่น เพลงจากเพลงล่าสุด
หรือคิวแบบสุ่ม
ประกาศการรองรับการสั่งงานด้วยเสียงแบบเดิม
ในกรณีส่วนใหญ่ การจัดการกับการเล่นที่อธิบายข้างต้นจะทำให้แอปของคุณ ฟังก์ชันการเล่นที่จำเป็น อย่างไรก็ตาม บางระบบกำหนดให้แอปต้องดำเนินการต่อไปนี้ มีตัวกรอง Intent สำหรับการค้นหา คุณควรประกาศการสนับสนุนสำหรับ Intent นี้ ในไฟล์ Manifest ของแอป
ใส่โค้ดนี้ในไฟล์ Manifest สำหรับแอปโทรศัพท์
<activity>
<intent-filter>
<action android:name=
"android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<category android:name=
"android.intent.category.DEFAULT" />
</intent-filter>
</activity>
ตัวควบคุมการรับส่งข้อมูล
หลังจากที่เซสชันสื่อของแอปทำงานแล้ว Assistant จะออกคำสั่งเสียงได้ เพื่อควบคุมการเล่นและอัปเดตข้อมูลเมตาของสื่อ เพื่อให้วิธีนี้ได้ผล ควรทำให้มีการทำงานต่อไปนี้ และติดตั้ง Callback:
การทำงาน | การติดต่อกลับ | คำอธิบาย |
---|---|---|
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
การสั่งงานด้วยเสียงที่คุณสนับสนุนมักจะแตกต่างกันไปตามประเภทเนื้อหา
ประเภทเนื้อหา | การดำเนินการที่จำเป็น |
---|---|
เพลง |
ต้องมีการรองรับ: เล่น หยุดชั่วคราว หยุด ข้ามไปรายการถัดไป และข้ามไปที่ก่อนหน้า แนะนำการสนับสนุนอย่างยิ่งสำหรับ: "กรอไปยัง" |
พอดแคสต์ |
ต้องมีการสนับสนุน: เล่น หยุดชั่วคราว หยุด และกรอไปยัง แนะนำการสนับสนุนสำหรับ: ข้ามไปยังรายการถัดไปและข้ามไปยังก่อนหน้า |
หนังสือเสียง | ต้องมีการสนับสนุน: เล่น หยุดชั่วคราว หยุด และกรอไปยัง |
วิทยุ | ต้องรองรับ: เล่น หยุดชั่วคราว และหยุด |
ข่าว | ต้องมีการรองรับ: เล่น หยุดชั่วคราว หยุด ข้ามไปรายการถัดไป และข้ามไปที่ก่อนหน้า |
วิดีโอ |
ต้องมีการรองรับ: เล่น หยุดชั่วคราว หยุด กรอไปข้างหน้า และกรอไปข้างหน้า แนะนำการสนับสนุนอย่างยิ่งสำหรับ: ข้ามไปยังรายการถัดไปและข้ามไปยังก่อนหน้า |
คุณต้องรองรับการดำเนินการตามที่แสดงไว้ข้างต้นให้ได้มากที่สุดเหมือนกับข้อเสนอผลิตภัณฑ์ อนุญาต แต่ยังตอบสนองต่อการดำเนินการอื่นๆ ได้อย่างดี ตัวอย่างเช่น หาก ผู้ใช้ระดับพรีเมียมสามารถ กลับมาที่รายการก่อนหน้าได้ คุณอาจเพิ่ม ข้อผิดพลาดหากผู้ใช้รุ่นฟรีขอให้ Assistant กลับไปยังรายการก่อนหน้า ดูคําแนะนําเพิ่มเติมในส่วนการจัดการข้อผิดพลาด
ตัวอย่างคำถามแบบเสียงที่จะลองใช้
ตารางต่อไปนี้จะสรุปตัวอย่างการค้นหาที่คุณควรใช้ในฐานะ ทดสอบการใช้งาน:
การติดต่อกลับ MediaSession | วลี "Ok Google" ที่จะใช้ | |
---|---|---|
onPlay() |
"เล่น" "ฟังต่อ" |
|
onPlayFromSearch()
onPlayFromUri() |
เพลง |
"เปิดเพลงหรือเพลงใน (ชื่อแอป)" คำค้นหานี้ว่างเปล่า "เปิด (เพลง | ศิลปิน | อัลบั้ม | แนวเพลง | เพลย์ลิสต์) ใน (ชื่อแอป)" |
วิทยุ | "เปิด (ความถี่ | สถานี) ใน (ชื่อแอป)" | |
Audiobook |
"อ่านหนังสือเสียงของฉันใน (ชื่อแอป)" "อ่าน (หนังสือเสียง) ใน (ชื่อแอป)" |
|
พอดแคสต์ | "เปิด (พอดแคสต์) ใน (ชื่อแอป)" | |
onPause() |
"หยุดชั่วคราว" | |
onStop() |
"หยุด" | |
onSkipToNext() |
"(เพลง | ตอน | แทร็ก) ถัดไป" | |
onSkipToPrevious() |
"(เพลง | ตอน | แทร็ก) ก่อนหน้า" | |
onSeekTo() |
"รีสตาร์ท" "ข้ามไปข้างหน้า ## วินาที" "ย้อนกลับไป ## นาที" |
|
ไม่มี (เก็บ
MediaMetadata
อัปเดตแล้ว) |
"เปิดอะไรอยู่" |
ข้อผิดพลาด
Assistant จัดการข้อผิดพลาดจากเซสชันสื่อเมื่อเกิดเหตุการณ์ขึ้น และส่งรายงาน
ให้แก่ผู้ใช้ ตรวจสอบว่าเซสชันสื่ออัปเดตสถานะการนำส่งและ
ใน PlaybackState
อย่างถูกต้อง ตามที่อธิบายไว้ใน การทำงานกับ
เซสชันสื่อ Assistant
จดจำรหัสข้อผิดพลาดทั้งหมดที่แสดงผลโดย
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
ที่เหลือไว้ตามเดิม
- ตั้งค่ารหัสข้อผิดพลาด
- ผู้ใช้ขอเนื้อหาที่ไม่มีการจับคู่ที่ตรงกันทั้งหมด ตัวอย่างเช่น
ผู้ใช้ระดับพรีเมียมที่ขอเนื้อหาซึ่งมีให้บริการแก่ผู้ใช้ระดับพรีเมียมเท่านั้น
- ขอแนะนำว่าอย่าส่งคืนข้อผิดพลาด และควรให้ความสำคัญ เพื่อหาเกมคล้ายๆ กัน Assistant จะจัดการการพูดมากที่สุด คำตอบที่เป็นเสียงที่เกี่ยวข้องก่อนเริ่มเล่น
การเล่นตามความตั้งใจ
Assistant สามารถเปิดแอปเสียงหรือวิดีโอ และเริ่มเล่นได้โดยส่ง Intent ด้วย Deep Link
ความตั้งใจและ Deep Link อาจมาจากแหล่งที่มาต่างๆ ดังนี้
- เมื่อ Assistant เปิดอยู่ แอปดังกล่าวสามารถใช้การค้นหาของ Google เพื่อเรียกเนื้อหาที่มาร์กอัปที่ ใส่ลิงก์ให้กับการดำเนินการดูวิดีโอ
- เมื่อ Assistant กำลังเริ่มแอป TV แอปของคุณควรมี
ผู้ให้บริการค้นหาทีวี
เพื่อแสดง URI ของเนื้อหาสื่อ Assistant ส่งคำถามไปยัง
ผู้ให้บริการเนื้อหาซึ่งควรแสดงผล Intent ที่มี URI สำหรับ Deep Link และ
การดำเนินการที่ไม่บังคับ
หากการค้นหาแสดงการดำเนินการใน Intent
Assistant จะส่งการดำเนินการและ URI กลับไปยังแอปของคุณ
หากผู้ให้บริการไม่ได้ระบุ
การดําเนินการ Assistant จะเพิ่ม
ACTION_VIEW
ลงใน Intent
Assistant เพิ่ม EXTRA_START_PLAYBACK
ที่มีค่า true
ตามจุดประสงค์ที่ส่งไปยังแอปของคุณ แอปควรเริ่มเล่นเมื่อ
ได้รับ Intent ด้วย EXTRA_START_PLAYBACK
การจัดการ Intent ขณะใช้งาน
ผู้ใช้สามารถขอให้ Assistant เปิดเนื้อหาขณะที่แอปยังเปิดอยู่ได้ เนื้อหาจากคำขอก่อนหน้า ซึ่งหมายความว่าแอปของคุณสามารถรับ Intent ใหม่ๆ เพื่อ เริ่มเล่นขณะที่กิจกรรมการเล่นเปิดขึ้นและใช้งานอยู่แล้ว
กิจกรรมที่รองรับ Intent ที่มี Deep Link ควรลบล้าง
onNewIntent()
ในการจัดการคำขอใหม่
เมื่อเริ่มเล่น Assistant อาจเพิ่ม
แฟล็ก
ตามจุดประสงค์ที่ส่งไปยังแอปของคุณ โดยเฉพาะอย่างยิ่ง อาจเพิ่ม
FLAG_ACTIVITY_CLEAR_TOP
หรือ
FLAG_ACTIVITY_NEW_TASK
หรือทั้งคู่ แม้ว่าโค้ดของคุณ
ไม่จำเป็นต้องจัดการกับการแจ้งว่าไม่เหมาะสมเหล่านี้ แต่ระบบ Android จะตอบสนองต่อการแจ้งดังกล่าว
การทำเช่นนี้อาจส่งผลต่อลักษณะการทำงานของแอปเมื่อมีคำขอเล่นครั้งที่ 2 ที่มี 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
ที่อนุญาตให้เชื่อมต่อจาก Assistant
Assistant สามารถเริ่มแอปด้วยการสื่อสารกับบริการ
media session
บริการเบราว์เซอร์สื่อไม่ควรเรียกใช้กิจกรรม
Assistant จะเปิดกิจกรรมตามPendingIntent
ที่คุณกำหนด
ด้วย setSessionActivity()
อย่าลืมตั้งค่า MediaSession.Token เมื่อคุณ เริ่มต้นบริการเบราว์เซอร์สื่อ อย่าลืมกำหนดการดำเนินการเล่นที่รองรับ ตลอดเวลา รวมถึงในระหว่างการเริ่มต้น Assistant คาดหวังว่าสื่อของคุณ แอปสำหรับตั้งค่าการเล่นก่อนที่ Assistant จะส่งการเล่นครั้งแรก คำสั่ง
โดย Assistant จะใช้ API ไคลเอ็นต์ของเบราว์เซอร์สื่อเพื่อเริ่มต้นใช้งานจากบริการ ดำเนินการเรียกใช้ TransportControl ที่เรียกใช้ Callback การดำเนินการ PLAY บน เซสชันสื่อของแอป
แผนภาพต่อไปนี้แสดงลำดับการเรียกที่ Assistant สร้างขึ้นและ Callback ของเซสชันสื่อที่เกี่ยวข้อง (ระบบจะส่ง Callback ที่เตรียมไว้ให้เท่านั้น หากแอปรองรับ) การเรียกทั้งหมดทำงานไม่พร้อมกัน Assistant จะไม่ทำ รอการตอบกลับจากแอปของคุณ
เมื่อผู้ใช้ออกคําสั่งเสียงเพื่อเล่น Assistant จะตอบกลับด้วยประกาศสั้นๆ ทันทีที่การประกาศเสร็จสมบูรณ์ Assistant จะดําเนินการกับ PLAY ไม่ต้องรอสถานะการเล่นที่เฉพาะเจาะจงใดๆ
หากแอปรองรับการดำเนินการACTION_PREPARE_*
Assistant จะเรียกใช้ PREPARE
ก่อนเริ่มประกาศ
การเชื่อมต่อกับ MediaBrowserService
หากต้องการใช้บริการเพื่อเริ่มแอป Assistant ต้องเชื่อมต่อกับ MediaBrowserService ของแอปได้และ
เรียก MediaSession.Token ระบบจะจัดการคำขอการเชื่อมต่อใน
onGetRoot()
การจัดการคำขอมี 2 วิธีดังนี้
- ยอมรับคำขอเชื่อมต่อทั้งหมด
- ยอมรับคำขอเชื่อมต่อจากแอป Assistant เท่านั้น
ยอมรับคำขอเชื่อมต่อทั้งหมด
คุณต้องคืนค่า BrowserRoot เพื่ออนุญาตให้ Assistant ส่งคำสั่งไปยังเซสชันสื่อของคุณ วิธีที่ง่ายที่สุดคือการอนุญาตให้แอป 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... }
ยอมรับแพ็กเกจแอป Assistant และลายเซ็น
คุณอนุญาตให้ Assistant เชื่อมต่อกับบริการเบราว์เซอร์สื่ออย่างชัดแจ้งได้โดยตรวจสอบชื่อแพ็กเกจและลายเซ็น แอปของคุณจะได้รับชื่อแพ็กเกจในเมธอด onGetRoot ของ MediaBrowserService ของคุณ คุณต้องคืนค่า BrowserRoot เพื่ออนุญาตให้ Assistant ส่งคำสั่งไปยังเซสชันสื่อของคุณ โปรแกรมเล่นเพลงสากล ตัวอย่างจะเก็บรายการชื่อแพ็กเกจและลายเซ็นที่รู้จัก ด้านล่างนี้คือชื่อแพ็กเกจและลายเซ็นที่ Google Assistant ใช้
<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>