ดำเนินการวิทยุ

หน้านี้อธิบายวิธีการใช้วิทยุในระดับฮาร์ดแวร์และซอฟต์แวร์

ส่วนประกอบของระบบ

สแต็กวิทยุกระจายเสียงประกอบด้วยส่วนประกอบต่อไปนี้

สถาปัตยกรรมวิทยุกระจายเสียง
รูปที่ 1 สถาปัตยกรรมวิทยุกระจายเสียง

แอพอ้างอิงวิทยุ

สำหรับรายละเอียดเกี่ยวกับวิธีการใช้งานการควบคุมด้วยวิทยุ โปรดดูที่ การใช้งานการควบคุมด้วยวิทยุ

แอปวิทยุ 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)
คำอธิบาย:
  • HIDL HAL: เมื่อมีการเปิดเซสชันจูนเนอร์ใหม่ เซสชันเก่าจะต้องถูกยกเลิก
  • AIDL HAL: เนื่องจากไม่มีเซสชันเครื่องรับจึงจำเป็นต้องตั้งค่าเฉพาะการเรียกกลับเครื่องรับเท่านั้น หากมีอยู่ ควรยกเลิกการตั้งค่าการโทรกลับเก่า
HIDL2.0 openSession(ITunerCallback callback) สร้างขึ้น (Result result, ITunerSession session)
โรคเอดส์ void setTunerCallback(in ITunerCallback callback)
คำอธิบาย:
  • HIDL HAL: การปิดเซสชันจูนเนอร์จะต้องไม่ล้มเหลวและจะต้องออกเพียงครั้งเดียวเท่านั้น
  • AIDL HAL: ไม่มีจูนเนอร์และต้องยกเลิกการตั้งค่าการโทรกลับของจูนเนอร์เท่านั้น
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 int TUNER_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 และอื่นๆ) ทุกวงดนตรีมีไดเร็กทอรีระดับบนสุดแยกกัน
โครงสร้างแผนผัง MediaBrowserService
รูปที่ 2 โครงสร้างแผนผัง MediaBrowserService

แต่ละองค์ประกอบในแต่ละโฟลเดอร์เหล่านี้ (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 จะต้องรองรับการแบ่งหน้า:

    หมายเหตุ: ตามค่าเริ่มต้น การแบ่งหน้าจะถูกนำไปใช้ตามค่าเริ่มต้นในตัวแปร 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 จะไม่มีแท็กเฉพาะวิทยุ ดังนั้น ลูกค้าที่ต้องการตรวจสอบว่ามีแหล่งที่มาบนอุปกรณ์หรือไม่ จะต้อง:

    1. ค้นหาบริการวิทยุ (โทร resolveService สำหรับ ACTION_PLAY_BROADCASTRADIO )
    2. สร้าง MediaBrowser แล้วเชื่อมต่อกับมัน
    3. ตรวจสอบว่า 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 (แต่แต่ละช่องจะต้องแสดงอยู่ในแผนผังเสมอ)

    โครงสร้างแผนผังซีดีเพลง
    รูปที่ 3 โครงสร้างแผนผังซีดีเพลง

    รายการเหล่านี้จะถูกทำเครื่องหมายในลักษณะเดียวกับที่โฟลเดอร์วิทยุกระจายเสียงคือ โดยจะมีช่องเพิ่มเติมเพิ่มเติมที่กำหนดไว้ใน MediaDescription API:

    • EXTRA_CD_TRACK : สำหรับ MediaItem ทุกรายการใน Audio CD หมายเลขแทร็กแบบ 1
    • EXTRA_CD_DISK : หมายเลขดิสก์แบบ 1

    สำหรับระบบที่เปิดใช้งานข้อความซีดีและดิสก์ที่เข้ากันได้ MediaItem ระดับบนสุดจะมีชื่อของดิสก์ ในทำนองเดียวกัน MediaItems สำหรับแทร็กก็จะมีชื่อของแทร็ก

    อินพุตเสริม

    แอปที่ทำหน้าที่อินพุตเสริมจะแสดงแผนผัง MediaBrowser ด้วยรายการเดียว (หรือมากกว่านั้น เมื่อมีพอร์ตหลายพอร์ต) ซึ่งแสดงถึงพอร์ต AUX ใน MediaSession ที่เกี่ยวข้องจะใช้ mediaId และสลับไปยังแหล่งที่มานั้นหลังจากได้รับคำขอ playFromMediaId

    โครงสร้างต้นไม้AUX
    รูปที่ 4 โครงสร้างแผนผัง AUX

    รายการ 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
    • รายการโปรด (เรียกดูได้ เล่นได้) 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
    • 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
    • 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
    • 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
    • ซีดีเพลงของฉัน (เรียกดูและเล่นได้) 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"