หน้านี้อธิบายวิธีการใช้วิทยุในระดับฮาร์ดแวร์และซอฟต์แวร์
- ส่วนประกอบของระบบ แสดงและอธิบายกลุ่มเทคโนโลยีวิทยุ
- เลเยอร์นามธรรมของฮาร์ดแวร์วิทยุกระจายเสียง (HAL) จัดเตรียมโครงสร้างข้อมูลและอินเทอร์เฟซสำหรับ OEM เพื่อใช้วิทยุกระจายเสียง เช่น AM/FM และวิทยุกระจายเสียงแบบดิจิทัล (DAB) ในระดับฮาร์ดแวร์
- การใช้งานการควบคุมวิทยุ จะขึ้นอยู่กับ
MediaSession
และMediaBrowse
ซึ่งช่วยให้แอปสื่อและเสียงสามารถควบคุมวิทยุได้ นอกเหนือจากเนื้อหาที่ให้ไว้ด้านล่าง โปรดดู สร้างแอปสื่อสำหรับรถยนต์
ส่วนประกอบของระบบ
สแต็กวิทยุกระจายเสียงประกอบด้วยส่วนประกอบต่อไปนี้
แอพอ้างอิงวิทยุ
สำหรับรายละเอียดเกี่ยวกับวิธีการใช้งานการควบคุมด้วยวิทยุ โปรดดูที่ การใช้งานการควบคุมด้วยวิทยุ
แอปวิทยุ Java ตัวอย่าง ( packages/apps/Car/Radio
) ทำหน้าที่เป็นการใช้งานอ้างอิง เมื่อบริการแอปเริ่มต้นขึ้น แอปจะขอให้ Radio Manager เปิดเครื่องรับวิทยุ จากนั้น แอพสามารถส่งคำขอไปยังเครื่องรับวิทยุ เช่น การจูนสถานีวิทยุเฉพาะ ความถี่ หรือเพื่อค้นหาสถานีวิทยุถัดไปที่มีอยู่ แอพได้รับการอัพเดตจาก Radio Manager และ Radio Tuner ในวิทยุ เช่น ข้อมูลรายการปัจจุบัน รายการรายการวิทยุ การกำหนดค่า และพารามิเตอร์ที่ผู้จำหน่ายกำหนด แอปวิทยุอ้างอิงรองรับเฉพาะวิทยุ AM และ FM OEM สามารถแก้ไขหรือแทนที่แอป Radio ได้ตามต้องการ
ผู้จัดการวิทยุ
เมื่อแอปขอให้ Radio Manager เปิดจูนเนอร์ Radio Manager ( frameworks/base/core/java/android/hardware/radio/RadioManager.java
) ร้องขอบริการ Broadcast Radio ให้เปิดเซสชัน Tuner จากนั้นล้อมเซสชันไว้ใน Radio Tuner ( frameworks/base/core/java/android/hardware/radio/RadioTuner.java
) ซึ่งส่งคืนให้กับแอป เครื่องรับวิทยุกำหนด API (เช่น ปรับแต่ง ขั้นตอน และยกเลิก) ที่สามารถเรียกจากแอปวิทยุและส่งคำขอไปยังบริการวิทยุกระจายเสียง วิธีการโทรกลับ ( RadioTuner.Callback
) ที่กำหนดในเครื่องรับวิทยุจะส่งการอัพเดตเกี่ยวกับวิทยุกระจายเสียง HAL เช่น ข้อมูลโปรแกรมปัจจุบัน รายชื่อโปรแกรม และพารามิเตอร์ที่ผู้จำหน่ายกำหนด จากบริการวิทยุกระจายเสียงไปยังแอพ
บริการวิทยุกระจายเสียง
บริการวิทยุกระจายเสียง ( frameworks/base/services/core/java/com/android/server/broadcastradio
) เป็นบริการลูกค้าสำหรับ Broadcast Radio HAL บริการวิทยุกระจายเสียงประสานงานผู้จัดการวิทยุหลายรายกับ Broadcast Radio HAL บริการวิทยุกระจายเสียงรองรับ HAL ภาษาคำจำกัดความอินเทอร์เฟซ (HIDL) และ ภาษาคำจำกัดความอินเทอร์เฟซ Android (AIDL) HAL วิทยุออกอากาศ บริการวิทยุกระจายเสียงจะเชื่อมโยงกับ AIDL HAL เมื่อมีบริการ AIDL HAL อยู่ มิฉะนั้น บริการจะเชื่อมโยงกับ HIDL HAL บริการวิทยุกระจายเสียงสร้างโมดูลวิทยุสำหรับอินสแตนซ์ HAL แต่ละรายการที่มีอยู่ (เช่น AM, FM และ DAB)
ผู้จัดการวิทยุแต่ละคนสามารถร้องขอบริการวิทยุกระจายเสียงเพื่อสร้างเซสชันจูนเนอร์บนโมดูลวิทยุที่เกี่ยวข้อง โดยขึ้นอยู่กับประเภทของวิทยุ แต่ละเซสชันเครื่องรับสามารถเรียกวิธีการต่างๆ เช่น ปรับแต่ง ขั้นตอน และยกเลิก (กำหนดไว้ในอินเทอร์เฟซ HAL) เพื่อดำเนินการกับอินสแตนซ์ HAL วิทยุกระจายเสียงที่เกี่ยวข้อง เมื่อเซสชันเครื่องรับสัญญาณได้รับการติดต่อกลับจากอินสแตนซ์ HAL ในการอัปเดต HAL เช่น ข้อมูลโปรแกรมปัจจุบัน รายการโปรแกรม การตั้งค่าสถานะ และพารามิเตอร์ของผู้จำหน่าย การเรียกกลับเกี่ยวกับการอัพเดตจะถูกส่งไปยังเครื่องรับวิทยุทั้งหมดที่เชื่อมโยงกับโมดูลวิทยุเดียวกัน
วิทยุกระจายเสียง HAL
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับอินเทอร์เฟซ HIDL และ AIDL ของวิทยุกระจายเสียง และความแตกต่างระหว่างทั้งสอง โปรดดูที่ อินเทอร์เฟซ HAL ของวิทยุกระจายเสียง
เลเยอร์นามธรรมของฮาร์ดแวร์วิทยุกระจายเสียง
ส่วนต่อไปนี้อธิบายวิธีการทำงานกับ hardware abstraction layer (HAL) เพื่อใช้งานวิทยุกระจายเสียง
อินเตอร์เฟซวิทยุกระจายเสียง HAL
วิทยุกระจายเสียง HAL มีโครงสร้างข้อมูลและอินเทอร์เฟซในระดับฮาร์ดแวร์เพื่อใช้งานวิทยุกระจายเสียง เช่น วิทยุ AM/FM และ DAB
อินเทอร์เฟซ HIDL 2.0 และ AIDL
วิทยุกระจายเสียง HAL ใช้อินเทอร์เฟซที่อธิบายไว้ในส่วนต่อไปนี้
ผู้ฟังประกาศ
IAnnouncementListener
เป็นอินเทอร์เฟซการโทรกลับสำหรับผู้ฟังประกาศ ซึ่งสามารถลงทะเบียนทางวิทยุกระจายเสียง HAL เพื่อรับประกาศได้ อินเทอร์เฟซมีวิธีการดังต่อไปนี้:
Iประกาศผู้ฟัง | ||
---|---|---|
คำอธิบาย: โทรทุกครั้งที่รายการประกาศมีการเปลี่ยนแปลง | ||
HIDL2.0 | oneway onListUpdated(vec<Announcement> announcements) | |
โรคเอดส์ | oneway void onListUpdated(in Announcement[] announcements) |
ปิดที่จับ
ICloseHandle
เป็นจุดจับปิดทั่วไปเพื่อลบการติดต่อกลับที่ไม่ต้องการอินเทอร์เฟซที่ใช้งานอยู่
ICloseHandle | ||
---|---|---|
คำอธิบาย : ปิดที่จับ. | ||
HIDL2.0 | close() | |
โรคเอดส์ | void close() |
อินเทอร์เฟซการโทรกลับ
ITunerCallback
เป็นอินเทอร์เฟซการติดต่อกลับที่เรียกโดยวิทยุกระจายเสียง HAL เพื่อส่งการอัปเดตไปยังบริการไคลเอ็นต์ HAL
ITunerCallback | ||
---|---|---|
คำอธิบาย: เรียกโดย HAL เมื่อการดำเนินการปรับแต่ง (ปรับแต่ง ค้นหา (ใน AIDL) หรือสแกน (ใน HIDL) และขั้นตอนสำเร็จ) ล้มเหลวแบบอะซิงโครนัส | ||
HIDL2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
โรคเอดส์ | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
คำอธิบาย: เรียกว่าเมื่อปรับแต่ง ค้นหา (ใน AIDL) หรือสแกน (ใน HIDL) หรือขั้นตอนสำเร็จ | ||
HIDL2.0 | oneway onTuneFailed(Result result, ProgramSelector selector) | |
โรคเอดส์ | void onTuneFailed(in Result result, in ProgramSelector selector) | |
คำอธิบาย: เรียกว่าเมื่อปรับแต่ง ค้นหา (ใน AIDL) หรือสแกน (ใน HIDL) หรือขั้นตอนสำเร็จ | ||
HIDL2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
โรคเอดส์ | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
คำอธิบาย: เรียกเมื่อมีการอัพเดตรายการโปรแกรม; ขนาดของแต่ละชิ้นควรจำกัดไว้ที่ 500kiB | ||
HIDL2.0 | oneway onProgramListUpdated(ProgramListChunk chunk) | |
โรคเอดส์ | oneway onProgramListUpdated(ProgramListChunk chunk) | |
คำอธิบาย: เรียกว่าเมื่อเชื่อมต่อเสาอากาศหรือตัดการเชื่อมต่อ | ||
HIDL2.0 | oneway onAntennaStateChange(bool connected) | |
โรคเอดส์ | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
คำอธิบาย: ถูกเรียกเมื่อมีการอัพเดตค่าพารามิเตอร์เฉพาะผู้จำหน่ายภายในใน HAL (ไม่ควรเรียกใช้หลังจากการเรียก setParameters โดยไคลเอนต์ HAL) | ||
HIDL2.0 | oneway onParametersUpdated(vec<VendorKeyValue> parameters) | |
โรคเอดส์ | void onParametersUpdated(in VendorKeyValue[] parameters) | |
คำอธิบาย: ใหม่ใน AIDL เรียกว่าเมื่อมีการอัปเดตการตั้งค่าสถานะภายในใน HAL (ไม่ควรเรียกใช้หลังจากเรียก setConfigFlag โดยไคลเอ็นต์ HAL) | ||
HIDL2.0 | ไม่สามารถใช้ได้. | |
โรคเอดส์ | void onConfigFlagUpdated(in ConfigFlag flag, in boolean value) |
อินเทอร์เฟซ HAL ของวิทยุกระจายเสียงหลัก
IBroadcastRadio
เป็นอินเทอร์เฟซหลักสำหรับวิทยุกระจายเสียง HAL ใน HIDL 2.0 HAL ให้ใช้อินเทอร์เฟ ITunerSession
กับจูนเนอร์เพื่อเรียกใช้การดำเนินการ อย่างไรก็ตาม มีจูนเนอร์ที่ใช้งานได้สูงสุด 1 ตัวในคราวเดียว (โดยที่อินสแตนซ์ HAL วิทยุกระจายเสียงแต่ละตัวมีชิปจูนเนอร์เพียงตัวเดียวเท่านั้น) ITunerSession
ถูกลบออกจากอินเทอร์เฟซ AIDL และอินเทอร์เฟซถูกย้ายไปยัง IBroadcastRadio
IBroadcastRadio | ||
---|---|---|
คำอธิบาย: รับคำอธิบายของโมดูลและความสามารถของโมดูล | ||
HIDL2.0 | getProperties() generates (Properties properties) | |
โรคเอดส์ | Properties getProperties() | |
คำอธิบาย: ดึงข้อมูลการกำหนดค่าภูมิภาค AM/FM ในปัจจุบันหรือที่เป็นไปได้ | ||
HIDL2.0 | getAmFmRegionConfig(bool full) generates (Result result, AmFmRegionConfig config) | |
โรคเอดส์ | AmFmRegionConfig getAmFmRegionConfig(bool full) | |
คำอธิบาย: ดึงข้อมูลการกำหนดค่าภูมิภาค DAB ปัจจุบัน | ||
HIDL2.0 | getDabRegionConfig() generates (Result result, vec<DabTableEntry> config) | |
โรคเอดส์ | DabTableEntry[] getDabRegionConfig() | |
คำอธิบาย: รับภาพจากแคชโมดูลวิทยุ ใน AIDL ขนาดรูปภาพต้องน้อยกว่า 1MB เนื่องจากขีดจำกัดฮาร์ดในบัฟเฟอร์ธุรกรรมของ Binder | ||
HIDL2.0 | getImage(uint32_t id) generates (vec<uint8_t> image) | |
โรคเอดส์ | byte[] getImage(in int id) | |
คำอธิบาย: ลงทะเบียนผู้ฟังประกาศ | ||
HIDL2.0 | registerAnnouncementListener(vec<AnnouncementType> enabled,IAnnouncementListener listener) generates (Result result, ICloseHandle closeHandle) | |
โรคเอดส์ | ICloseHandle registerAnnouncementListener(in IAnnouncementListener listener, in AnnouncementType[] enabled) | |
คำอธิบาย:
| ||
HIDL2.0 | openSession(ITunerCallback callback) สร้างขึ้น (Result result, ITunerSession session) | |
โรคเอดส์ | void setTunerCallback(in ITunerCallback callback) | |
คำอธิบาย:
| ||
HIDL2.0 | close() | |
โรคเอดส์ | unsetTunerCallback() | |
คำอธิบาย: ปรับไปยังโปรแกรมที่ระบุ | ||
HIDL2.0 | tune(ProgramSelector program) generates (Result result) | |
โรคเอดส์ | void tune(in ProgramSelector program) | |
คำอธิบาย: ค้นหารายการที่ถูกต้องรายการถัดไปที่ ออกอากาศ เพื่อหลีกเลี่ยงความสับสนใน AIDL scan จึงเปลี่ยนชื่อเป็น seek | ||
HIDL2.0 | scan(bool directionUp, bool skipSubChannel) generates (Result result) | |
โรคเอดส์ | void seek(in boolean directionUp, in boolean skipSubChannel) | |
คำอธิบาย: ขั้นตอนสู่ช่องสัญญาณที่อยู่ติดกันซึ่งอาจไม่ถูกครอบครองโดยโปรแกรมใด ๆ | ||
HIDL2.0 | step(bool directionUp) generates (Result result) | |
โรคเอดส์ | void step(in boolean directionUp) | |
คำอธิบาย: ยกเลิกการปรับแต่งที่ค้างอยู่ การสแกน (ใน HIDL) หรือการค้นหา (ใน AIDL) หรือการดำเนินการตามขั้นตอน | ||
HIDL2.0 | cancel() | |
โรคเอดส์ | void cancel() | |
คำอธิบาย: ใช้ตัวกรองกับรายการโปรแกรมและเริ่มส่งการอัปเดตรายการโปรแกรมผ่านการโทรกลับ onProgramListUpdated | ||
HIDL2.0 | startProgramListUpdates(ProgramFilter filter) generates (Result result) | |
โรคเอดส์ | void startProgramListUpdates(in ProgramFilter filter) | |
คำอธิบาย: หยุดส่งการอัปเดตรายการโปรแกรม | ||
HIDL2.0 | stopProgramListUpdates() | |
โรคเอดส์ | void stopProgramListUpdates() | |
คำอธิบาย: ดึงข้อมูลการตั้งค่าปัจจุบันของแฟล็กการกำหนดค่าที่กำหนด | ||
HIDL2.0 | isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value) | |
โรคเอดส์ | boolean isConfigFlagSet(in ConfigFlag flag) | |
คำอธิบาย: ตั้งค่าสถานะการตั้งค่าที่กำหนด | ||
HIDL2.0 | setConfigFlag(ConfigFlag flag, bool value) generates (Result result) | |
โรคเอดส์ | void setConfigFlag(in ConfigFlag flag, boolean value) | |
คำอธิบาย: ตั้งค่าพารามิเตอร์เฉพาะผู้ขาย | ||
HIDL2.0 | setParameters(vec<VendorKeyValue> parameters) ก่อให้เกิด (vec<VendorKeyValue> results) | |
โรคเอดส์ | VendorKeyValue[] setParameters(in VendorKeyValue[] parameters) | |
คำอธิบาย: ดึงค่าพารามิเตอร์เฉพาะของผู้ขาย | ||
HIDL2.0 | getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters) | |
โรคเอดส์ | VendorKeyValue[] getParameters(in String[] keys) |
การชี้แจงอินเทอร์เฟซ
พฤติกรรมแบบอะซิงโครนัส
เนื่องจากการดำเนินการปรับแต่งแต่ละครั้ง (เช่น ปรับแต่ง สแกน (ใน HIDL) หรือค้นหา (ใน AIDL) และขั้นตอน) อาจใช้เวลานาน และไม่ควรบล็อกเธรดเป็นเวลานาน การดำเนินการจึงควรกำหนดเวลาการดำเนินการที่ใช้เวลานาน ให้เกิดขึ้นในภายหลังและคืนสถานะหรือผลลัพธ์อย่างรวดเร็ว ในรายละเอียดแต่ละการดำเนินการควร:
- ยกเลิกการดำเนินการปรับแต่งที่ค้างอยู่ทั้งหมด
- ตรวจสอบว่าการดำเนินการสามารถประมวลผลตามอินพุตวิธีการและสถานะของจูนเนอร์ได้หรือไม่
- กำหนดเวลางานการปรับแต่งแล้วส่งคืน
Result
(ใน HIDL) หรือstatus
(ใน AIDL) ทันที หากResult
หรือstatus
เป็นOK
จะต้องเรียกจูนเนอร์เรียกกลับtuneFailed
หรือcurrentProgramInfoChanged
เมื่องานการปรับแต่งล้มเหลว (เช่น เนื่องจากการหมดเวลา) หรือเสร็จสมบูรณ์
ในทำนองเดียวกัน startProgramListUpdates
ยังจัดกำหนดการงานที่ต้องใช้เวลานานในการอัพเดตรายการโปรแกรมเพื่อให้เกิดขึ้นในภายหลัง และส่งคืนสถานะหรือผลลัพธ์อย่างรวดเร็ว วิธีแรกจะยกเลิกคำขอการอัปเดตที่รอดำเนินการ จากนั้นกำหนดเวลางานการอัปเดตและส่งคืนผลลัพธ์อย่างรวดเร็ว
สภาพการแข่งขัน
เนื่องจากพฤติกรรมแบบอะซิงโครนัสของการดำเนินการปรับแต่ง (เช่น ปรับแต่ง สแกน (ใน HIDL) หรือค้นหา (ใน AIDL) และขั้นตอน) มีสภาวะการแข่งขันระหว่างการยกเลิกการดำเนินการและการดำเนินการปรับแต่ง หากมีการเรียก cancel
หลังจากที่ HAL เสร็จสิ้นการดำเนินการปรับแต่ง และก่อนที่การโทรกลับจะเสร็จสิ้น การยกเลิกสามารถละเว้นได้ และการโทรกลับควรเสร็จสิ้นและได้รับจากไคลเอ็นต์ HAL
ในทำนองเดียวกัน ถ้า stopProgramListUpdates
ถูกเรียกหลังจาก HAL เสร็จสิ้นการอัพเดตรายการโปรแกรม และก่อนที่การเรียกกลับ onCurrentProgramInfoChanged
จะเสร็จสิ้น stopProgramListUpdates
ก็สามารถละเว้นได้ และการเรียกกลับควรเสร็จสิ้น
ขีดจำกัดขนาดข้อมูล
เนื่องจากมีขีดจำกัดฮาร์ดในบัฟเฟอร์ธุรกรรมของ Binder ขีดจำกัดข้อมูลสำหรับวิธีอินเทอร์เฟซบางอย่างที่ส่งผ่านข้อมูลที่อาจมีขนาดใหญ่จึงได้รับการชี้แจงใน AIDL HAL
-
getImage
ต้องการให้อิมเมจส่งคืนน้อยกว่า 1 MB -
onProgramListUpdate
กำหนดให้แต่ละchunk
มีขนาดน้อยกว่า 500kiB รายการโปรแกรมขนาดใหญ่จะต้องแบ่งตามการใช้งาน HAL ออกเป็นหลายส่วน และส่งผ่านการเรียกกลับหลายครั้ง
การเปลี่ยนแปลงโครงสร้างข้อมูล AIDL HAL
นอกเหนือจากการเปลี่ยนแปลงอินเทอร์เฟซแล้ว การเปลี่ยนแปลงเหล่านี้ยังถูกนำไปใช้กับโครงสร้างข้อมูลที่กำหนดไว้ในวิทยุกระจายเสียง AIDL HAL ซึ่งใช้ประโยชน์จาก AIDL
- ค่า
Constant
enum จะถูกลบออกใน AIDL และกำหนดให้เป็น const int ในIBroadcastRadio
ในขณะเดียวกันANTENNA_DISCONNECTED_TIMEOUT_MS
ก็เปลี่ยนชื่อเป็นANTENNA_STATE_CHANGE_TIMEOUT_MS
มีการเพิ่ม const intTUNER_TIMEOUT_MS
ใหม่ การดำเนินการปรับแต่ง ค้นหา และขั้นตอนทั้งหมดจะต้องเสร็จสิ้นภายในเวลานี้ - Enum
RDS
และDeemphasis
จะถูกลบออกใน AIDL และกำหนดให้เป็น const int ในAmFmRegionConfig
ในทำนองเดียวกัน ทั้งfmDeemphasis
และfmRds
ในProgramInfo
ได้รับการประกาศเป็น int ซึ่งเป็นผลการคำนวณบิตของแฟล็กที่เกี่ยวข้อง ในขณะเดียวกันD50
และD75
จะเปลี่ยนชื่อเป็นDEEMPHASIS_D50
และDEEMPHASIS_D75
ตามลำดับ - Enum
ProgramInfoFlags
จะถูกลบออกใน AIDL และกำหนดให้เป็น const int ในProgramInfo
โดยมีการเพิ่มคำนำหน้าFLAG_
ในทำนองเดียวกันinfoFlags
ในProgramInfo
ได้รับการประกาศเป็น int ซึ่งเป็นผลการคำนวณเล็กน้อยของแฟล็กTUNED
ยังเปลี่ยนชื่อเป็นFLAG_TUNABLE
เพื่ออธิบายคำจำกัดความที่สามารถปรับจูนสถานีได้ดีขึ้น - ใน
AmFmBandRange
scanSpacing
จะถูกเปลี่ยนชื่อเป็นseekSpacing
เนื่องจากscan
ถูกเปลี่ยนชื่อเป็นseek
ใน AIDL - เนื่องจากแนวคิดเรื่อง การรวม ถูกนำมาใช้ใน AIDL จึงไม่มีการใช้
MetadataKey
และMetadata
ที่กำหนดใน HIDL HAL อีกต่อไปMetadata
สหภาพ AIDL ถูกกำหนดไว้ใน AIDL HAL ค่าแจงนับแต่ละค่าก่อนหน้านี้ในMetadataKey
กลายเป็นเขตข้อมูลในMetadata
ที่มีประเภทของสตริงหรือ int ขึ้นอยู่กับคำจำกัดความ
การดำเนินการควบคุมด้วยวิทยุ
การใช้งานการควบคุมวิทยุจะขึ้นอยู่กับ MediaSession
และ MediaBrowse
ซึ่งช่วยให้แอปสื่อและเสียงสามารถควบคุมวิทยุได้ สำหรับข้อมูลเพิ่มเติม โปรดดู สร้างแอปสื่อสำหรับรถยนต์ บน Developer.android.com
การใช้งานแผนผังการเรียกดูสื่อมีอยู่ในไลบรารี car-broadcastradio-support ใน packages/apps/Car/libs
ไลบรารีนี้ยังประกอบด้วยส่วนขยายของ ProgramSelector ที่จะแปลงเป็นและจาก URI ขอแนะนำให้การใช้งานวิทยุใช้ไลบรารีนี้เพื่อสร้างแผนผังการสืบค้นที่เกี่ยวข้อง
ตัวสลับแหล่งสื่อ
เพื่อให้การเปลี่ยนผ่านระหว่างวิทยุและแอพอื่น ๆ ที่แสดงในสื่อเป็นไปอย่างราบรื่น ไลบรารี car-media-common จึงประกอบด้วยคลาสที่ควรรวมเข้ากับแอพวิทยุ MediaAppSelectorWidget
สามารถรวมไว้ใน XML สำหรับแอปวิทยุ (ไอคอนและเมนูแบบเลื่อนลงที่ใช้ในสื่ออ้างอิงและแอปวิทยุ):
<com.android.car.media.common.MediaAppSelectorWidget android:id="@+id/app_switch_container" android:layout_width="@dimen/app_switch_widget_width" android:layout_height="wrap_content" android:background="@drawable/app_item_background" android:gravity="center" />
วิดเจ็ตนี้เปิดตัว AppSelectionFragment
ซึ่งแสดงรายการแหล่งสื่อที่สามารถเปลี่ยนมาใช้ได้ หากต้องการ UI อื่นนอกเหนือจากที่ให้มา คุณสามารถสร้างวิดเจ็ตแบบกำหนดเองเพื่อเปิดใช้ AppSelectionFragment
เมื่อควรแสดงตัวสลับ
AppSelectionFragment newFragment = AppSelectionFragment.create(widget, packageName, fullScreen); newFragment.show(mActivity.getSupportFragmentManager(), null);
การใช้งานตัวอย่างมีอยู่ในการใช้งานแอปวิทยุอ้างอิง ซึ่งอยู่ใน packages/apps/Car/Radio
ข้อกำหนดการควบคุมโดยละเอียด
อินเทอร์เฟซ MediaSession
(ผ่าน MediaSession.Callback
) ให้กลไกการควบคุมสำหรับรายการวิทยุที่กำลังเล่นอยู่:
-
onPlay
,onStop
. (ยกเลิก) ปิดเสียงการเล่นวิทยุ -
onPause
การหยุดชั่วคราวแบบเลื่อนเวลา (หากรองรับ) -
onPlayFromMediaId
เล่นเนื้อหาใดๆ จากโฟลเดอร์ระดับบนสุด เช่น "เปิด FM" หรือ "เปิดวิทยุ" -
onPlayFromUri
เล่นความถี่เฉพาะ เช่น "เปิด 88.5 FM" -
onSkipToNext
,onSkipToPrevious
ปรับไปยังสถานีถัดไปหรือก่อนหน้า -
onSetRating
เพิ่มหรือลบออกจากรายการโปรด
MediaBrowser เปิดเผย MediaItem ที่ปรับแต่งได้เหนือไดเร็กทอรีระดับบนสุดสามประเภท:
- ( ไม่บังคับ ) โปรแกรม (สถานี) โดยทั่วไปโหมดนี้จะใช้โดยวิทยุแบบจูนเนอร์คู่เพื่อระบุสถานีวิทยุที่จูนได้ทั้งหมดที่มีในตำแหน่งของผู้ใช้
- รายการโปรด รายการวิทยุที่เพิ่มเข้าไปในรายการโปรด บางรายการอาจไม่สามารถใช้ได้ (อยู่นอกขอบเขตการรับสัญญาณ)
- ช่องวงดนตรี. ช่องสัญญาณที่เป็นไปได้ทางกายภาพทั้งหมดในภูมิภาคปัจจุบัน (87.9, 88.1, 88.3, 88.5, 88.7, 88.9, 89.1 และอื่นๆ) ทุกวงดนตรีมีไดเร็กทอรีระดับบนสุดแยกกัน
แต่ละองค์ประกอบในแต่ละโฟลเดอร์เหล่านี้ (AM/FM/โปรแกรม) คือ MediaItem ที่มี URI ที่สามารถใช้กับ MediaSession เพื่อปรับแต่งได้ โฟลเดอร์ระดับบนสุดแต่ละโฟลเดอร์ (AM/FM/Programs) คือ MediaItem พร้อมด้วย mediaId ที่สามารถใช้กับ MediaSession เพื่อทริกเกอร์การเล่น และขึ้นอยู่กับดุลยพินิจของ OEM ตัวอย่างเช่น "เล่น FM" "เล่น AM" และ "เล่นวิทยุ" ล้วนเป็นคำสั่งวิทยุที่ไม่เฉพาะเจาะจงซึ่งใช้ mediaId เพื่อส่งไปยังแอปวิทยุ OEM ขึ้นอยู่กับแอปวิทยุที่จะกำหนดว่าจะเล่นอะไรจากคำขอทั่วไปและรหัสสื่อ
มีเดียเซสชัน
เนื่องจากไม่มีแนวคิดในการหยุดสตรีมการออกอากาศชั่วคราว การดำเนินการเล่น หยุดชั่วคราว และหยุดจึงอาจไม่มีผลกับวิทยุเสมอไป เมื่อใช้วิทยุ การดำเนินการหยุดจะเชื่อมโยงกับการปิดเสียงสตรีม ในขณะที่การเล่นจะเกี่ยวข้องกับการเอาการปิดเสียงออก
เครื่องรับวิทยุ (หรือแอป) บางตัวมีความสามารถในการจำลองการหยุดสตรีมการออกอากาศชั่วคราวโดยการแคชเนื้อหาแล้วเล่นในภายหลัง ในกรณีเช่นนี้ ให้ใช้ onPause
การเล่นจากการกระทำ mediaId และ URI มีวัตถุประสงค์เพื่อปรับไปยังสถานีที่ดึงมาจากอินเทอร์เฟซ MediaBrowser mediaId เป็นสตริงที่กำหนดโดยแอปวิทยุเพื่อกำหนดค่าที่ไม่ซ้ำกัน (ดังนั้น ID ที่กำหนดจะชี้ไปที่รายการเดียวเท่านั้น) และค่าคงที่ (ดังนั้นรายการที่กำหนดจะมี ID เดียวกันตลอดทั้งเซสชัน) เพื่อระบุสถานีที่กำหนด . URI จะเป็นสคีมาที่กำหนดไว้อย่างดี กล่าวโดยสรุปคือ ProgramSelector ในรูปแบบ URI แม้ว่าสิ่งนี้จะรักษาคุณลักษณะ uniquity ไว้ แต่ก็ไม่จำเป็นต้องเสถียร แม้ว่าจะสามารถเปลี่ยนแปลงได้เมื่อสถานีเคลื่อนที่ไปยังความถี่อื่น
ตามการออกแบบ ไม่ได้ใช้ onPlayFromSearch
เป็นความรับผิดชอบของลูกค้า (แอปร่วม) ในการเลือกผลการค้นหาจากแผนผัง MediaBrowser การย้ายความรับผิดชอบนั้นไปยังแอปวิทยุจะช่วยเพิ่มความซับซ้อน ต้องมีสัญญาอย่างเป็นทางการเกี่ยวกับวิธีการแสดงข้อความค้นหาสตริง และส่งผลให้ผู้ใช้ได้รับประสบการณ์ที่ไม่สม่ำเสมอบนแพลตฟอร์มฮาร์ดแวร์ที่แตกต่างกัน
หมายเหตุ: แอปวิทยุไม่มีข้อมูลเพิ่มเติมที่จะเป็นประโยชน์ในการค้นหาชื่อสถานีที่ไม่ได้เปิดเผยต่อไคลเอนต์ผ่านอินเทอร์เฟซ MediaBrowser
การข้ามไปยังสถานีถัดไปหรือก่อนหน้าจะขึ้นอยู่กับบริบทปัจจุบัน:
- เมื่อปรับแอพไปยังสถานีจากรายการโปรด แอพจะสามารถย้ายไปยังสถานีถัดไปจากรายการโปรดได้
- การฟังสถานีจากรายการโปรแกรมอาจส่งผลให้มีการจูนไปยังสถานีถัดไปที่มีอยู่ โดยจัดเรียงตามหมายเลขช่อง
- การฟังช่องใดช่องหนึ่งอาจส่งผลให้ต้องปรับไปยังช่องทางกายภาพถัดไป แม้ว่าจะไม่มีสัญญาณออกอากาศก็ตาม
แอพวิทยุจัดการการกระทำเหล่านี้
การจัดการข้อผิดพลาด
การดำเนินการ TransportControls
(เล่น หยุด และถัดไป) ไม่ได้ให้ข้อเสนอแนะว่าการดำเนินการสำเร็จหรือไม่ วิธีเดียวที่จะระบุข้อผิดพลาดคือตั้งค่าสถานะ MediaSession เป็น STATE_ERROR
พร้อมข้อความแสดงข้อผิดพลาด
แอปวิทยุจะต้องจัดการกับการกระทำเหล่านั้นและดำเนินการหรือตั้งค่าสถานะข้อผิดพลาด หากการดำเนินการคำสั่ง Play ไม่เกิดขึ้นทันที สถานะการเล่นควรเปลี่ยนเป็น STATE_CONNECTING
(ในกรณีของการปรับแต่งโดยตรง) หรือ STATE_SKIPPING_TO_PREVIOUS
หรือ NEXT
ขณะที่คำสั่งกำลังดำเนินการ
ไคลเอนต์ควรดู PlaybackState
และตรวจสอบว่าเซสชันเปลี่ยนโปรแกรมปัจจุบันเป็นสิ่งที่ร้องขอหรือเข้าสู่สถานะข้อผิดพลาด STATE_CONNECTING
ต้องไม่เกิน 30 วินาที อย่างไรก็ตาม การปรับจูนโดยตรงไปยังความถี่ AM/FM ที่กำหนดควรจะทำงานได้เร็วกว่ามาก
เพิ่มและลบรายการโปรด
MediaSession มีการรองรับการให้คะแนน ซึ่งสามารถใช้เพื่อควบคุมรายการโปรด onSetRating
ที่ถูกเรียกด้วยเรตติ้งประเภท RATING_HEART
จะเพิ่มหรือลบสถานีที่ปรับจูนอยู่ในปัจจุบันเข้าหรือออกจากรายการโปรด
ตรงกันข้ามกับค่าที่ตั้งล่วงหน้าแบบเดิม รุ่นนี้ถือว่ารายการโปรดไม่มีการเรียงลำดับและไม่มีขอบเขต เมื่อรายการโปรดที่บันทึกไว้แต่ละรายการถูกจัดสรรให้กับช่องตัวเลข (โดยทั่วไปคือ 1 ถึง 6) ด้วยเหตุนี้ ระบบที่ใช้การตั้งค่าล่วงหน้าจึงเข้ากันไม่ได้กับการดำเนินการ onSetRating
ข้อจำกัดของ MediaSession API คือสามารถเพิ่มหรือลบเฉพาะสถานีที่ปรับจูนอยู่ในปัจจุบันเท่านั้น ตัวอย่างเช่น ต้องเลือกรายการก่อนจึงจะสามารถลบออกได้ นี่เป็นเพียงข้อจำกัดของไคลเอ็นต์ MediaBrowser เช่น แอปที่แสดงร่วม แอปวิทยุไม่ได้ถูกจำกัดในลักษณะเดียวกัน ส่วนนี้เป็นทางเลือกเมื่อแอปไม่รองรับรายการโปรด
มีเดียเบราว์เซอร์
เพื่อแสดงว่าความถี่หรือชื่อช่องทางกายภาพใด (เมื่อปรับช่องสัญญาณตามอำเภอใจซึ่งเหมาะสำหรับเทคโนโลยีวิทยุที่กำหนด) ที่ถูกต้องสำหรับภูมิภาคที่กำหนด ช่อง (ความถี่) ที่ถูกต้องทั้งหมดจะแสดงรายการสำหรับแต่ละแบนด์ ในภูมิภาคสหรัฐอเมริกา มีจำนวนช่อง FM 101 ช่องในช่วง 87.8 ถึง 108.0 MHz (ใช้ระยะห่าง 0.2MHz) และ 117 ช่อง AM ในช่วง 530 ถึง 1700 kHz (ใช้ระยะห่าง 10kHz) เนื่องจากวิทยุ HD ใช้พื้นที่ช่องสัญญาณเดียวกัน จึงไม่แสดงแยกกัน
รายชื่อรายการวิทยุที่มีอยู่ในปัจจุบันไม่ชัดเจน เนื่องจากไม่อนุญาตให้มีรูปแบบการแสดงผล เช่น การจัดกลุ่มตามชุดออกอากาศเสียงโดยตรง (DAB)
รายการในรายการโปรดอาจไม่สามารถปรับได้ เช่น หากโปรแกรมใดโปรแกรมหนึ่งอยู่นอกขอบเขต แอพวิทยุอาจตรวจหรือตรวจไม่พบว่าสามารถปรับรายการล่วงหน้าได้หรือไม่ หากเป็นเช่นนั้น ระบบอาจไม่ทำเครื่องหมายรายการว่าสามารถเล่นได้
ในการระบุโฟลเดอร์ระดับบนสุด จะใช้กลไกเดียวกับที่บลูทูธใช้ นั่นคือชุด Extras ของออบเจ็กต์ MediaDescription
จะมีฟิลด์เฉพาะเครื่องรับ เช่นเดียวกับที่ Bluetooth ทำกับ EXTRA_BT_FOLDER_TYPE
ในกรณีของวิทยุกระจายเสียง สิ่งนี้นำไปสู่การกำหนดฟิลด์ใหม่ต่อไปนี้ใน API สาธารณะ:
-
EXTRA_BCRADIO_FOLDER_TYPE = "android.media.extra.EXTRA_BCRADIO_FOLDER_TYPE"
ค่าใดค่าหนึ่งต่อไปนี้:-
BCRADIO_FOLDER_TYPE_PROGRAMS = 1
โปรแกรมที่มีอยู่ในปัจจุบัน -
BCRADIO_FOLDER_TYPE_FAVORITES = 2
รายการโปรด -
BCRADIO_FOLDER_TYPE_BAND = 3
ช่องทางทางกายภาพทั้งหมดสำหรับวงดนตรีที่กำหนด
ไม่จำเป็นต้องกำหนดฟิลด์ข้อมูลเมตาที่กำหนดเองเฉพาะทางวิทยุ เนื่องจากข้อมูลที่เกี่ยวข้องทั้งหมดเหมาะสมกับรูปแบบ
MediaBrowser.MediaItem
ที่มีอยู่:- ชื่อโปรแกรม (RDS PS, ชื่อบริการ DAB)
MediaDescription.getTitle
- ความถี่เอฟเอ็ม URI (ดู ProgramSelector ) หรือ
MediaDescription.getTitle
(หากรายการอยู่ในโฟลเดอร์BROADCASTRADIO_FOLDER_TYPE_BAND
) - ตัวระบุเฉพาะวิทยุ (RDS PI, DAB SId)
MediaDescription.getMediaUri
แยกวิเคราะห์เป็น ProgramSelector
โดยปกติแล้ว ไม่จำเป็นต้องดึงความถี่ FM สำหรับรายการในรายการปัจจุบันหรือรายการโปรด (เนื่องจากไคลเอ็นต์ควรใช้งานกับรหัสสื่อ) อย่างไรก็ตาม หากจำเป็นต้องเกิดขึ้น (เช่น เพื่อจุดประสงค์ในการแสดงผล) สิ่งนั้นก็จะปรากฏใน URI และสามารถแยกวิเคราะห์เป็น
ProgramSelector
ได้ อย่างไรก็ตาม เราไม่แนะนำให้ใช้ URI เพื่อเลือกรายการภายในเซสชันปัจจุบัน สำหรับรายละเอียด โปรดดูที่ProgramSelector
เพื่อหลีกเลี่ยงปัญหาด้านประสิทธิภาพหรือปัญหาที่เกี่ยวข้องกับเครื่องผูก บริการ MediaBrowser จะต้องรองรับการแบ่งหน้า:
-
EXTRA_PAGE
-
EXTRA_PAGE_SIZE
- พารามิเตอร์เพิ่มเติมสำหรับ
subscribe()
หมายเหตุ: ตามค่าเริ่มต้น การแบ่งหน้าจะถูกนำไปใช้ตามค่าเริ่มต้นในตัวแปร
onLoadChildren()
โดยไม่มีการจัดการตัวเลือกรายการที่เกี่ยวข้องจากรายการทุกประเภท (ช่องดิบ โปรแกรมที่พบ และรายการโปรด) อาจมีรหัสสื่อที่แตกต่างกัน (ขึ้นอยู่กับแอปวิทยุ ไลบรารีสนับสนุนจะมีความแตกต่างกัน) URI (ในรูปแบบ ProgramSelector) จะแตกต่างกันระหว่างช่อง Raw และโปรแกรมที่พบในกรณีส่วนใหญ่ (ยกเว้น FM ที่ไม่มี RDS) แต่ส่วนใหญ่จะเหมือนกันระหว่างโปรแกรมที่พบและรายการโปรด (ยกเว้น ตัวอย่างเช่น เมื่ออัปเดต AF)
การมีรหัสสื่อที่แตกต่างกันสำหรับรายการจากรายการประเภทต่างๆ ทำให้สามารถดำเนินการกับรายการเหล่านั้นที่แตกต่างกันได้ คุณสามารถสำรวจรายการโปรดหรือรายการโปรแกรมทั้งหมดบน
onSkipToNext
ขึ้นอยู่กับโฟลเดอร์ของMediaItem
ที่เลือกล่าสุด (ดู MediaSession )การดำเนินการปรับแต่งพิเศษ
รายการโปรแกรมทำให้ผู้ใช้สามารถจูนสถานีเฉพาะได้ แต่ไม่อนุญาตให้ผู้ใช้ส่งคำขอทั่วไป เช่น "จูนเป็น FM" ซึ่งอาจส่งผลให้จูนสถานีที่ฟังล่าสุดบนแถบความถี่ FM
เพื่อรองรับการดำเนินการดังกล่าว ไดเรกทอรีระดับบนสุดบางแห่งจึงมีการตั้งค่าสถานะ
FLAG_PLAYABLE
(พร้อมกับFLAG_BROWSABLE
สำหรับโฟลเดอร์)การกระทำ ปรับแต่งเพื่อ วิธีการออก เล่นวิทยุ วิทยุช่องใดก็ได้ startService(ACTION_PLAY_BROADCASTRADIO)
หรือ
playFromMediaId(MediaBrowser. getRoot() )
เล่นเอฟเอ็ม ช่อง FM ใดก็ได้ เล่นจาก mediaId
ของวง FMการตัดสินใจว่าจะจูนโปรแกรมใดนั้นขึ้นอยู่กับแอพ โดยทั่วไปจะเป็นช่องที่ปรับล่าสุดจากรายการที่กำหนด สำหรับรายละเอียดเกี่ยวกับ
ACTION_PLAY_BROADCASTRADIO
โปรดดู จุดประสงค์ในการเล่นทั่วไปการค้นพบและการเชื่อมต่อบริการ
PackageManager
สามารถค้นหา MediaBrowserService ที่ให้บริการแผนผังวิทยุกระจายเสียงได้โดยตรง ในการดำเนินการดังกล่าว ให้เรียกresolveService
ด้วยความตั้งใจACTION_PLAY_BROADCASTRADIO
(ดู ความตั้งใจในการเล่นทั่วไป ) และการตั้งค่าสถานะMATCH_SYSTEM_ONLY
หากต้องการค้นหาบริการทั้งหมดที่ให้บริการวิทยุ (อาจมีมากกว่าหนึ่งบริการ เช่น แยก AM/FM และดาวเทียม) ให้ใช้queryIntentServices
บริการที่ได้รับการแก้ไขจะจัดการเจตนาการผูก
android.media.browse.MediaBrowserService
เช่นกัน สิ่งนี้ได้รับการตรวจสอบด้วย GTSหากต้องการเชื่อมต่อกับ MediaBrowserService ที่เลือก ให้ สร้าง อินสแตนซ์
MediaBrowser
สำหรับส่วนประกอบบริการที่กำหนดและconnect
หลังจากสร้างการเชื่อมต่อแล้ว สามารถรับหมายเลขอ้างอิงของ MediaSession ได้ผ่านgetSessionToken
แอป Radio สามารถจำกัดแพ็คเกจไคลเอนต์ที่อนุญาตให้เชื่อมต่อในการใช้บริการ
onGetRoot
แอปควรอนุญาตให้แอประบบเชื่อมต่อโดยไม่ต้องอยู่ในรายการที่อนุญาตพิเศษ สำหรับรายละเอียดเกี่ยวกับการอนุญาตพิเศษ โปรดดูที่ ยอมรับแพ็คเกจแอพ Assistant และลายเซ็นหากมีการติดตั้งแอปเฉพาะแหล่งที่มา (เช่น แอปวิทยุ) บนอุปกรณ์ที่ไม่มีการสนับสนุนแหล่งที่มาดังกล่าว แอปจะยังคงโฆษณาตัวเองว่าจัดการจุดประสงค์
ACTION_PLAY_BROADCASTRADIO
แต่แผนผัง MediaBrowser จะไม่มีแท็กเฉพาะวิทยุ ดังนั้น ลูกค้าที่ต้องการตรวจสอบว่ามีแหล่งที่มาบนอุปกรณ์หรือไม่ จะต้อง:- ค้นหาบริการวิทยุ (โทร
resolveService
สำหรับACTION_PLAY_BROADCASTRADIO
) - สร้าง
MediaBrowser
แล้วเชื่อมต่อกับมัน - ตรวจสอบว่า
MediaItem
มีEXTRA_BCRADIO_FOLDER_TYPE
พิเศษหรือไม่
หมายเหตุ: ในกรณีส่วนใหญ่ ไคลเอนต์จะต้องสแกนแผนผัง MediaBrowser ที่มีอยู่ทั้งหมดเพื่อตรวจหาแหล่งที่มาที่มีอยู่ทั้งหมดสำหรับอุปกรณ์ที่กำหนด
ชื่อวง
รายชื่อวงดนตรีแสดงโดยชุดของไดเร็กทอรีระดับบนสุดพร้อมแท็กประเภทโฟลเดอร์ที่ตั้งค่าเป็น
BCRADIO_FOLDER_TYPE_BAND
ชื่อของMediaItem
เป็นสตริงที่แปลเป็นภาษาท้องถิ่นซึ่งแสดงถึงชื่อวงดนตรี ในกรณีส่วนใหญ่จะเหมือนกับการแปลภาษาอังกฤษ แต่ลูกค้าไม่สามารถพึ่งพาสมมติฐานดังกล่าวได้เพื่อให้กลไกที่มั่นคงในการค้นหาวงดนตรีบางวง จึงได้มีการเพิ่มแท็กพิเศษสำหรับโฟลเดอร์วงดนตรี
EXTRA_BCRADIO_BAND_NAME_EN
นี่คือชื่อแบนด์ที่ไม่ได้แปลเป็นภาษาท้องถิ่น และสามารถรับค่าที่กำหนดไว้ล่วงหน้าได้เพียงค่าใดค่าหนึ่งเท่านั้น:-
AM
-
FM
-
DAB
หากวงดนตรีไม่อยู่ในรายการนี้ ไม่ควรตั้งป้ายชื่อวงดนตรี อย่างไรก็ตามหากวงดนตรีอยู่ในรายการก็จะต้องมีชุดแท็ก วิทยุ HD ไม่ได้ระบุแบนด์แยกเนื่องจากใช้สื่อพื้นฐานเดียวกันกับ AM/FM
ความตั้งใจในการเล่นทั่วไป
แต่ละแอปสำหรับเล่นแหล่งที่กำหนดโดยเฉพาะ (เช่น วิทยุหรือซีดี) จะต้องจัดการกับจุดประสงค์ ในการเล่น ทั่วไปเพื่อเริ่มเล่นเนื้อหาบางส่วนที่อาจมาจากสถานะไม่ใช้งาน (เช่น หลังบูต) ขึ้นอยู่กับแอปว่าจะเลือกเนื้อหาที่จะเล่นอย่างไร แต่โดยปกติแล้วจะเป็นรายการวิทยุหรือแทร็กซีดีที่เพิ่งเล่น มีจุดประสงค์ที่แยกจากกันที่กำหนดไว้สำหรับแหล่งที่มาของเสียงแต่ละแหล่ง:
-
android.car.intent.action.PLAY_BROADCASTRADIO
-
android.car.intent.action.PLAY_AUDIOCD
: CD-DA หรือ CD-Text -
android.car.intent.action.PLAY_DATADISC
: แผ่นดิสก์ข้อมูลออปติคัลเช่น CD/DVD แต่ไม่ใช่ CD-DA (อาจเป็นซีดีโหมดผสม) -
android.car.intent.action.PLAY_AUX
: โดยไม่ระบุว่าพอร์ต AUX ใด -
android.car.intent.action.PLAY_BLUETOOTH
-
android.car.intent.action.PLAY_USB
: โดยไม่ระบุว่าอุปกรณ์ USB ใด -
android.car.intent.action.PLAY_LOCAL
: ที่เก็บข้อมูลสื่อในเครื่อง (แฟลชในตัว)
Intents ถูกเลือกเพื่อใช้สำหรับคำสั่งการเล่นทั่วไป เนื่องจากจะช่วยแก้ปัญหาสองประการพร้อมกัน: คำสั่งการเล่นทั่วไปและการค้นหาบริการ ประโยชน์เพิ่มเติมของการมีเจตนาดังกล่าวคือความเป็นไปได้ในการดำเนินการง่ายๆ ดังกล่าวโดยไม่ต้องเปิดเซสชัน MediaBrowser
การค้นพบบริการเป็นปัญหาที่สำคัญกว่าซึ่งแก้ไขได้ด้วยจุดประสงค์เหล่านี้ ขั้นตอนการค้นหาบริการทำได้ง่ายและชัดเจนด้วยวิธีนี้ (ดู การค้นพบและการเชื่อมต่อบริการ )
เพื่อให้การใช้งานไคลเอ็นต์บางอย่างง่ายขึ้น มีวิธีอื่นในการออกคำสั่ง Play ดังกล่าว (ซึ่งต้องใช้งานโดยแอปวิทยุด้วย): การออก
playFromMediaId
ด้วย rootId ของโหนดรูท (ใช้เป็น mediaId) แม้ว่า โหนดรูท ไม่ได้หมายถึงให้เล่นได้ แต่ rootId ของโหนดนั้นเป็นสตริงที่กำหนดเองซึ่งสามารถทำให้สามารถใช้เป็น mediaId ได้ อย่างไรก็ตาม ลูกค้าไม่จำเป็นต้องเข้าใจความแตกต่างนี้ตัวเลือกโปรแกรม
แม้ว่า
mediaId
จะเพียงพอที่จะเลือกช่องจากMediaBrowserService
แต่ก็เชื่อมโยงกับเซสชันและไม่สอดคล้องกันระหว่างผู้ให้บริการ ในบางกรณี ไคลเอนต์อาจต้องใช้ตัวชี้ที่แน่นอน (เช่น ความถี่สัมบูรณ์) เพื่อรักษาไว้ระหว่างเซสชันและอุปกรณ์ในยุคของการออกอากาศวิทยุดิจิทัล ความถี่เปล่าไม่เพียงพอที่จะปรับไปยังสถานีเฉพาะ ดังนั้น ให้ใช้
ProgramSelector
เพื่อปรับช่องสัญญาณอนาล็อกหรือดิจิตอลProgramSelector
ประกอบด้วยสองส่วน:- ตัวระบุหลัก ตัวระบุที่ไม่ซ้ำกันและมีเสถียรภาพสำหรับสถานีวิทยุที่กำหนดซึ่งไม่มีการเปลี่ยนแปลงแต่อาจไม่เพียงพอที่จะปรับไปยังสถานีนั้น ตัวอย่างเช่น รหัส RDS PI ซึ่งอาจแปลเป็นสัญญาณเรียกขานในสหรัฐอเมริกา
- ตัวระบุรอง ตัวระบุเพิ่มเติมที่เป็นประโยชน์สำหรับการจูนไปยังสถานีนั้น (เช่น ความถี่) อาจรวมถึงตัวระบุจากเทคโนโลยีวิทยุอื่นๆ ตัวอย่างเช่น สถานี DAB อาจมีทางเลือกในการออกอากาศแบบอะนาล็อก
หากต้องการเปิดใช้งาน
ProgramSelector
ให้พอดีกับโซลูชันที่ใช้MediaBrowser
หรือMediaSession
ให้กำหนดสคีมา URI เพื่อทำให้เป็นอนุกรม สคีมาถูกกำหนดดังนี้:broadcastradio://program/<primary ID type>/<primary ID>? <secondary ID type>=<secondary ID>&<secondary ID type>=<secondary ID>
ในตัวอย่างนี้ ส่วนตัวระบุรอง (หลังเครื่องหมายคำถาม (
?
)) เป็นทางเลือกและสามารถลบออกได้เพื่อให้ตัวระบุที่เสถียรสำหรับใช้เป็นmediaId
ตัวอย่างเช่น:-
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=88500&AMFM_FREQUENCY=103300
-
broadcastradio://program/AMFM_FREQUENCY/102100
-
broadcastradio://program/DAB_SID_EXT/14895264?RDS_PI=1234
ส่วนอำนาจ (โฮสต์ AKA) ของ
program
ให้พื้นที่บางส่วนสำหรับการขยายโครงการในอนาคต สตริงประเภทตัวระบุได้รับการระบุอย่างแม่นยำเป็นชื่อในคำจำกัดความ HAL 2.x ของIdentifierType
และรูปแบบของค่าเป็นตัวเลขทศนิยมหรือเลขฐานสิบหก (พร้อมคำนำหน้า0x
)ตัวระบุเฉพาะผู้ขายทั้งหมดจะแสดงด้วยคำนำหน้า
VENDOR_
ตัวอย่างเช่นVENDOR_0
สำหรับVENDOR_START
และVENDOR_1
สำหรับVENDOR_START
บวก 1 URI ดังกล่าวเป็นข้อมูลเฉพาะสำหรับฮาร์ดแวร์วิทยุที่ใช้สร้างขึ้น และไม่สามารถถ่ายโอนระหว่างอุปกรณ์ที่ผลิตโดย OEM ที่แตกต่างกันได้ต้องกำหนด URI เหล่านี้ให้กับแต่ละรายการ MediaItem ภายใต้โฟลเดอร์วิทยุระดับบนสุด นอกจากนี้ MediaSession จะต้องรองรับทั้ง
playFromMediaId
และplayFromUri
อย่างไรก็ตาม URI มีวัตถุประสงค์หลักสำหรับการดึงข้อมูลเมตาของวิทยุ (เช่น ความถี่ FM) และการจัดเก็บข้อมูลถาวร ไม่มีการรับประกันว่า URI จะพร้อมใช้งานสำหรับรายการสื่อทั้งหมด (เช่น เมื่อเฟรมเวิร์กยังไม่รองรับประเภท ID หลัก) ในทางกลับกัน Media ID จะใช้งานได้เสมอ ไม่แนะนำ ให้ไคลเอ็นต์ใช้ URI เพื่อเลือกรายการจากเซสชัน MediaBrowser ปัจจุบัน ให้ใช้playFromMediaId
แทน อย่างไรก็ตาม นี่ไม่ใช่ทางเลือกสำหรับแอปที่ให้บริการ และ URI ที่ขาดหายไปจะสงวนไว้สำหรับกรณีที่สมเหตุสมผลการออกแบบเริ่มต้นใช้โคลอนเดี่ยวแทนลำดับ
://
หลังส่วนของโครงร่าง อย่างไรก็ตามandroid.net.Uri
แบบแรกไม่รองรับการอ้างอิง URI แบบลำดับชั้นแบบสัมบูรณ์แหล่งที่มาประเภทอื่นๆ
แหล่งเสียงอื่นๆ ก็สามารถจัดการได้เช่นเดียวกัน ตัวอย่างเช่นอินพุตเสริมและเครื่องเล่นซีดีเพลง
แอปเดียวอาจให้บริการแหล่งที่มาหลายประเภท ในกรณีเช่นนี้ ขอแนะนำให้ คุณสร้าง MediaBrowserService แยกต่างหากสำหรับแหล่งที่มาแต่ละประเภท แม้จะอยู่ในการตั้งค่าที่มีแหล่งที่มา/MediaBrowserServices ที่ให้บริการหลายแหล่ง ขอแนะนำอย่างยิ่ง ให้มี MediaSession เดียวภายในแอปเดียว
ซีดีเพลง
เช่นเดียวกับซีดีเพลงตรงที่แอปที่ให้บริการดิสก์ดังกล่าวจะเปิดเผย MediaBrowser ด้วยรายการเดียวที่สามารถเรียกดูได้ (หรือมากกว่านั้นหากระบบมีเครื่องเปลี่ยนซีดี) ซึ่งจะมีแทร็กทั้งหมดของซีดีที่กำหนด หากระบบไม่มีความรู้เกี่ยวกับแทร็กในซีดีทุกแผ่น (เช่น เมื่อใส่ดิสก์ทั้งหมดลงในคาร์ทริดจ์พร้อมกันแต่ไม่ได้อ่านทั้งหมด) ดังนั้น MediaItem สำหรับทั้งดิสก์ก็จะเป็นเพียง
PLAYABLE
เท่านั้น ไม่ใช่BROWSABLE
และPLAYABLE
หากไม่มีดิสก์ในช่องที่กำหนด รายการนั้นจะไม่PLAYABLE
หรือBROWSABLE
(แต่แต่ละช่องจะต้องแสดงอยู่ในแผนผังเสมอ)รายการเหล่านี้จะถูกทำเครื่องหมายในลักษณะเดียวกับที่โฟลเดอร์วิทยุกระจายเสียงคือ โดยจะมีช่องเพิ่มเติมเพิ่มเติมที่กำหนดไว้ใน MediaDescription API:
-
EXTRA_CD_TRACK
: สำหรับMediaItem
ทุกรายการใน Audio CD หมายเลขแทร็กแบบ 1 -
EXTRA_CD_DISK
: หมายเลขดิสก์แบบ 1
สำหรับระบบที่เปิดใช้งานข้อความซีดีและดิสก์ที่เข้ากันได้ MediaItem ระดับบนสุดจะมีชื่อของดิสก์ ในทำนองเดียวกัน MediaItems สำหรับแทร็กก็จะมีชื่อของแทร็ก
อินพุตเสริม
แอปที่ทำหน้าที่อินพุตเสริมจะแสดงแผนผัง MediaBrowser ด้วยรายการเดียว (หรือมากกว่านั้น เมื่อมีพอร์ตหลายพอร์ต) ซึ่งแสดงถึงพอร์ต AUX ใน MediaSession ที่เกี่ยวข้องจะใช้ mediaId และสลับไปยังแหล่งที่มานั้นหลังจากได้รับคำขอ
playFromMediaId
รายการ AUX MediaItem แต่ละรายการจะมีช่องพิเศษ
EXTRA_AUX_PORT_NAME
ที่ตั้งค่าเป็นชื่อพอร์ตที่ไม่ได้แปลเป็นภาษาท้องถิ่นโดยไม่มีวลี "AUX" ตัวอย่างเช่น "AUX 1" จะต้องตั้งค่าเป็น "1", "AUX front" เป็น "front" และ "AUX" เป็นสตริงว่าง ในภาษาที่ไม่ใช่ภาษาอังกฤษ แท็กชื่อจะยังคงเป็นสตริงภาษาอังกฤษเดียวกัน ไม่น่าจะเป็นไปได้สำหรับEXTRA_BCRADIO_BAND_NAME_EN
ค่าต่างๆ ถูกกำหนดโดย OEM และไม่จำกัดเฉพาะรายการที่กำหนดไว้ล่วงหน้าหากฮาร์ดแวร์ตรวจพบอุปกรณ์ที่เชื่อมต่อกับพอร์ต AUX ฮาร์ดแวร์ควรทำเครื่องหมาย MediaItem เป็น
PLAYABLE
เฉพาะในกรณีที่เชื่อมต่ออินพุตแล้วเท่านั้น ฮาร์ดแวร์ควรยังคงได้รับการแจกแจง (แต่ไม่ใช่PLAYABLE
) หากไม่มีสิ่งใดเชื่อมต่อกับพอร์ตนี้ หากฮาร์ดแวร์ไม่มีความสามารถดังกล่าว MediaItem จะต้องตั้งค่าเป็นPLAYABLE
เสมอช่องพิเศษ
กำหนดฟิลด์ต่อไปนี้:
-
EXTRA_CD_TRACK = "android.media.extra.CD_TRACK"
-
EXTRA_CD_DISK = "android.media.extra.CD_DISK"
-
EXTRA_AUX_PORT_NAME = "android.media.extra.AUX_PORT_NAME"
ลูกค้าจำเป็นต้องตรวจสอบ MediaItems ระดับบนสุดเพื่อหาองค์ประกอบที่มีการตั้งค่าช่องพิเศษ
EXTRA_CD_DISK
หรือEXTRA_AUX_PORT_NAME
ตัวอย่างโดยละเอียด
ตัวอย่างต่อไปนี้กล่าวถึงโครงสร้างแผนผัง MediaBrowser สำหรับประเภทแหล่งที่มาที่เป็นส่วนหนึ่งของการออกแบบนี้
วิทยุกระจายเสียง MediaBrowserService (จัดการ
ACTION_PLAY_BROADCASTRADIO
):- สถานี (เรียกดูได้)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_PROGRAMS
- BBC One (เล่นได้) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=90500
- ABC 88.1 (เล่นได้) URI:
broadcastradio://program/RDS_PI/5678?AMFM_FREQUENCY=88100
- ABC 88.1 HD1 (เล่นได้) URI:
broadcastradio://program/HD_STATION_ID_EXT/158241DEADBEEF?AMFM_FREQUENCY=88100&RDS_PI=5678
- ABC 88.1 HD2 (เล่นได้) URI:
broadcastradio://program/HD_STATION_ID_EXT/158242DEADBEFE
- 90.5 FM (เล่นได้) - FM ที่ไม่มี RDSURI:
broadcastradio://program/AMFM_FREQUENCY/90500
- 620 AM (เล่นได้) URI:
broadcastradio://program/AMFM_FREQUENCY/620
- BBC One (เล่นได้) URI:
broadcastradio://program/DAB_SID_EXT/1E24102?RDS_PI=1234
- BBC One (เล่นได้) URI:
- รายการโปรด (เรียกดูได้ เล่นได้)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_FAVORITES
- BBC One (เล่นได้) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=101300
- BBC Two (เล่นไม่ได้) URI:
broadcastradio://program/RDS_PI/1300?AMFM_FREQUENCY=102100
- BBC One (เล่นได้) URI:
- AM (เรียกดูและเล่นได้):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="AM"
- 530 AM (เล่นได้) URI:
broadcastradio://program/AMFM_FREQUENCY/530
- 540 AM (เล่นได้) URI:
broadcastradio://program/AMFM_FREQUENCY/540
- 550 AM (เล่นได้) URI:
broadcastradio://program/AMFM_FREQUENCY/550
- 530 AM (เล่นได้) URI:
- FM (เรียกดูและเล่นได้):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="FM"
- 87.7 FM (เล่นได้) URI:
broadcastradio://program/AMFM_FREQUENCY/87700
- 87.9 FM (เล่นได้) URI:
broadcastradio://program/AMFM_FREQUENCY/87900
- 88.1 FM (เล่นได้) URI:
broadcastradio://program/AMFM_FREQUENCY/88100
- 87.7 FM (เล่นได้) URI:
- DAB (เล่นได้):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="DAB"
ซีดีเพลง MediaBrowserService (จัดการ
ACTION_PLAY_AUDIOCD
):- ดิสก์ 1 (เล่นได้)
EXTRA_CD_DISK=1
- ดิสก์ 2 (เรียกดูและเล่นได้)
EXTRA_CD_DISK=2
- แทร็ก 1 (เล่นได้)
EXTRA_CD_TRACK=1
- แทร็ก 2 (เล่นได้)
EXTRA_CD_TRACK=2
- แทร็ก 1 (เล่นได้)
- ซีดีเพลงของฉัน (เรียกดูและเล่นได้)
EXTRA_CD_DISK=3
- ทั้งหมดด้วยตัวเอง (เล่นได้)
EXTRA_CD_TRACK=1
- ไรซ์ ไรซ์ (เล่นได้)
EXTRA_CD_TRACK=2
- ทั้งหมดด้วยตัวเอง (เล่นได้)
- ช่องว่าง 4 (เล่นไม่ได้)
EXTRA_CD_DISK=4
AUX MediaBrowserService (จัดการ
ACTION_PLAY_AUX
):- AUX ด้านหน้า (เล่นได้)
EXTRA_AUX_PORT_NAME="front"
- AUX ด้านหลัง (เล่นได้)
EXTRA_AUX_PORT_NAME="rear"
-