Android Auto และ Android Automotive OS ช่วยให้คุณนําเนื้อหาแอปสื่อไปยัง ในรถของผู้ใช้ แอปสื่อสำหรับรถยนต์ต้องให้บริการเบราว์เซอร์สื่อ เพื่อให้ Android Auto และ Android Automotive OS หรือแอปอื่นที่มีสื่อ สามารถค้นพบและแสดงเนื้อหาของคุณ
คู่มือนี้จะถือว่าคุณมีแอปสื่อที่เล่นเสียงใน โทรศัพท์และแอปสื่อของคุณสอดคล้องกับแอปสื่อของ Android สถาปัตยกรรม
คู่มือนี้จะอธิบายคอมโพเนนต์ที่จําเป็นของ MediaBrowserService
และ
MediaSession
ที่แอปของคุณต้องใช้เพื่อทำงานบน Android Auto หรือ Android
Automotive OS หลังจากที่คุณสร้างโครงสร้างพื้นฐานของสื่อหลักเสร็จสมบูรณ์แล้ว คุณจะสามารถ
เพิ่มการสนับสนุนสำหรับ Android Auto และเพิ่มการสนับสนุนสำหรับ
Android Automotive OS ไปยังสื่อของคุณ
แอป
ก่อนเริ่มต้น
- อ่านเอกสารประกอบของ Android Media API
- อ่านหัวข้อสร้างแอปสื่อ เพื่อรับคำแนะนำในการออกแบบ
- ตรวจสอบคำศัพท์และแนวคิดสำคัญที่แสดงในส่วนนี้
คำสำคัญและแนวคิด
- บริการเบราว์เซอร์สื่อ
- บริการ Android ที่ใช้งานโดยแอปสื่อซึ่งปฏิบัติตามข้อกำหนด
MediaBrowserServiceCompat
API แอปของคุณใช้บริการนี้เพื่อแสดงเนื้อหาของแอป - เบราว์เซอร์สื่อ
- API ที่แอปสื่อใช้เพื่อค้นหาบริการเบราว์เซอร์สื่อและการแสดงผล เนื้อหาของตน Android Auto และ Android Automotive OS ใช้เบราว์เซอร์สื่อเพื่อ ค้นหาบริการเบราว์เซอร์สื่อของแอป
- รายการสื่อ
เบราว์เซอร์สื่อจะจัดระเบียบเนื้อหาเป็นแผนผังของ
MediaItem
ออบเจ็กต์ รายการสื่ออาจมีแฟล็กต่อไปนี้อย่างใดอย่างหนึ่งหรือทั้ง 2 อย่างFLAG_PLAYABLE
: ระบุว่ารายการเป็นใบไม้ในแผนผังเนื้อหา รายการจะแสดงสตรีมเสียงเดียว เช่น เพลงในอัลบั้ม บทในหนังสือเสียง หรือตอนของพอดแคสต์FLAG_BROWSABLE
: ระบุว่ารายการเป็นโหนดในโครงสร้างเนื้อหาและรายการ มีบุตร ตัวอย่างเช่น รายการแสดงถึงอัลบั้ม และรายการย่อยคือ เพลงในอัลบั้ม
รายการสื่อที่ทั้งสามารถเลือกดูได้และเล่นได้ เช่น เพลย์ลิสต์ คุณสามารถ เลือกรายการด้วยตนเองเพื่อเล่นเด็กทั้งหมดของรายการนั้น หรือคุณสามารถเรียกดู
- เพิ่มประสิทธิภาพยานพาหนะ
กิจกรรมสําหรับแอป Android Automotive OS ที่ปฏิบัติตาม หลักเกณฑ์การออกแบบของ Android Automotive OS อินเทอร์เฟซสำหรับกิจกรรมเหล่านี้ไม่ได้วาดโดย Android Automotive OS ดังนั้นคุณจึง ต้องตรวจสอบว่าแอปของคุณเป็นไปตามหลักเกณฑ์ด้านการออกแบบ โดยทั่วไปแล้ว ประกอบด้วยเป้าหมายการแตะและขนาดแบบอักษรที่ใหญ่ขึ้น การรองรับโหมดกลางวันและกลางคืน และ อัตราคอนทราสต์ที่สูงขึ้น
อนุญาตให้แสดงอินเทอร์เฟซผู้ใช้ที่เพิ่มประสิทธิภาพยานพาหนะเฉพาะเมื่อ ข้อจำกัดเกี่ยวกับประสบการณ์ของผู้ใช้ (CUXR) จะไม่มีผลเนื่องจากข้อจำกัดเหล่านี้ ของอินเทอร์เฟซอาจต้องใช้ความสนใจหรือการโต้ตอบจากผู้ใช้มากขึ้น CUXR ไม่มีผลเมื่อรถหยุดหรือจอดอยู่แต่จะทำงานตลอดเวลา เมื่อรถเคลื่อนที่
คุณไม่จำเป็นต้องออกแบบกิจกรรมสำหรับ Android Auto เพราะ Android Auto จะแสดงอินเทอร์เฟซที่ปรับให้เหมาะกับยานพาหนะของตนเอง โดยใช้ข้อมูลจาก บริการเบราว์เซอร์สื่อ
กำหนดค่าไฟล์ Manifest ของแอป
ก่อนที่คุณจะสร้างบริการเบราว์เซอร์สื่อ คุณจะต้องกำหนดค่า ไฟล์ Manifest ของแอป
ประกาศบริการเบราว์เซอร์สื่อของคุณ
ทั้ง Android Auto และ Android Automotive OS เชื่อมต่อกับแอปของคุณผ่าน บริการเบราว์เซอร์สื่อเพื่อเรียกดูรายการสื่อ ประกาศสื่อของคุณ บริการเบราว์เซอร์ในไฟล์ Manifest ของคุณเพื่ออนุญาตให้ Android Auto และ Android Automotive OS สำรวจบริการและเชื่อมต่อกับแอปของคุณ
ข้อมูลโค้ดต่อไปนี้แสดงวิธีประกาศบริการเบราว์เซอร์สื่อใน ไฟล์ Manifest ใส่โค้ดนี้ในไฟล์ Manifest สำหรับ โมดูล Android Automotive OS และในไฟล์ Manifest สําหรับแอปโทรศัพท์
<application>
...
<service android:name=".MyMediaBrowserService"
android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
...
</application>
ระบุไอคอนแอป
คุณต้องระบุไอคอนแอปที่ Android Auto และ Android Automotive OS ทำได้ ใช้เพื่อแสดงแอปของคุณใน UI ของระบบ ต้องมีไอคอน 2 ประเภทดังนี้
- ไอคอน Launcher
- ไอคอนระบุแหล่งที่มา
ไอคอน Launcher
ไอคอน Launcher แสดงถึงแอปของคุณใน UI ของระบบ เช่น บน Launcher และในถาดไอคอน คุณระบุได้ว่าต้องการใช้ไอคอนจาก แอปบนอุปกรณ์เคลื่อนที่เพื่อแสดงแอปสื่อของรถยนต์โดยใช้ไฟล์ Manifest ต่อไปนี้ การประกาศ:
<application
...
android:icon="@mipmap/ic_launcher"
...
/>
หากต้องการใช้ไอคอนอื่นที่ไม่ใช่ไอคอนของแอปบนอุปกรณ์เคลื่อนที่ ให้ตั้งค่าพร็อพเพอร์ตี้ android:icon
ในองค์ประกอบ <service>
ของบริการเบราว์เซอร์สื่อของคุณในไฟล์ Manifest
<application>
...
<service
...
android:icon="@mipmap/auto_launcher"
...
/>
</application>
ไอคอนระบุแหล่งที่มา
![](https://developer.android.google.cn/static/images/training/cars/attribution-icon.png?authuser=19&hl=th)
รูปที่ 1 ไอคอนระบุแหล่งที่มาบนการ์ดสื่อ
ไอคอนการแสดงที่มาจะใช้ในจุดที่เนื้อหาสื่อมีลำดับความสำคัญเหนือกว่า เช่น ในการ์ดสื่อ ลองนำไอคอนขนาดเล็กที่ใช้สำหรับการแจ้งเตือนมาใช้ซ้ำ ไอคอนนี้ต้องเป็นโมโนโครม คุณระบุไอคอนที่ใช้แสดงได้ แอปของคุณโดยใช้การประกาศต่อไปนี้ในไฟล์ Manifest
<application>
...
<meta-data
android:name="androidx.car.app.TintableAttributionIcon"
android:resource="@drawable/ic_status_icon" />
...
</application>
สร้างบริการเบราว์เซอร์สื่อ
คุณสร้างบริการเบราว์เซอร์สื่อโดยการขยาย MediaBrowserServiceCompat
จากนั้นทั้ง Android Auto และ Android Automotive OS ก็จะใช้บริการของคุณได้
ทำสิ่งต่อไปนี้ได้
- เรียกดูลำดับชั้นเนื้อหาของแอปเพื่อนำเสนอเมนูให้แก่ผู้ใช้
- รับโทเค็นสำหรับ
MediaSessionCompat
ของแอป เพื่อควบคุมการเล่นเสียง
คุณยังใช้บริการเบราว์เซอร์สื่อเพื่อช่วยให้ไคลเอ็นต์อื่นๆ เข้าถึงเนื้อหาสื่อจากแอป ไคลเอ็นต์สื่อเหล่านี้อาจเป็นแอปอื่นๆ ใน โทรศัพท์ของผู้ใช้ หรือพวกเขาอาจเป็นไคลเอ็นต์ระยะไกลอื่นๆ
เวิร์กโฟลว์บริการเบราว์เซอร์สื่อ
ส่วนนี้อธิบายวิธีที่ Android Automotive OS และ Android โต้ตอบกับบริการเบราว์เซอร์สื่อโดยอัตโนมัติในกระบวนการทำงานของผู้ใช้ทั่วไป
- ผู้ใช้เปิดแอปของคุณใน Android Automotive OS หรือ Android Auto
- Android Automotive OS หรือ Android Auto ติดต่อเบราว์เซอร์สื่อของแอป
บริการที่ใช้
onCreate()
ในการติดตั้งใช้งานonCreate()
คุณต้องสร้างและลงทะเบียนMediaSessionCompat
และออบเจ็กต์ Callback ของออบเจ็กต์ - Android Automotive OS หรือ Android Auto เรียกใช้
onGetRoot()
ของบริการ เพื่อรับรายการสื่อรูทในลำดับชั้นเนื้อหาของคุณ รายการสื่อรูท ไม่แสดง แต่จะใช้เพื่อดึงเนื้อหาเพิ่มเติมจากแอปของคุณแทน - Android Automotive OS หรือ Android Auto โทรหาบริการของคุณ
onLoadChildren()
วิธีรับรายการย่อยของรายการสื่อราก Android Automotive OS และ Android Auto แสดงรายการสื่อเหล่านี้เป็นรายการเนื้อหาระดับบนสุด โปรดดู จัดโครงสร้างเมนูรากในหน้านี้สำหรับข้อมูลเพิ่มเติม เกี่ยวกับสิ่งที่ระบบคาดหวังในระดับนี้ - หากผู้ใช้เลือกรายการสื่อที่เรียกดูได้ บริการของคุณ
onLoadChildren()
เรียกเมธอดอีกครั้งเพื่อเรียกรายการย่อยของรายการในเมนูที่เลือก - หากผู้ใช้เลือกรายการสื่อที่เล่นได้, Android Automotive OS หรือ Android อัตโนมัติจะเรียกใช้เมธอด Callback ของเซสชันสื่อที่เหมาะสมเพื่อดำเนินการนั้น
- หากแอปของคุณรองรับ ผู้ใช้จะค้นหาเนื้อหาของคุณได้เช่นกัน ด้วยวิธีนี้
Android Automotive OS หรือ Android Auto เรียกใช้บริการของคุณ
onSearch()
สร้างลำดับชั้นเนื้อหา
Android Auto และ Android Automotive OS จะเรียกใช้บริการเบราว์เซอร์สื่อของแอปไปยัง
ดูว่ามีเนื้อหาอะไรบ้าง คุณต้องใช้ 2 วิธีในบัญชี
บริการเบราว์เซอร์สื่อเพื่อรองรับนี้: onGetRoot()
และ
onLoadChildren()
ใช้งาน onGetRoot
onGetRoot()
ของบริการ
จะแสดงข้อมูลเกี่ยวกับโหนดรากของลำดับชั้นเนื้อหาของคุณ
Android Auto และ Android Automotive OS ใช้โหนดรูทนี้เพื่อขอส่วนที่เหลือของ
เนื้อหาของคุณโดยใช้
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()
เมื่อมีการโทรหา onGetRoot()
ของบริการ
แพ็กเกจการโทรจะส่งข้อมูลระบุตัวตนไปยังบริการของคุณ บัญชี
บริการสามารถใช้ข้อมูลนี้เพื่อระบุว่าแพ็กเกจดังกล่าวสามารถเข้าถึง
เนื้อหา เช่น คุณจำกัดการเข้าถึงเนื้อหาของแอปได้เฉพาะรายการ
แพ็กเกจที่ได้รับการอนุมัติโดยการเปรียบเทียบ clientPackageName
กับรายการที่อนุญาตและ
ยืนยันใบรับรองที่ใช้ในการลงนาม APK ของแพ็กเกจ หากระบุแพ็กเกจไม่ได้
ได้รับการยืนยัน ให้กลับไปยัง null
เพื่อปฏิเสธการเข้าถึงเนื้อหาของคุณ
เพื่อให้บริการแอประบบ เช่น Android Auto และ Android Automotive OS
ที่เข้าถึงเนื้อหาของคุณได้ บริการของคุณจะต้องส่งคืนค่า
BrowserRoot
เมื่อแอประบบเหล่านี้เรียกใช้ onGetRoot()
ลายเซ็นของแอประบบ Android Automotive OS อาจแตกต่างกันไปโดยขึ้นอยู่กับ
จากยี่ห้อและรุ่นของรถ คุณจึงต้องอนุญาตให้การเชื่อมต่อ
แอประบบเพื่อรองรับ Android Automotive OS อย่างมีประสิทธิภาพ
ข้อมูลโค้ดต่อไปนี้จะแสดงวิธีที่บริการของคุณสามารถตรวจสอบได้ว่า แพ็กเกจการโทรเป็นแอประบบ
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 Automotive OS
ใช้ onLoadChildren()
หลังจากได้รับออบเจ็กต์โหนดรูทแล้ว Android Auto และ Android Automotive OS
สร้างเมนูระดับบนสุดโดยโทรหา 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<MediaBrowserCompat.MediaItem> = mutableListOf() // Check whether 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 children of that menu in the mediaItems list. } result.sendResult(mediaItems) }
Java
@Override public void onLoadChildren(final String parentMediaId, final Result<List<MediaBrowserCompat.MediaItem>> result) { // Assume for example that the music catalog is already loaded/cached. List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); // Check whether 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 children of that menu in the mediaItems list. } result.sendResult(mediaItems); }
สำหรับตัวอย่างทั้งหมดของวิธีการนี้ โปรดดู
onLoadChildren()
ในแอปตัวอย่างของ Universal Android Music Player บน GitHub
จัดโครงสร้างเมนูรูท
![](https://developer.android.google.cn/static/images/training/cars/browse_home_tabs.png?authuser=19&hl=th)
รูปที่ 2 เนื้อหารูทที่แสดงเป็นแท็บการนําทาง
Android Auto และ Android Automotive OS มีข้อจำกัดเฉพาะเกี่ยวกับ
ของเมนูราก ซึ่งระบบจะส่งเรื่องดังกล่าวให้ MediaBrowserService
ผ่านคำแนะนำระดับรูท ซึ่งสามารถอ่านผ่านอาร์กิวเมนต์ Bundle
ที่ส่งผ่าน
onGetRoot()
การทำตามคำแนะนำเหล่านี้จะช่วยให้ระบบแสดงเนื้อหาระดับรูทได้อย่างเหมาะสม
เป็นแท็บนำทาง หากไม่ปฏิบัติตามคำแนะนำเหล่านี้ เนื้อหารูทบางส่วนอาจ
ถูกทิ้งหรือทำให้ค้นพบได้น้อยลง ระบบจะส่งคำใบ้ไป 2 ฉบับ ได้แก่
- ขีดจํากัดจํานวนย่อยรูท: ในกรณีส่วนใหญ่ จำนวนนี้น่าจะเท่ากับ 4 ซึ่งหมายความว่า ไม่สามารถแสดงเกิน 4 แท็บ
- แฟล็กที่รองรับในรูทย่อย:
คุณจะเห็นค่านี้
MediaItem#FLAG_BROWSABLE
ซึ่งหมายความว่าเฉพาะรายการที่เรียกดูได้ (ไม่ใช่รายการที่เล่นได้) เท่านั้นที่สามารถแสดงเป็นแท็บ
ใช้รหัสต่อไปนี้เพื่ออ่านคำแนะนำรากที่เกี่ยวข้อง
Kotlin
import androidx.media.utils.MediaConstants // Later, in your MediaBrowserServiceCompat. 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 และ Android Automotive OS
เช่น หากปกติแล้วคุณแสดงรายการรูทที่เล่นได้ คุณอาจต้องการซ้อนรายการนั้น
ภายใต้รายการที่เรียกดูได้ระดับรูทแทนเนื่องจากค่าของแฟล็กที่รองรับ
คำใบ้
นอกจากคำแนะนำรูทแล้ว ยังมีหลักเกณฑ์เพิ่มเติมอีก 2-3 ข้อที่ควรทำตาม เพื่อช่วยให้แน่ใจว่าแท็บจะแสดงผลอย่างเหมาะสม
- ใส่ไอคอนโมโนโครมสำหรับแต่ละรายการแท็บ โดยควรเป็นสีขาว
- ใส่ป้ายกำกับที่สั้นแต่มีความหมายสำหรับรายการแท็บแต่ละรายการ ทำให้ป้ายกำกับสั้นเข้าไว้ จะช่วยลดโอกาสที่สตริงจะถูกตัด
แสดงอาร์ตเวิร์กสื่อ
อาร์ตเวิร์กสำหรับรายการสื่อต้องส่งเป็น URI ในเครื่องโดยใช้
ContentResolver.SCHEME_CONTENT
หรือ ContentResolver.SCHEME_ANDROID_RESOURCE
URI ภายในนี้ต้องแปลค่าเป็นบิตแมปหรือเวกเตอร์ที่ถอนออกได้ใน
แหล่งข้อมูลของแอปพลิเคชัน สำหรับ MediaDescriptionCompat
ออบเจ็กต์ที่แสดงรายการใน
ลำดับชั้นเนื้อหา แล้วส่ง URI ผ่าน setIconUri()
สำหรับออบเจ็กต์ MediaMetadataCompat
รายการที่แสดงถึงรายการที่กำลังเล่นอยู่ ให้ส่ง
URI ผ่าน putString()
โดยใช้คีย์ใดก็ได้ต่อไปนี้
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI
MediaMetadataCompat.METADATA_KEY_ART_URI
MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI
ขั้นตอนต่อไปนี้อธิบายวิธีดาวน์โหลดอาร์ตเวิร์กจาก URI ของเว็บและแสดง
ผ่าน URI ในเครื่อง ดูตัวอย่างที่สมบูรณ์มากขึ้นได้ที่
การใช้งาน
ของ openFile()
และวิธีการโดยรอบใน Universal Android Music
แอปตัวอย่างโปรแกรมเล่น
สร้าง URI
content://
ที่สอดคล้องกับ URI ของเว็บ เบราว์เซอร์สื่อ บริการและสื่อจะส่ง URI เนื้อหานี้ไปยัง Android Auto และ Android Automotive OSKotlin
fun Uri.asAlbumArtContentURI(): Uri { return Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CONTENT_PROVIDER_AUTHORITY) .appendPath(this.getPath()) // Make sure you trust the URI .build() }
Java
public static Uri asAlbumArtContentURI(Uri webUri) { return new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CONTENT_PROVIDER_AUTHORITY) .appendPath(webUri.getPath()) // Make sure you trust the URI! .build(); }
ในการใช้งาน
ContentProvider.openFile()
ให้ตรวจสอบว่าไฟล์ สำหรับ URI ที่เกี่ยวข้อง หากไม่มี ให้ดาวน์โหลดและแคชไฟล์ภาพ ข้อมูลโค้ดต่อไปนี้ใช้ GlideKotlin
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? { val context = this.context ?: return null val file = File(context.cacheDir, uri.path) if (!file.exists()) { val remoteUri = Uri.Builder() .scheme("https") .authority("my-image-site") .appendPath(uri.path) .build() val cacheFile = Glide.with(context) .asFile() .load(remoteUri) .submit() .get(DOWNLOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) cacheFile.renameTo(file) file = cacheFile } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY) }
Java
@Nullable @Override public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { Context context = this.getContext(); File file = new File(context.getCacheDir(), uri.getPath()); if (!file.exists()) { Uri remoteUri = new Uri.Builder() .scheme("https") .authority("my-image-site") .appendPath(uri.getPath()) .build(); File cacheFile = Glide.with(context) .asFile() .load(remoteUri) .submit() .get(DOWNLOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS); cacheFile.renameTo(file); file = cacheFile; } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); }
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับผู้ให้บริการเนื้อหา โปรดดูที่การสร้างเนื้อหา ผู้ให้ทุน
ใช้รูปแบบเนื้อหา
หลังจากสร้างลำดับชั้นเนื้อหาโดยใช้รายการที่สามารถเลือกดูได้หรือเล่นได้ สามารถใช้รูปแบบเนื้อหาที่กำหนดว่าสินค้าเหล่านั้นจะแสดงในรถอย่างไร
คุณใช้รูปแบบเนื้อหาต่อไปนี้ได้
- ทีละรายการ
-
รูปแบบเนื้อหานี้ให้ความสำคัญกับชื่อและข้อมูลเมตามากกว่ารูปภาพ
- รายการตารางกริด
-
รูปแบบเนื้อหานี้ให้ความสำคัญกับรูปภาพมากกว่าชื่อและข้อมูลเมตา
ตั้งค่ารูปแบบเนื้อหาเริ่มต้น
คุณสามารถตั้งค่าเริ่มต้นส่วนกลางสำหรับวิธีแสดงรายการสื่อของคุณโดยใส่
ค่าคงที่บางอย่างในแพ็กเกจพิเศษ BrowserRoot
ของบริการ
onGetRoot()
Android Auto และ Android Automotive OS จะอ่านแพ็กเกจนี้และมองหา
ค่าคงที่เหล่านั้นเพื่อระบุรูปแบบที่เหมาะสม
ส่วนเสริมต่อไปนี้สามารถใช้เป็นคีย์ในแพ็กเกจได้
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
: ระบุคำแนะนำในการนำเสนอสำหรับรายการที่เรียกดูได้ทั้งหมดภายในโครงสร้างการเรียกดูDESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
: บ่งชี้ถึงคำแนะนำการนำเสนอสำหรับรายการที่เล่นได้ทั้งหมดภายในโครงสร้างการเรียกดู
คีย์สามารถจับคู่กับค่าคงที่ที่เป็นจำนวนเต็มต่อไปนี้เพื่อกำหนด การนำเสนอรายการเหล่านั้น
DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM
: ระบบจะแสดงรายการที่เกี่ยวข้องเป็นลิสต์รายการDESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM
: ระบบจะแสดงรายการที่เกี่ยวข้องเป็นตารางกริดDESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM
: รายการที่เกี่ยวข้องจะแสดงเป็น "หมวดหมู่" รายการ สิ่งเหล่านี้คือ เหมือนกับรายการทั่วไป เว้นแต่ว่าจะมีการใช้ส่วนต่างกำไร the items' เนื่องจากไอคอนจะดูดีขึ้นเมื่อมีขนาดเล็ก ไอคอน ต้องเป็นเวกเตอร์ที่ถอนออกได้ คำแนะนำนี้ควรได้มีเพียง สำหรับรายการที่เรียกดูได้DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM
: รายการที่เกี่ยวข้องจะแสดงเป็น "หมวดหมู่" รายการในตาราง สิ่งเหล่านี้คือ เหมือนรายการตารางกริดทั่วไป เว้นแต่ว่าจะมีการใช้ขอบ the items' เนื่องจากไอคอนจะดูดีขึ้นเมื่อมีขนาดเล็ก ไอคอน ต้องเป็นเวกเตอร์ที่ถอนออกได้ คำแนะนำนี้ควรได้มีเพียง สำหรับรายการที่เรียกดูได้
ข้อมูลโค้ดต่อไปนี้แสดงวิธีตั้งค่ารูปแบบเนื้อหาเริ่มต้นสำหรับ รายการที่เรียกดูได้ในตารางและรายการที่เล่นได้ลงในรายการ:
Kotlin
import androidx.media.utils.MediaConstants @Nullable override fun onGetRoot( @NonNull clientPackageName: String, clientUid: Int, @Nullable rootHints: Bundle ): BrowserRoot { val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM) return BrowserRoot(ROOT_ID, extras) }
Java
import androidx.media.utils.MediaConstants; @Nullable @Override public BrowserRoot onGetRoot( @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) { Bundle extras = new Bundle(); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM); return new BrowserRoot(ROOT_ID, extras); }
กำหนดรูปแบบเนื้อหาต่อรายการ
Content Style API ช่วยให้คุณสามารถลบล้างรูปแบบเนื้อหาเริ่มต้นได้ รายการสื่อย่อยที่เรียกดูได้ ตลอดจนรายการสื่อทั้งหมด
หากต้องการลบล้างค่าเริ่มต้นสำหรับรายการสื่อย่อยของรายการสื่อที่เรียกดูได้ ให้สร้าง
เพิ่มเติมใน MediaDescription
ของรายการสื่อแล้วเพิ่ม
คำใบ้ที่พูดถึงไปก่อนหน้านี้ DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
จะมีผลกับเด็กที่เล่นของรายการนั้น ขณะที่
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
มีผลกับ
ที่สามารถเลือกดูได้
หากต้องการลบล้างค่าเริ่มต้นสำหรับรายการสื่อบางรายการด้วยตัวเอง ไม่ใช่สำหรับรายการนั้น
เด็ก ให้สร้างกลุ่มรายการเพิ่มเติมไว้ใน MediaDescription
ของรายการสื่อ
และเพิ่มคำแนะนำด้วยคีย์
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM
ใช้ค่าเดียวกันกับที่อธิบายก่อนหน้านี้เพื่อระบุการนำเสนอของรายการนั้นๆ
ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้าง MediaItem
ที่เรียกดูได้ซึ่ง
จะลบล้างรูปแบบเนื้อหาเริ่มต้นสำหรับทั้งตัวเองและองค์ประกอบย่อย มีรูปแบบ
เป็นรายการหมวดหมู่ รายการย่อยที่สามารถเลือกดูได้ และเป็นรายการ และ
แบบตารางในเกมสำหรับเด็ก
Kotlin
import androidx.media.utils.MediaConstants private fun createBrowsableMediaItem( mediaId: String, folderName: String, iconUri: Uri ): MediaBrowser.MediaItem { val mediaDescriptionBuilder = MediaDescription.Builder() mediaDescriptionBuilder.setMediaId(mediaId) mediaDescriptionBuilder.setTitle(folderName) mediaDescriptionBuilder.setIconUri(iconUri) val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM) mediaDescriptionBuilder.setExtras(extras) return MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE) }
Java
import androidx.media.utils.MediaConstants; private MediaBrowser.MediaItem createBrowsableMediaItem( String mediaId, String folderName, Uri iconUri) { MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder(); mediaDescriptionBuilder.setMediaId(mediaId); mediaDescriptionBuilder.setTitle(folderName); mediaDescriptionBuilder.setIconUri(iconUri); Bundle extras = new Bundle(); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM); mediaDescriptionBuilder.setExtras(extras); return new MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE); }
จัดกลุ่มรายการโดยใช้คำแนะนำชื่อ
หากต้องการจัดกลุ่มรายการสื่อที่เกี่ยวข้องไว้ด้วยกัน ให้ใช้คำแนะนำต่อรายการ สื่อทุกรายการ
ในกลุ่มต้องประกาศแพ็กเกจพิเศษใน MediaDescription
ที่
รวมการแมปกับคีย์
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE
และค่าสตริงที่เหมือนกัน แปลสตริงนี้ ซึ่งใช้เป็น
ชื่อกลุ่ม
ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้าง MediaItem
กับกลุ่มย่อย
ส่วนหัวของ"Songs"
:
Kotlin
import androidx.media.utils.MediaConstants private fun createMediaItem( mediaId: String, folderName: String, iconUri: Uri ): MediaBrowser.MediaItem { val mediaDescriptionBuilder = MediaDescription.Builder() mediaDescriptionBuilder.setMediaId(mediaId) mediaDescriptionBuilder.setTitle(folderName) mediaDescriptionBuilder.setIconUri(iconUri) val extras = Bundle() extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs") mediaDescriptionBuilder.setExtras(extras) return MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), /* playable or browsable flag*/) }
Java
import androidx.media.utils.MediaConstants; private MediaBrowser.MediaItem createMediaItem(String mediaId, String folderName, Uri iconUri) { MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder(); mediaDescriptionBuilder.setMediaId(mediaId); mediaDescriptionBuilder.setTitle(folderName); mediaDescriptionBuilder.setIconUri(iconUri); Bundle extras = new Bundle(); extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs"); mediaDescriptionBuilder.setExtras(extras); return new MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), /* playable or browsable flag*/); }
แอปของคุณต้องส่งผ่านรายการสื่อทั้งหมดที่คุณต้องการจัดกลุ่มเข้าด้วยกันเป็น บล็อกที่ต่อเนื่องกัน ตัวอย่างเช่น สมมติว่าคุณต้องการแสดง 2 กลุ่ม ของรายการสื่อ, "เพลง" และ "อัลบั้ม" ตามลำดับดังกล่าว และแอปของคุณ รายการสื่อ 5 รายการตามลำดับต่อไปนี้
- รายการสื่อ A ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- รายการสื่อ B ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
- รายการสื่อ C ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- รายการสื่อ D ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- รายการสื่อ E ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
เนื่องจากรายการสื่อสำหรับ "เพลง" กลุ่มและ "อัลบั้ม" ไม่เก็บกลุ่มไว้ บล็อกติดกัน, Android Auto และ Android Automotive OS ระบบจะตีความข้อมูลนี้เป็น 4 กลุ่มต่อไปนี้
- กลุ่ม 1 ชื่อว่า "เพลง" ที่มีรายการสื่อ A
- กลุ่ม 2 ชื่อ "อัลบั้ม" ที่มีรายการสื่อ B
- กลุ่ม 3 ชื่อว่า "เพลง" ที่มีรายการสื่อ C และ D
- กลุ่ม 4 ชื่อ "อัลบั้ม" ที่มีรายการสื่อ E
หากต้องการแสดงรายการเหล่านี้ใน 2 กลุ่ม แอปของคุณจะต้องส่งรายการสื่อใน ต่อไปนี้แทน:
- รายการสื่อ A ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- รายการสื่อ C ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- รายการสื่อ D ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- รายการสื่อ B ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
- รายการสื่อ E ที่มี
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
แสดงตัวบ่งชี้ข้อมูลเมตาเพิ่มเติม
คุณสามารถระบุตัวบ่งชี้ข้อมูลเมตาเพิ่มเติมเพื่อแสดงข้อมูลโดยย่อ สำหรับเนื้อหาในโครงสร้างเบราว์เซอร์สื่อและระหว่างการเล่น ภายใน แผนผังเรียกดู, Android Auto และ Android Automotive OS อ่านข้อมูลเพิ่มเติมที่เกี่ยวข้อง โดยใช้รายการหนึ่ง และมองหาค่าคงที่เพื่อระบุว่าควรใช้ตัวบ่งชี้ใด จอแสดงผล ระหว่างการเล่นสื่อ Android Auto และ Android Automotive OS จะอ่าน สำหรับเซสชันสื่อและมองหาค่าคงที่บางอย่างเพื่อระบุ สัญญาณที่จะแสดง
![](https://developer.android.google.cn/static/images/training/cars/metadata_indicators.png?authuser=19&hl=th)
รูปที่ 3 มุมมองการเล่นที่มีข้อมูลเมตาที่ระบุเพลง และศิลปิน รวมถึงไอคอนที่ระบุเนื้อหาที่อาจไม่เหมาะสม
![](https://developer.android.google.cn/static/images/training/cars/progress_indicators.png?authuser=19&hl=th)
รูปที่ 4 มุมมองแบบเรียกดูที่มีจุดสำหรับเนื้อหาที่ยังไม่ได้เล่นเปิดอยู่ รายการแรกและแถบความคืบหน้าสำหรับเนื้อหาที่มีการเล่นบางส่วนบน รายการที่ 2
ค่าคงที่ต่อไปนี้ใช้ได้ในทั้งส่วนเพิ่มเติมของคำอธิบาย MediaItem
และ
เพิ่มเติม MediaMetadata
รายการ:
EXTRA_DOWNLOAD_STATUS
: ระบุสถานะการดาวน์โหลดของรายการ ใช้ค่าคงที่นี้เป็นค่า คีย์; ค่าคงที่ยาวต่อไปนี้คือค่าที่เป็นไปได้STATUS_DOWNLOADED
: ดาวน์โหลดรายการเรียบร้อยแล้วSTATUS_DOWNLOADING
: กำลังดาวน์โหลดรายการSTATUS_NOT_DOWNLOADED
: ไม่ได้ดาวน์โหลดรายการ
METADATA_KEY_IS_EXPLICIT
: ระบุว่ารายการนั้นมีเนื้อหาที่อาจไม่เหมาะสมหรือไม่ ในการระบุว่ารายการ ให้ใช้ค่าคงที่นี้เป็นคีย์และMETADATA_VALUE_ATTRIBUTE_PRESENT
เป็นค่า
ค่าคงที่ต่อไปนี้ใช้เฉพาะในคำอธิบายเพิ่มเติมของ MediaItem
ได้
DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
: ระบุสถานะความสำเร็จของคอนเทนต์แบบยาว เช่น ตอนของพอดแคสต์หรือ หนังสือเสียง ใช้ค่าคงที่นี้เป็นกุญแจสำคัญ จำนวนเต็มต่อไปนี้ คงตัวเป็นค่าที่เป็นไปได้:DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED
: ไม่ได้เล่นรายการเลยDESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
: มีการเล่นรายการบางส่วน และตำแหน่งปัจจุบันอยู่ที่ตำแหน่งใดตำแหน่งหนึ่ง ในช่วงกลางDESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED
: รายการนั้นเสร็จสมบูรณ์แล้ว
DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
: บอกถึงจำนวนความคืบหน้าในการเล่นเนื้อหาแบบยาวเป็นเลขทศนิยมอย่างละเอียด ตั้งแต่ 0.0 ถึง 1.0 ข้อมูลเพิ่มเติมนี้จะให้ข้อมูลเพิ่มเติมเกี่ยวกับPARTIALLY_PLAYING
ทำให้ Android Auto หรือ Android Automotive OS จะแสดงตัวบ่งชี้ความคืบหน้าที่มีความหมายมากขึ้น เช่น แถบความคืบหน้า หากคุณใช้ส่วนเสริมนี้ โปรดดูส่วนเกี่ยวกับ การอัปเดตแถบความคืบหน้าในมุมมองแบบเรียกดูขณะที่เนื้อหากำลังเล่น ในคู่มือนี้เพื่อเรียนรู้วิธีทำให้ตัวบ่งชี้นี้อัปเดตอยู่เสมอหลังจาก การแสดงผลครั้งแรก
เพื่อแสดงสัญญาณบอกสถานะที่ปรากฏเมื่อผู้ใช้เรียกดูสื่อ
ต้นไม้ ให้สร้างชุดข้อมูลพิเศษที่รวมค่าคงที่เหล่านี้อย่างน้อย 1 ค่าและ
ส่ง Bundle นั้นไปยังเมธอด MediaDescription.Builder.setExtras()
ข้อมูลโค้ดต่อไปนี้แสดงวิธีแสดงตัวบ่งชี้สำหรับสื่อที่อาจไม่เหมาะสม รายการที่เสร็จสมบูรณ์ 70%
Kotlin
import androidx.media.utils.MediaConstants val extras = Bundle() extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED) extras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7) val description = MediaDescriptionCompat.Builder() .setMediaId(/*...*/) .setTitle(resources.getString(/*...*/)) .setExtras(extras) .build() return MediaBrowserCompat.MediaItem(description, /* flags */)
Java
import androidx.media.utils.MediaConstants; Bundle extras = new Bundle(); extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED); extras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId(/*...*/) .setTitle(resources.getString(/*...*/)) .setExtras(extras) .build(); return new MediaBrowserCompat.MediaItem(description, /* flags */);
หากต้องการแสดงสัญญาณบอกสถานะสำหรับรายการสื่อที่กำลังเล่นอยู่ คุณสามารถดำเนินการได้ดังนี้
ประกาศค่า Long
สำหรับ METADATA_KEY_IS_EXPLICIT
หรือ EXTRA_DOWNLOAD_STATUS
ใน MediaMetadataCompat
ของ mediaSession
ไม่สามารถแสดง
DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
หรือ
สัญญาณบอกสถานะ DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
ในมุมมองการเล่น
ข้อมูลโค้ดต่อไปนี้แสดงวิธีระบุว่าเพลงปัจจุบันใน มุมมองการเล่นอาจไม่เหมาะสมและจะดาวน์โหลด
Kotlin
import androidx.media.utils.MediaConstants mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name") .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name") .putString( MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUri.toString()) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) .putLong( MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS, MediaDescriptionCompat.STATUS_DOWNLOADED) .build())
Java
import androidx.media.utils.MediaConstants; mediaSession.setMetadata( new MediaMetadataCompat.Builder() .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name") .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name") .putString( MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUri.toString()) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) .putLong( MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS, MediaDescriptionCompat.STATUS_DOWNLOADED) .build());
อัปเดตแถบความคืบหน้าในมุมมองการเรียกดูขณะที่เนื้อหากำลังเล่น
ดังที่กล่าวไว้ก่อนหน้านี้ คุณสามารถใช้
DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
เพิ่มเติมเพื่อแสดงแถบความคืบหน้าสำหรับเนื้อหาที่เล่นบางส่วนใน
มุมมองแบบเรียกดู อย่างไรก็ตาม หากผู้ใช้เล่นเนื้อหาที่เล่นบางส่วนต่อ
จาก Android Auto หรือ Android Automotive OS ตัวบ่งชี้นั้นจะ
ไม่แม่นยำเมื่อเวลาผ่านไป
สำหรับ Android Auto และ Android Automotive OS
เพื่อให้แถบความคืบหน้าอัปเดตอยู่เสมอ คุณสามารถให้ข้อมูลเพิ่มเติมใน
MediaMetadataCompat
และ PlaybackStateCompat
เพื่อลิงก์เนื้อหาต่อเนื่อง
รายการสื่อในมุมมองการเรียกดู ต้องเป็นไปตามข้อกำหนดต่อไปนี้สำหรับ
รายการสื่อให้มีแถบความคืบหน้าการอัปเดตโดยอัตโนมัติ:
- เมื่อสร้างแล้ว
MediaItem
ต้องส่งDESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
ในส่วนขยายที่มีค่าระหว่าง 0.0 ถึง 1.0 MediaMetadataCompat
ต้องส่งMETADATA_KEY_MEDIA_ID
ที่มีค่าสตริงเท่ากับ รหัสสื่อ ส่งไปยังMediaItem
PlaybackStateCompat
ต้องมีส่วนเสริมพร้อมกับคีย์PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID
ซึ่งจับคู่กับค่าสตริงที่เท่ากับ รหัสสื่อ ส่งไปยังMediaItem
ข้อมูลโค้ดต่อไปนี้แสดงวิธีระบุว่ารายการที่กำลังเล่น ถูกเชื่อมโยงกับรายการในมุมมองการเรียกดู:
Kotlin
import androidx.media.utils.MediaConstants // When the MediaItem is constructed to show in the browse view. // Suppose the item was 25% complete when the user launched the browse view. val mediaItemExtras = Bundle() mediaItemExtras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25) val description = MediaDescriptionCompat.Builder() .setMediaId("my-media-id") .setExtras(mediaItemExtras) // ...and any other setters. .build() return MediaBrowserCompat.MediaItem(description, /* flags */) // Elsewhere, when the user has selected MediaItem for playback. mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id") // ...and any other setters. .build()) val playbackStateExtras = Bundle() playbackStateExtras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id") mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setExtras(playbackStateExtras) // ...and any other setters. .build())
Java
import androidx.media.utils.MediaConstants; // When the MediaItem is constructed to show in the browse view. // Suppose the item was 25% complete when the user launched the browse view. Bundle mediaItemExtras = new Bundle(); mediaItemExtras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId("my-media-id") .setExtras(mediaItemExtras) // ...and any other setters. .build(); return MediaBrowserCompat.MediaItem(description, /* flags */); // Elsewhere, when the user has selected MediaItem for playback. mediaSession.setMetadata( new MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id") // ...and any other setters. .build()); Bundle playbackStateExtras = new Bundle(); playbackStateExtras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id"); mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setExtras(playbackStateExtras) // ...and any other setters. .build());
แสดงผลการค้นหาที่เรียกดูได้
![](https://developer.android.google.cn/static/images/training/cars/search_results.png?authuser=19&hl=th)
รูปที่ 5 มุมมองการเล่นที่มีตัวเลือก "ผลการค้นหา" สำหรับ ดูรายการสื่อที่เกี่ยวข้องกับการค้นหาด้วยเสียงของผู้ใช้
แอปสามารถให้ผลการค้นหาตามบริบทที่แสดงต่อผู้ใช้เมื่อ ผู้ใช้เริ่มใช้คำค้นหา รายการ Android Auto และ Android Automotive OS ผลลัพธ์เหล่านี้ผ่านอินเทอร์เฟซคำค้นหาหรือผ่านจำนวนเงินที่เปลี่ยนได้ สำหรับการค้นหาที่เกิดขึ้นก่อนหน้านี้ในเซสชัน ดูข้อมูลเพิ่มเติมได้ที่ ส่วนรองรับการสั่งงานด้วยเสียงในคู่มือนี้
หากต้องการแสดงผลการค้นหาที่เรียกดูได้ ให้ใส่แป้นคงที่
BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED
ในแพ็กเกจเพิ่มเติมของ onGetRoot()
ของบริการ
การแมปกับ true
แบบบูลีน
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเปิดใช้การสนับสนุนใน onGetRoot()
วิธีการ:
Kotlin
import androidx.media.utils.MediaConstants @Nullable fun onGetRoot( @NonNull clientPackageName: String, clientUid: Int, @Nullable rootHints: Bundle ): BrowserRoot { val extras = Bundle() extras.putBoolean( MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true) return BrowserRoot(ROOT_ID, extras) }
Java
import androidx.media.utils.MediaConstants; @Nullable @Override public BrowserRoot onGetRoot( @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) { Bundle extras = new Bundle(); extras.putBoolean( MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true); return new BrowserRoot(ROOT_ID, extras); }
หากต้องการเริ่มแสดงผลการค้นหา ให้ลบล้าง onSearch()
ในบริการเบราว์เซอร์สื่อของคุณ Android Auto และ Android Automotive OS
ส่งต่อข้อความค้นหาของผู้ใช้ไปยังวิธีการนี้เมื่อใดก็ตามที่ผู้ใช้ทำการค้นหา
อินเทอร์เฟซคำค้นหาหรือ "ผลการค้นหา"
คุณสามารถจัดระเบียบการค้นหา
ผลลัพธ์จากเมธอด onSearch()
ของบริการที่ใช้ title items
เพื่อให้ผู้ใช้เลือกดูได้ง่ายขึ้น ตัวอย่างเช่น หากแอปเปิดเพลง คุณอาจ
จัดระเบียบผลการค้นหาตามอัลบั้ม ศิลปิน และเพลง
ข้อมูลโค้ดต่อไปนี้แสดงการใช้งาน onSearch()
แบบง่ายๆ
วิธีการ:
Kotlin
fun onSearch(query: String, extras: Bundle) { // Detach from results to unblock the caller (if a search is expensive). result.detach() object:AsyncTask() { internal var searchResponse:ArrayList internal var succeeded = false protected fun doInBackground(vararg params:Void):Void { searchResponse = ArrayList() if (doSearch(query, extras, searchResponse)) { succeeded = true } return null } protected fun onPostExecute(param:Void) { if (succeeded) { // Sending an empty List informs the caller that there were no results. result.sendResult(searchResponse) } else { // This invokes onError() on the search callback. result.sendResult(null) } return null } }.execute() } // Populates resultsToFill with search results. Returns true on success or false on error. private fun doSearch( query: String, extras: Bundle, resultsToFill: ArrayList ): Boolean { // Implement this method. }
Java
@Override public void onSearch(final String query, final Bundle extras, Result<List<MediaItem>> result) { // Detach from results to unblock the caller (if a search is expensive). result.detach(); new AsyncTask<Void, Void, Void>() { List<MediaItem> searchResponse; boolean succeeded = false; @Override protected Void doInBackground(Void... params) { searchResponse = new ArrayList<MediaItem>(); if (doSearch(query, extras, searchResponse)) { succeeded = true; } return null; } @Override protected void onPostExecute(Void param) { if (succeeded) { // Sending an empty List informs the caller that there were no results. result.sendResult(searchResponse); } else { // This invokes onError() on the search callback. result.sendResult(null); } } }.execute() } /** Populates resultsToFill with search results. Returns true on success or false on error. */ private boolean doSearch(String query, Bundle extras, ArrayList<MediaItem> resultsToFill) { // Implement this method. }
การดำเนินการเรียกดูที่กำหนดเอง
![การดำเนินการเรียกดูที่กำหนดเอง 1 รายการ](https://developer.android.google.cn/static/images/training/cars/custom_browse_action_single.png?authuser=19&hl=th)
รูปที่ 6 การเรียกดูที่กำหนดเองรายการเดียว
การดำเนินการเรียกดูแบบกำหนดเองช่วยให้คุณสามารถเพิ่มไอคอนและป้ายกำกับที่กำหนดเองลงใน
MediaItem
ในแอปสื่อของรถยนต์ และจัดการการโต้ตอบของผู้ใช้กับ
การกระทำเหล่านี้ ซึ่งจะช่วยให้คุณขยายฟังก์ชันการทำงานของแอปสื่อใน
หลายวิธี เช่น เพิ่ม "ดาวน์โหลด" "เพิ่มลงในคิว" "เล่นวิทยุ"
"รายการโปรด" หรือ "นำออก" การดำเนินการ
![เมนูรายการเพิ่มเติมของการดำเนินการเรียกดูที่กำหนดเอง](https://developer.android.google.cn/static/images/training/cars/custom_browse_action_overflow.png?authuser=19&hl=th)
รูปที่ 7 การดำเนินการเพิ่มเติมของการเรียกดูที่กำหนดเอง
หากมีการดำเนินการที่กำหนดเองมากกว่าที่ OEM อนุญาตให้แสดงได้ เมนูรายการเพิ่มเติมจะแสดงให้ผู้ใช้เห็น
วิธีการทำงาน
การทำงานเรียกดูที่กำหนดเองแต่ละรายการจะกำหนดด้วย:
- รหัสการดำเนินการ (ตัวระบุสตริงที่ไม่ซ้ำกัน)
- ป้ายกำกับการดำเนินการ (ข้อความที่แสดงต่อผู้ใช้)
- URI ไอคอนการทำงาน (เวกเตอร์ที่ถอนออกได้ที่สามารถปรับสีได้)
คุณกำหนดรายการการดำเนินการเรียกดูที่กำหนดเองทั่วโลกโดยเป็นส่วนหนึ่งของ
BrowseRoot
จากนั้นคุณสามารถแนบชุดย่อยของการดำเนินการเหล่านี้กับ
MediaItem.
เมื่อผู้ใช้โต้ตอบกับการดำเนินการเรียกดูที่กำหนดเอง แอปจะได้รับการติดต่อกลับ
ใน onCustomAction()
จากนั้นคุณสามารถจัดการการทำงานและอัปเดตรายการของ
การดำเนินการสำหรับ MediaItem
หากจำเป็น การดำเนินการนี้มีประโยชน์สำหรับการดำเนินการแบบเก็บสถานะ
เช่น "รายการโปรด" และ "ดาวน์โหลด" สำหรับการดำเนินการที่ไม่ต้องอัปเดต เช่น "เปิด
Radio" คุณไม่จำเป็นต้องอัปเดตรายการการดำเนินการ
![การดำเนินการเรียกดูที่กำหนดเองในรูทของโหนดการเรียกดู](https://developer.android.google.cn/static/images/training/cars/custom_browse_action_toolbar.png?authuser=19&hl=th)
รูปที่ 8 แถบเครื่องมือการดำเนินการเรียกดูที่กำหนดเอง
นอกจากนี้ คุณยังแนบการดำเนินการเรียกดูที่กำหนดเองกับรูทของโหนดการเรียกดูได้ด้วย การดำเนินการเหล่านี้ จะแสดงในแถบเครื่องมือสำรองใต้แถบเครื่องมือหลัก
วิธีใช้งานการดำเนินการเรียกดูที่กำหนดเอง
ขั้นตอนในการเพิ่มการดำเนินการเรียกดูที่กำหนดเองลงในโปรเจ็กต์มีดังนี้
- ลบล้าง 2 วิธีใน
MediaBrowserServiceCompat
การใช้งาน: - วิธีแยกวิเคราะห์ขีดจำกัดการดำเนินการระหว่างรันไทม์
- ใน
onGetRoot()
รับจำนวนการดำเนินการสูงสุดที่อนุญาตสำหรับแต่ละรายการMediaItem
โดยใช้คีย์BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT
ในBundle
rootHints
ขีดจำกัดเป็น 0 หมายความว่าฟีเจอร์นั้น ไม่รองรับระบบดังกล่าว
- ใน
- สร้างรายการการดำเนินการเรียกดูที่กำหนดเองโดยรวมดังนี้
- สำหรับการดำเนินการแต่ละรายการ ให้สร้างออบเจ็กต์
Bundle
ด้วยคีย์ต่อไปนี้ *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
: รหัสการดำเนินการ *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
: ป้ายกำกับการดำเนินการ *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
: URI ไอคอนการทำงาน * เพิ่มออบเจ็กต์Bundle
การดำเนินการทั้งหมดลงในรายการ
- สำหรับการดำเนินการแต่ละรายการ ให้สร้างออบเจ็กต์
- เพิ่มรายการส่วนกลางลงใน
BrowseRoot
:- ใน
BrowseRoot
เพิ่มเติมBundle
ให้เพิ่มรายการการดำเนินการเป็นParcelable
Arraylist
โดยใช้คีย์BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST
- ใน
- เพิ่มการดำเนินการลงในออบเจ็กต์
MediaItem
ดังนี้- คุณเพิ่มการดำเนินการให้กับออบเจ็กต์
MediaItem
แต่ละรายการได้โดยรวม รายการรหัสการดำเนินการในส่วนเพิ่มเติมของMediaDescriptionCompat
ที่ใช้คีย์DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST
รายการนี้ต้องเป็นชุดย่อยของการดำเนินการทั้งหมดที่คุณกำหนดในBrowseRoot
- คุณเพิ่มการดำเนินการให้กับออบเจ็กต์
- จัดการการดำเนินการและแสดงผลความคืบหน้าหรือผลลัพธ์
- ใน
onCustomAction
ให้จัดการการดำเนินการตามรหัสการดำเนินการ ข้อมูลอื่นๆ ที่คุณต้องการ คุณสามารถรับรหัสของMediaItem
ที่ ทริกเกอร์การดำเนินการจากส่วนเสริมโดยใช้คีย์EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID
. - คุณสามารถอัปเดตรายการการดำเนินการสำหรับ
MediaItem
โดยใส่ แป้นEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
กำลังดำเนินการหรือกลุ่มผลลัพธ์
- ใน
การเปลี่ยนแปลงที่คุณทำได้ในBrowserServiceCompat
เพื่อเริ่มต้นใช้งานมีดังนี้
ด้วยการดำเนินการเรียกดูที่กำหนดเอง
ลบล้าง BrowserServiceCompat
คุณต้องลบล้างเมธอดต่อไปนี้ใน MediaBrowserServiceCompat
public void onLoadItem(String itemId, @NonNull Result<MediaBrowserCompat.MediaItem> result)
public void onCustomAction(@NonNull String action, Bundle extras, @NonNull Result<Bundle> result)
การแยกวิเคราะห์ขีดจำกัด
คุณควรตรวจสอบเพื่อดูจำนวนการดำเนินการเรียกดูที่กำหนดเองที่รองรับ
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT, 0) }
สร้างการดำเนินการเรียกดูที่กำหนดเอง
การดำเนินการแต่ละรายการจะต้องรวมอยู่ใน Bundle
แยกกัน
- รหัสการทำงาน
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, "<ACTION_ID>")
- ป้ายกำกับการทำงาน
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, "<ACTION_LABEL>")
- URI ไอคอนการทำงาน
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, "<ACTION_ICON_URI>")
เพิ่มการดำเนินการเรียกดูที่กำหนดเองลงใน Parceable
ArrayList
เพิ่มออบเจ็กต์การดำเนินการเรียกดูที่กำหนดเอง Bundle
ทั้งหมดลงใน ArrayList
private ArrayList<Bundle> createCustomActionsList( CustomBrowseAction browseActions) { ArrayList<Bundle> browseActionsBundle = new ArrayList<>(); for (CustomBrowseAction browseAction : browseActions) { Bundle action = new Bundle(); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, browseAction.mId); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, getString(browseAction.mLabelResId)); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, browseAction.mIcon); browseActionsBundle.add(action); } return browseActionsBundle; }
เพิ่มรายการการดำเนินการเรียกดูที่กำหนดเองลงในรูทการเรียกดู
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { Bundle browserRootExtras = new Bundle(); browserRootExtras.putParcelableArrayList( BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST, createCustomActionsList())); mRoot = new BrowserRoot(ROOT_ID, browserRootExtras); return mRoot; }
เพิ่มการดำเนินการไปยัง MediaItem
MediaDescriptionCompat buildDescription (long id, String title, String subtitle, String description, Uri iconUri, Uri mediaUri, ArrayList<String> browseActionIds) { MediaDescriptionCompat.Builder bob = new MediaDescriptionCompat.Builder(); bob.setMediaId(id); bob.setTitle(title); bob.setSubtitle(subtitle); bob.setDescription(description); bob.setIconUri(iconUri); bob.setMediaUri(mediaUri); Bundle extras = new Bundle(); extras.putStringArrayList( DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST, browseActionIds); bob.setExtras(extras); return bob.build(); } MediaItem mediaItem = new MediaItem(buildDescription(...), flags);
สร้างผลลัพธ์ onCustomAction
รายการ
- แยกวิเคราะห์รหัสสื่อจาก
Bundle extras
:@Override public void onCustomAction( @NonNull String action, Bundle extras, @NonNull Result<Bundle> result){ String mediaId = extras.getString(MediaConstans.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID); }
- สำหรับผลลัพธ์แบบอะซิงโครนัส ให้ปลดผลลัพธ์ออก
result.detach()
- กลุ่มผลการค้นหา
- ข้อความถึงผู้ใช้
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE, mContext.getString(stringRes))
- อัปเดตรายการ(ใช้เพื่ออัปเดตการดำเนินการในรายการ)
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
- เปิดมุมมองการเล่น
//Shows user the PBV without changing the playback state mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
- อัปเดตการเรียกดูโหนด
//Change current browse node to mediaId mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
- ข้อความถึงผู้ใช้
- หากเกิดข้อผิดพลาด โปรดโทรติดต่อ
result.sendError(resultBundle).
- หากมีการอัปเดตความคืบหน้า โปรดโทรติดต่อ
result.sendProgressUpdate(resultBundle)
- ให้เสร็จสิ้นโดยการโทรหา
result.sendResult(resultBundle)
อัปเดตสถานะการดำเนินการ
โดยใช้เมธอด result.sendProgressUpdate(resultBundle)
กับเมธอด
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
คุณสามารถอัปเดต MediaItem
เพื่อแสดงสถานะใหม่ของการดำเนินการได้ ช่วงเวลานี้
ช่วยให้คุณแสดงความคิดเห็นแบบเรียลไทม์เกี่ยวกับความคืบหน้าและ
ของการกระทำ
ตัวอย่าง: การดาวน์โหลด
ตัวอย่างวิธีใช้ฟีเจอร์นี้เพื่อใช้การดาวน์โหลด ซึ่งมี 3 สถานะ ได้แก่
- ดาวน์โหลด: นี่คือสถานะเริ่มต้นของการดำเนินการ เมื่อผู้ใช้เลือก
การดำเนินการนี้
คุณสามารถเปลี่ยนการตั้งค่าเป็น "กำลังดาวน์โหลด" และโทร
sendProgressUpdate
เพื่ออัปเดต UI - กำลังดาวน์โหลด: สถานะนี้บ่งบอกว่ากำลังดาวน์โหลดอยู่ คุณสามารถ ใช้สถานะนี้เพื่อแสดงแถบความคืบหน้าหรือสัญญาณบอกสถานะอื่นแก่ผู้ใช้
- ดาวน์โหลดแล้ว: สถานะนี้บ่งบอกว่าการดาวน์โหลดเสร็จสมบูรณ์ เมื่อ
การดาวน์โหลดเสร็จสิ้นแล้ว คุณสามารถสลับปุ่ม "ดาวน์โหลด" พร้อม "ดาวน์โหลดแล้ว" และโทร
sendResult
ที่มีEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
เพื่อระบุว่าควรรีเฟรชรายการ นอกจากนี้ คุณยังสามารถใช้ เวลาEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE
เพื่อแสดงข้อความดำเนินการสำเร็จแก่ผู้ใช้
วิธีนี้ช่วยให้คุณแสดงความคิดเห็นที่ชัดเจนแก่ผู้ใช้เกี่ยวกับการดาวน์โหลดได้ และสถานะปัจจุบันของกระบวนการ คุณเพิ่มรายละเอียดได้มากยิ่งขึ้นด้วยไอคอนที่จะแสดง สถานะการดาวน์โหลด 25%, 50%, 75%
ตัวอย่าง: การดำเนินการโปรด
อีกตัวอย่างหนึ่งคือการดำเนินการโปรดที่มี 2 สถานะ ดังนี้
- รายการโปรด: การดำเนินการนี้จะแสดงสำหรับรายการที่ไม่ได้อยู่ใน
รายการโปรดของผู้ใช้ เมื่อผู้ใช้เลือกการดำเนินการนี้ คุณจะสลับการกระทำได้
กับ "รายการโปรด" และโทรหา
sendResult
ด้วยEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
เพื่ออัปเดต UI - รายการโปรด: การดําเนินการนี้จะแสดงสำหรับรายการที่อยู่ใน
รายการโปรด เมื่อผู้ใช้เลือกการดำเนินการนี้ คุณสามารถสลับกับ
"รายการโปรด" และโทรหา
sendResult
ด้วยEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
เพื่ออัปเดต UI
แนวทางนี้จะให้วิธีการที่ชัดเจนและสอดคล้องกันสำหรับผู้ใช้ในการจัดการ รายการโปรด
ตัวอย่างเหล่านี้แสดงความยืดหยุ่นของการดำเนินการเรียกดูที่กำหนดเอง และวิธีที่คุณสามารถ ให้ใช้ฟังก์ชันต่างๆ เพื่อปรับใช้ฟังก์ชันต่างๆ พร้อมการแสดงความคิดเห็นแบบเรียลไทม์สำหรับ ปรับปรุงประสบการณ์ของผู้ใช้ในแอปสื่อของรถยนต์
หากต้องการดูตัวอย่างที่สมบูรณ์ของฟีเจอร์นี้ โปรดดู
TestMediaApp
โปรเจ็กต์ของคุณ
เปิดใช้ตัวควบคุมการเล่น
Android Auto และ Android Automotive OS ส่งคําสั่งการควบคุมการเล่นผ่าน
MediaSessionCompat
ของบริการ
คุณต้องลงทะเบียนเซสชันและใช้วิธีการเรียกกลับที่เกี่ยวข้อง
ลงทะเบียนเซสชันสื่อ
ใน onCreate()
ของบริการเบราว์เซอร์สื่อของคุณ
ให้สร้าง MediaSessionCompat
จากนั้นลงทะเบียนเซสชันสื่อโดยโทรไปที่ setSessionToken()
ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้างและลงทะเบียนเซสชันสื่อ
Kotlin
override fun onCreate() { super.onCreate() ... // Start a new MediaSession. val session = MediaSessionCompat(this, "session tag").apply { // Set a callback object that implements MediaSession.Callback // to handle play control requests. setCallback(MyMediaSessionCallback()) } sessionToken = session.sessionToken ... }
Java
public void onCreate() { super.onCreate(); ... // Start a new MediaSession. MediaSessionCompat session = new MediaSessionCompat(this, "session tag"); setSessionToken(session.getSessionToken()); // Set a callback object that implements MediaSession.Callback // to handle play control requests. session.setCallback(new MyMediaSessionCallback()); ... }
เมื่อสร้างออบเจ็กต์เซสชันสื่อ คุณจะตั้งค่าออบเจ็กต์ Callback ที่ใช้
ในการจัดการคำขอควบคุมการเล่น คุณสร้างออบเจ็กต์ Callback นี้ได้โดย
การติดตั้งใช้งานMediaSessionCompat.Callback
สำหรับแอปของคุณ ส่วนถัดไปจะกล่าวถึงวิธีการนำออบเจ็กต์นี้ไปใช้
ใช้คำสั่งการเล่น
เมื่อผู้ใช้ขอให้เล่นรายการสื่อจากแอป Android Automotive
ระบบปฏิบัติการและ Android Auto ใช้MediaSessionCompat.Callback
จากแอปพลิเคชัน MediaSessionCompat
ที่ได้รับจากบริการเบราว์เซอร์สื่อของแอป เมื่อผู้ใช้
ต้องการควบคุมการเล่นเนื้อหา เช่น การหยุดเล่นชั่วคราวหรือการข้ามไปยัง
แทร็กถัดไป Android Auto และ Android Automotive OS เรียกใช้หนึ่งใน Callback
ของออบเจ็กต์
แอปต้องขยาย MediaSessionCompat.Callback
สมมติจึงจะจัดการการเล่นเนื้อหาได้
และนำวิธีการที่แอปของคุณรองรับไปใช้
ใช้วิธีการเรียกกลับทั้งหมดต่อไปนี้ตามความเหมาะสม ประเภทของเนื้อหาที่แอปของคุณนำเสนอ ได้แก่
onPrepare()
- เรียกใช้เมื่อเปลี่ยนแหล่งที่มาของสื่อ Android Automotive OS ยังเรียกใช้ วิธีนี้ทันทีหลังจากเปิดเครื่อง แอปสื่อต้องใช้ฟีเจอร์นี้
onPlay()
- เรียกใช้หากผู้ใช้เลือกเล่นโดยไม่เลือกรายการที่เฉพาะเจาะจง บัญชี
แอปต้องเล่นเนื้อหาเริ่มต้น หรือหากหยุดเล่นชั่วคราวโดยมี
onPause()
กลับมาเล่นต่อหมายเหตุ: แอปไม่ควรเริ่มเปิดเพลงโดยอัตโนมัติ เมื่อ Android Automotive OS หรือ Android Auto เชื่อมต่อกับเบราว์เซอร์สื่อ service. สำหรับข้อมูลเพิ่มเติม โปรดดูหัวข้อเกี่ยวกับ การตั้งค่าสถานะการเล่นเริ่มต้น
onPlayFromMediaId()
- เรียกใช้เมื่อผู้ใช้เลือกเล่นรายการที่เจาะจง ผ่านวิธีแล้ว รหัสที่บริการเบราว์เซอร์สื่อของคุณกำหนด ไปยังรายการสื่อในลำดับชั้นเนื้อหา
onPlayFromSearch()
- เรียกใช้เมื่อผู้ใช้เลือกที่จะเล่นจากคำค้นหา แอปจะต้อง เลือกตัวเลือกที่เหมาะสมตามสตริงการค้นหาที่ส่งเข้ามา
onPause()
- เรียกใช้เมื่อผู้ใช้เลือกหยุดเล่นชั่วคราว
onSkipToNext()
- มีการเรียกใช้เมื่อผู้ใช้เลือกที่จะข้ามไปยังรายการถัดไป
onSkipToPrevious()
- มีการเรียกใช้เมื่อผู้ใช้เลือกที่จะข้ามไปยังรายการก่อนหน้า
onStop()
- เรียกใช้เมื่อผู้ใช้เลือกที่จะหยุดเล่น
ลบล้างวิธีการเหล่านี้ในแอปเพื่อให้มีฟังก์ชันการทำงานที่ต้องการ คุณ
คุณไม่จำเป็นต้องใช้วิธีใดหากแอปของคุณไม่รองรับฟังก์ชันการทำงานของวิธีการดังกล่าว สำหรับ
ตัวอย่างเช่น หากแอปเล่นสตรีมแบบสด เช่น การออกอากาศการแข่งขันกีฬา คุณ
คุณไม่จำเป็นต้องใช้เมธอด onSkipToNext()
คุณสามารถใช้ค่าเริ่มต้น
การใช้ onSkipToNext()
แทน
แอปของคุณไม่ต้องใช้ตรรกะพิเศษเพื่อเล่นเนื้อหาผ่านรถยนต์ ลำโพง เมื่อแอปได้รับคำขอให้เล่นเนื้อหา ก็จะเล่นเสียงได้ ด้วยวิธีเดียวกับที่เล่นเนื้อหาผ่าน ลำโพงโทรศัพท์หรือหูฟังของผู้ใช้ Android Auto และ Android Automotive OS ส่งเนื้อหาเสียงไปยังระบบของรถยนต์โดยอัตโนมัติเพื่อเล่นผ่าน ลำโพงรถยนต์
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการเล่นเนื้อหาเสียง โปรดดู ภาพรวมของ MediaPlayer ภาพรวมแอปเสียง, และภาพรวม ExoPlayer
ตั้งค่าการทำงานมาตรฐานในการเล่น
การควบคุมการเล่นจอแสดงผล Android Auto และ Android Automotive OS ตาม
การดำเนินการที่เปิดใช้ใน PlaybackStateCompat
ออบเจ็กต์
โดยค่าเริ่มต้น แอปของคุณต้องรองรับการดำเนินการต่อไปนี้
แอปรองรับการดำเนินการต่อไปนี้เพิ่มเติมได้ด้วย หากเกี่ยวข้องกับ เนื้อหาของแอป
นอกจากนี้ คุณยังมีตัวเลือกในการสร้างคิวการเล่นที่สามารถแสดงผลสำหรับ
ผู้ใช้ แต่ไม่จำเป็น ในการดำเนินการนี้ ให้เรียก setQueue()
และ setQueueTitle()
ให้เปิดใช้ ACTION_SKIP_TO_QUEUE_ITEM
การทำงาน และกำหนด Callback onSkipToQueueItem()
และเพิ่มการสนับสนุนสำหรับไอคอนกำลังเล่น ซึ่งเป็นสัญญาณบอกสถานะ
กำลังเล่นอยู่ ในการดำเนินการนี้ ให้เรียก setActiveQueueItemId()
และส่งรหัสของรายการที่กำลังเล่นอยู่ในคิว สิ่งที่คุณต้องทำ
อัปเดต setActiveQueueItemId()
เมื่อใดก็ตามที่มีการเปลี่ยนแปลงคิว
ปุ่มแสดง Android Auto และ Android Automotive OS สำหรับการดำเนินการที่เปิดใช้แต่ละรายการ
และคิวการเล่น เมื่อปุ่ม
ระบบจะเรียกใช้ Callback ที่เกี่ยวข้องจาก
MediaSessionCompat.Callback
จองพื้นที่ที่ไม่ได้ใช้
พื้นที่สงวนของ Android Auto และ Android Automotive OS ใน UI สําหรับ
การดำเนินการ ACTION_SKIP_TO_PREVIOUS
และ ACTION_SKIP_TO_NEXT
รายการ หากแอปของคุณ
ไม่รองรับฟังก์ชันเหล่านี้ การใช้ Android Auto และ Android Automotive OS
พื้นที่ทำงานเพื่อแสดงการดำเนินการที่กำหนดเองที่คุณสร้างขึ้น
หากคุณไม่ต้องการเติมพื้นที่ทำงานเหล่านั้นด้วยการดำเนินการที่กำหนดเอง คุณสามารถจอง
เพื่อให้ Android Auto และ Android Automotive OS เว้นช่องว่างไว้
เมื่อใดก็ตามที่แอปไม่รองรับฟังก์ชันที่เกี่ยวข้อง โดยโทร
setExtras()
ด้วยกลุ่มพิเศษที่มีค่าคงที่ที่สอดคล้องกับ
ฟังก์ชันที่สงวนไว้
SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT
สอดคล้องกับ ACTION_SKIP_TO_NEXT
และ
SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV
สอดคล้องกับ ACTION_SKIP_TO_PREVIOUS
ใช้ค่าคงที่เหล่านี้เป็นคีย์ใน
และใช้บูลีน true
สำหรับค่า
ตั้งค่า PlaybackState เริ่มต้น
เมื่อ Android Auto และ Android Automotive OS สื่อสารกับเบราว์เซอร์สื่อของคุณ
เซสชันสื่อของคุณจะสื่อสารสถานะการเล่นเนื้อหาโดยใช้
PlaybackStateCompat
แอปของคุณไม่ควรเริ่มเล่นเพลงโดยอัตโนมัติเมื่อ Android Automotive OS
หรือ Android Auto เชื่อมต่อกับบริการเบราว์เซอร์สื่อของคุณ โปรดใช้ Android แทน
Auto และ Android Automotive OS เพื่อกลับมาเล่นต่อหรือเริ่มเล่นตามการใช้งานของรถ
สถานะหรือการดำเนินการของผู้ใช้
หากต้องการทำเช่นนี้ ให้ตั้งค่า PlaybackStateCompat
เริ่มต้น
ของเซสชันสื่อไปยัง
STATE_STOPPED
,
STATE_PAUSED
,
STATE_NONE
หรือ STATE_ERROR
เซสชันสื่อภายใน Android Auto และ Android Automotive OS จะมีระยะเวลาไม่เกิน
ระยะเวลาขับรถ ดังนั้นผู้ใช้จึงเริ่มและหยุดเซสชันเหล่านี้บ่อยครั้ง ถึง
สร้างประสบการณ์ที่ดีระหว่างการขับรถ ติดตามประสบการณ์ที่ผ่านมาของผู้ใช้
ดังนั้นเมื่อแอปสื่อได้รับ
ให้กลับมาทำงานอีกครั้ง ผู้ใช้จึงจะดำเนินการต่อจากที่ค้างไว้ได้โดยอัตโนมัติ
ตัวอย่างเช่น รายการสื่อที่เล่นล่าสุด PlaybackStateCompat
และคิว
เพิ่มการทำงานที่กำหนดเองในการเล่น
คุณสามารถเพิ่มการทำงานที่กำหนดเองในการเล่นเพื่อแสดงการทำงานอื่นๆ ที่
รองรับแอปสื่อ หากมีพื้นที่เพียงพอ (และไม่ได้จองไว้) Android จะเพิ่ม
การดำเนินการที่กำหนดเองไปยังตัวควบคุมการรับส่งข้อมูล มิฉะนั้น การทำงานที่กำหนดเอง
แสดงในเมนูรายการเพิ่มเติม การดำเนินการที่กำหนดเองจะแสดงตามลำดับ
ระบบจะเพิ่มผู้ใช้ใน PlaybackStateCompat
ใช้การกระทำที่กำหนดเองเพื่อสร้างลักษณะการทำงานที่แตกต่างจากมาตรฐาน การดำเนินการ อย่าใช้เพื่อแทนที่หรือทำสำเนามาตรฐาน การดำเนินการ
คุณเพิ่มการดำเนินการที่กำหนดเองได้โดยใช้addCustomAction()
ในPlaybackStateCompat.Builder
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเพิ่ม "เริ่มช่องวิทยุ" ที่กำหนดเอง การดำเนินการ:
Kotlin
stateBuilder.addCustomAction( PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_START_RADIO_FROM_MEDIA, resources.getString(R.string.start_radio_from_media), startRadioFromMediaIcon ).run { setExtras(customActionExtras) build() } )
Java
stateBuilder.addCustomAction( new PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_START_RADIO_FROM_MEDIA, resources.getString(R.string.start_radio_from_media), startRadioFromMediaIcon) .setExtras(customActionExtras) .build());
ดูตัวอย่างโดยละเอียดของวิธีการนี้ได้ที่ setCustomAction()
ในแอปตัวอย่างของ Universal Android Music Player บน GitHub
หลังจากสร้างการกระทำที่กำหนดเองแล้ว เซสชันสื่อจะตอบสนองต่อการดำเนินการได้
โดยการลบล้าง onCustomAction()
ข้อมูลโค้ดต่อไปนี้จะแสดงวิธีที่แอปของคุณอาจตอบสนองต่อ การดำเนินการ "เริ่มช่องวิทยุ"
Kotlin
override fun onCustomAction(action: String, extras: Bundle?) { when(action) { CUSTOM_ACTION_START_RADIO_FROM_MEDIA -> { ... } } }
Java
@Override public void onCustomAction(@NonNull String action, Bundle extras) { if (CUSTOM_ACTION_START_RADIO_FROM_MEDIA.equals(action)) { ... } }
ดูตัวอย่างโดยละเอียดของวิธีการนี้ได้ที่ onCustomAction
ในแอปตัวอย่างของ Universal Android Music Player บน GitHub
ไอคอนสำหรับการกระทำที่กำหนดเอง
การดำเนินการที่กำหนดเองแต่ละรายการที่คุณสร้างขึ้นต้องใช้ทรัพยากรไอคอน แอปในรถยนต์สามารถ ได้บนหน้าจอหลายขนาดและหลายระดับ เช่น ไอคอนที่คุณให้ ต้องเป็น เวกเตอร์ที่ถอนออกได้ ต Vector Drawable ทำให้คุณปรับขนาดชิ้นงานได้โดยที่รายละเอียดไม่หายไป เวกเตอร์ ยังสามารถวาดได้ง่าย ช่วยให้สามารถจัดแนวขอบและมุมตามขอบเขตพิกเซล ความละเอียดน้อยลงได้อีกด้วย
หากการดำเนินการที่กำหนดเองเป็นแบบเก็บสถานะ เช่น เปิด/ปิดการตั้งค่าการเล่น ปิด ระบุไอคอนที่แตกต่างกันสำหรับแต่ละสถานะเพื่อให้ผู้ใช้ จะเห็นการเปลี่ยนแปลงเมื่อเลือกการดำเนินการ
ระบุรูปแบบไอคอนอื่นสำหรับการดำเนินการที่ปิดใช้
เมื่อการดำเนินการที่กำหนดเองไม่พร้อมใช้งานกับบริบทปัจจุบัน ให้สลับ ไอคอนการดำเนินการที่กำหนดเอง ซึ่งมีไอคอนสำรองที่แสดงว่าการดำเนินการดังกล่าว ปิดใช้อยู่
ระบุรูปแบบเสียง
หากต้องการระบุว่าสื่อที่กำลังเล่นอยู่ใช้รูปแบบเสียงพิเศษ
คุณสามารถระบุไอคอนที่แสดงผลในรถยนต์ที่รองรับฟีเจอร์นี้ได้ คุณ
สามารถตั้งค่า
KEY_CONTENT_FORMAT_TINTABLE_LARGE_ICON_URI
และ
KEY_CONTENT_FORMAT_TINTABLE_SMALL_ICON_URI
ในแพ็กเกจเพิ่มเติมของรายการสื่อที่เล่นอยู่ (ส่งไปยัง
MediaSession.setMetadata()
) อย่าลืมตั้งค่าทั้งคู่
เพื่อให้เหมาะกับเลย์เอาต์แบบต่างๆ
นอกจากนี้ คุณยังสามารถตั้งค่า KEY_IMMERSIVE_AUDIO
เพิ่มเติม
เพื่อบอก OEM รถยนต์ว่านี่เป็นเสียงที่สมจริง และพวกเขาควรระมัดระวังให้มาก
เมื่อตัดสินใจว่าจะใช้เอฟเฟกต์เสียงที่อาจรบกวน
เนื้อหาแบบสมจริง
เพิ่มลิงก์จากรายการที่กำลังเล่นอยู่
คุณสามารถกำหนดค่ารายการสื่อที่กำลังเล่น เพื่อให้คำบรรยาย คำอธิบาย หรือทั้งสองอย่างเป็นลิงก์ไปยังรายการสื่ออื่นๆ ซึ่งช่วยให้ผู้ใช้ข้ามไปยัง รายการที่เกี่ยวข้อง เช่น อาจข้ามไปยังเพลงอื่นของศิลปินคนเดียวกัน ตอนอื่นๆ ของพอดแคสต์นั้น ฯลฯ หากรถยนต์รองรับฟีเจอร์นี้ ก็สามารถแตะลิงก์เพื่อเรียกดูเนื้อหานั้น
หากต้องการเพิ่มลิงก์ ให้กำหนดค่า
ข้อมูลเมตา KEY_SUBTITLE_LINK_MEDIA_ID
(เพื่อลิงก์จากคำบรรยาย) หรือ
KEY_DESCRIPTION_LINK_MEDIA_ID
(เพื่อลิงก์จาก
คำอธิบาย) โปรดดูรายละเอียดในเอกสารอ้างอิงสําหรับ
ช่องข้อมูลเมตา
รองรับการสั่งงานด้วยเสียง
แอปสื่อต้องรองรับการสั่งงานด้วยเสียงเพื่อช่วยให้ผู้ขับขี่ปลอดภัย และประสบการณ์การใช้งานแสนสะดวก ที่ช่วยลดสิ่งรบกวนสมาธิ ตัวอย่างเช่น หากแอปของคุณ กำลังเล่นรายการสื่อ 1 รายการ ผู้ใช้สามารถพูดว่า "เปิด [ชื่อเพลง]" เพื่อบอกแอปของคุณให้เล่นเพลงอื่นโดยไม่ต้องดูหรือแตะเพลง จอแสดงผล ผู้ใช้สามารถเริ่มการค้นหาได้โดยคลิกปุ่มที่เหมาะสม พวงมาลัยหรือพูดคำสั่งให้ดำเนินการ "OK Google"
เมื่อ Android Auto หรือ Android Automotive OS ตรวจพบและตีความเสียง
การดำเนินการดังกล่าว คือการสั่งงานด้วยเสียงผ่าน
onPlayFromSearch()
เมื่อได้รับการติดต่อกลับนี้ แอปพบเนื้อหาที่ตรงกับ query
และเริ่มเล่น
ผู้ใช้สามารถระบุหมวดหมู่ของคำต่างๆ ในการค้นหา ได้แก่ แนวเพลง ศิลปิน
อัลบั้ม ชื่อเพลง สถานีวิทยุ หรือเพลย์ลิสต์ และอื่นๆ เมื่อสร้าง
รองรับการค้นหา รวมถึงหมวดหมู่ทั้งหมดที่เหมาะกับแอปของคุณ
หาก Android Auto หรือ Android Automotive OS ตรวจพบว่าคําค้นหาที่ระบุตรงกับ
ในบางหมวดหมู่ ตำแหน่งนี้จะต่อท้ายในพารามิเตอร์ extras
สามารถส่งเพิ่มเติมต่อไปนี้:
บัญชีสำหรับสตริง query
ที่ว่างเปล่า ซึ่งสามารถส่งได้โดย
Android Auto หรือ Android Automotive OS หากผู้ใช้ไม่ได้ระบุข้อความค้นหา
เช่น หากผู้ใช้พูดว่า "เปิดเพลง" ในกรณีนี้ แอปของคุณอาจ
เลือกแทร็กที่เล่นล่าสุดหรือแทร็กที่แนะนำใหม่
หากดำเนินการค้นหาไม่ได้อย่างรวดเร็ว โปรดอย่าบล็อกใน onPlayFromSearch()
แต่ให้ตั้งสถานะการเล่นเป็น STATE_CONNECTING
แทน
และค้นหาชุดข้อความอะซิงโครนัส
เมื่อเริ่มเล่น ให้พิจารณาใส่คิวเซสชันสื่อด้วย เนื้อหาที่เกี่ยวข้อง ตัวอย่างเช่น หากผู้ใช้ขอให้เล่นอัลบั้ม อาจใส่รายการแทร็กของอัลบั้มลงในคิว รวมทั้งพิจารณาการใช้งาน สนับสนุนผลการค้นหาที่เรียกดูได้ เพื่อให้ผู้ใช้เลือก แทร็กอื่นที่ตรงกับคำค้นหา
นอกเหนือจาก "play" การค้นหา, Android Auto และ Android Automotive OS
จดจำคำสั่งเสียงเพื่อควบคุมการเล่น เช่น "หยุดเพลงชั่วคราว" และ "ถัดไป
"เพลง" และจับคู่คำสั่งเหล่านี้กับ Callback ของเซสชันสื่อที่เหมาะสม
เช่น onPause()
และ onSkipToNext()
สำหรับตัวอย่างโดยละเอียดเกี่ยวกับวิธีใช้การเล่นเสียงที่สามารถเล่นได้ใน ดู Google Assistant และแอปสื่อ
ใช้การป้องกันสิ่งรบกวน
เนื่องจากโทรศัพท์ของผู้ใช้เชื่อมต่อกับลำโพงรถยนต์ขณะใช้ Android รถยนต์ คุณต้องระมัดระวังเป็นพิเศษเพื่อช่วยป้องกันสิ่งรบกวนผู้ขับขี่
ลดเสียงสัญญาณเตือนในรถ
แอปสื่อของ Android Auto ต้องไม่เริ่มเล่นเสียงผ่านลำโพงรถยนต์ เว้นแต่ผู้ใช้จะเริ่มเล่นโดยการกดปุ่มเล่น เป็นต้น แม้แต่การตั้งปลุกที่ผู้ใช้กำหนดเวลาไว้จากแอปสื่อก็ต้องไม่เริ่มทำงาน กำลังเปิดเพลงผ่านลำโพงรถ
เพื่อให้เป็นไปตามข้อกำหนดนี้ แอปของคุณ
สามารถใช้ CarConnection
เป็นสัญญาณก่อนเล่นเสียงใดๆ แอปจะตรวจสอบได้ว่าโทรศัพท์
ฉายภาพไปยังหน้าจอรถโดยสังเกต LiveData
สำหรับการเชื่อมต่อรถ
ประเภท
และตรวจสอบว่าค่าเท่ากับ
CONNECTION_TYPE_PROJECTION
ถ้าโทรศัพท์ของผู้ใช้กำลังฉายภาพ แอปสื่อที่รองรับการปลุกจะต้องแสดง ดังนี้
- ปิดการปลุก
- เล่นการปลุกเวลา
STREAM_ALARM
และแสดง UI ในหน้าจอโทรศัพท์เพื่อปิดใช้การปลุก
จัดการโฆษณาสื่อ
โดยค่าเริ่มต้น Android Auto จะแสดงการแจ้งเตือนเมื่อข้อมูลเมตาของสื่อมีการเปลี่ยนแปลง
ระหว่างเซสชันการเล่นเสียง เมื่อแอปสื่อเปลี่ยนจากการเปิดเพลง
การแสดงโฆษณาจะเป็นการรบกวนการแสดง
ให้ผู้ใช้ทราบ หากต้องการป้องกันไม่ให้ Android Auto แสดงการแจ้งเตือน
ในกรณีนี้ คุณต้องตั้งค่าคีย์ข้อมูลเมตาของสื่อ
METADATA_KEY_IS_ADVERTISEMENT
ถึง
METADATA_VALUE_ATTRIBUTE_PRESENT
,
ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
Kotlin
import androidx.media.utils.MediaConstants override fun onPlayFromMediaId(mediaId: String, extras: Bundle?) { MediaMetadataCompat.Builder().apply { if (isAd(mediaId)) { putLong( MediaConstants.METADATA_KEY_IS_ADVERTISEMENT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) } // ...add any other properties you normally would. mediaSession.setMetadata(build()) } }
Java
import androidx.media.utils.MediaConstants; @Override public void onPlayFromMediaId(String mediaId, Bundle extras) { MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); if (isAd(mediaId)) { builder.putLong( MediaConstants.METADATA_KEY_IS_ADVERTISEMENT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT); } // ...add any other properties you normally would. mediaSession.setMetadata(builder.build()); }
จัดการกับข้อผิดพลาดทั่วไป
เมื่อแอปพบข้อผิดพลาด ให้ตั้งค่าสถานะการเล่นเป็น STATE_ERROR
และแสดงข้อความแสดงข้อผิดพลาดโดยใช้ setErrorMessage()
โปรดดู PlaybackStateCompat
สำหรับรายการรหัสข้อผิดพลาดที่คุณใช้เมื่อตั้งค่าข้อความแสดงข้อผิดพลาดได้
ข้อความแสดงข้อผิดพลาดจะต้องแสดงต่อผู้ใช้และแปลเป็นภาษาปัจจุบันของผู้ใช้
ภาษา Android Auto และ Android Automotive OS จะแสดงข้อผิดพลาดได้
ข้อความถึงผู้ใช้
ตัวอย่างเช่น หากเนื้อหาไม่พร้อมใช้งานในภูมิภาคปัจจุบันของผู้ใช้ คุณจะดำเนินการต่อไปนี้ได้
ใช้ERROR_CODE_NOT_AVAILABLE_IN_REGION
เมื่อตั้งค่าข้อความแสดงข้อผิดพลาด
Kotlin
mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR) .setErrorMessage(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION, getString(R.string.error_unsupported_region)) // ...and any other setters. .build())
Java
mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR) .setErrorMessage(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION, getString(R.string.error_unsupported_region)) // ...and any other setters. .build());
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสถานะข้อผิดพลาด โปรดดูการใช้เซสชันสื่อ: สถานะ และข้อผิดพลาด
หากผู้ใช้ Android Auto ต้องการเปิดแอปโทรศัพท์เพื่อแก้ไขข้อผิดพลาด ให้ทำดังนี้ ให้ข้อมูลนั้นแก่ผู้ใช้ในข้อความ เช่น ข้อผิดพลาด อาจแสดงข้อความว่า "ลงชื่อเข้าใช้ [ชื่อแอปของคุณ]" แทน "โปรดลงชื่อเข้าใช้"