Halaman ini menjelaskan cara mengimplementasikan radio pada tingkat perangkat keras dan perangkat lunak.
- Komponen sistem menggambarkan dan menjelaskan tumpukan teknologi radio.
- Lapisan abstraksi perangkat keras radio siaran (HAL) menyediakan struktur data dan antarmuka bagi OEM untuk mengimplementasikan radio siaran seperti radio AM/FM dan radio penyiaran audio digital (DAB) di tingkat perangkat keras.
- Implementasi kontrol radio didasarkan pada
MediaSession
danMediaBrowse
, yang memungkinkan aplikasi Media dan asisten suara untuk mengontrol radio. Selain konten yang disediakan di bawah, lihat Membuat aplikasi media untuk mobil .
Komponen sistem
Tumpukan radio siaran mencakup komponen berikut.
Aplikasi referensi radio
Untuk detail tentang cara menerapkan kontrol radio, lihat Implementasi kontrol radio .
Contoh aplikasi radio Java ( packages/apps/Car/Radio
) berfungsi sebagai implementasi referensi. Saat layanan aplikasi dimulai, ia meminta Radio Manager untuk membuka Radio Tuner. Kemudian, aplikasi dapat mengirimkan permintaan ke Radio Tuner, seperti menyetel stasiun radio tertentu, frekuensi, atau untuk mencari stasiun radio berikutnya yang tersedia. Aplikasi ini menerima pembaruan dari Manajer Radio dan Penyetel Radio di Radio, seperti informasi program terkini, daftar program radio, konfigurasi, dan parameter yang ditentukan vendor. Aplikasi Radio referensi hanya mendukung radio AM dan FM. OEM dapat memodifikasi atau mengganti aplikasi Radio sesuai keinginan.
Manajer Radio
Ketika aplikasi meminta Radio Manager untuk membuka tuner, Radio Manager ( frameworks/base/core/java/android/hardware/radio/RadioManager.java
) meminta Layanan Radio Siaran untuk membuka sesi Tuner dan kemudian membungkus sesi tersebut dalam sebuah Radio Tuner ( frameworks/base/core/java/android/hardware/radio/RadioTuner.java
), yang dikembalikan ke aplikasi. Radio Tuner mendefinisikan API (seperti menyetel, melangkah, dan membatalkan) yang dapat dipanggil dari aplikasi radio dan mengirim permintaan ke Layanan Radio Siaran. Metode panggilan balik ( RadioTuner.Callback
) yang ditentukan di Radio Tuner mengirimkan pembaruan tentang HAL radio siaran, seperti informasi program terkini, daftar program, dan parameter yang ditentukan vendor, dari Layanan Radio Siaran ke aplikasi.
Layanan Radio Siaran
Layanan Radio Siaran ( frameworks/base/services/core/java/com/android/server/broadcastradio
) adalah layanan klien untuk Radio Siaran HAL. Layanan Radio Siaran mengoordinasikan beberapa Manajer Radio dengan HAL Radio Siaran. Layanan Radio Siaran mendukung bahasa definisi antarmuka HAL (HIDL) dan bahasa definisi antarmuka Android (AIDL) yang menyiarkan HAL radio. Layanan Radio Siaran terhubung ke AIDL HAL ketika ada layanan AIDL HAL; jika tidak, layanan akan terhubung ke HIDL HAL. Layanan Radio Siaran membuat Modul Radio untuk setiap instans HAL yang tersedia (seperti AM, FM, dan DAB).
Setiap Manajer Radio dapat meminta Layanan Radio Siaran untuk membuat sesi tuner pada Modul Radio yang sesuai, berdasarkan jenis radionya. Setiap sesi tuner dapat memanggil metode, seperti menyetel, melangkah, dan membatalkan (didefinisikan dalam antarmuka HAL) untuk melakukan operasi pada instans radio siaran HAL yang sesuai. Ketika satu sesi tuner menerima panggilan balik dari instans HAL pada pembaruan HAL, seperti info program saat ini, daftar program, tanda konfigurasi, dan parameter vendor, panggilan balik tentang pembaruan dikirim ke semua Radio Tuner yang terhubung ke Modul Radio yang sama.
Siaran radio HAL
Untuk mempelajari lebih lanjut tentang antarmuka HIDL dan AIDL pada radio siaran dan perbedaan antara keduanya, lihat Antarmuka HAL radio siaran .
Lapisan abstraksi perangkat keras radio siaran
Bagian berikut menjelaskan cara bekerja dengan lapisan abstraksi perangkat keras (HAL) untuk mengimplementasikan radio siaran.
Antarmuka HAL radio siaran
Radio siaran HAL menyediakan struktur data dan antarmuka di tingkat perangkat keras untuk mengimplementasikan radio siaran, seperti radio AM/FM dan DAB.
Antarmuka HIDL 2.0 dan AIDL
Radio siaran HAL menggunakan antarmuka yang dijelaskan di bagian berikut.
Pendengar pengumuman
IAnnouncementListener
adalah antarmuka panggilan balik untuk pendengar pengumuman, yang dapat didaftarkan di radio siaran HAL untuk menerima pengumuman. Antarmuka memiliki metode berikut:
IAnnouncementListener | ||
---|---|---|
Deskripsi: Dipanggil setiap kali daftar pengumuman berubah. | ||
MENYEMBUNYIKAN 2.0 | oneway onListUpdated(vec<Announcement> announcements) | |
AIDL | oneway void onListUpdated(in Announcement[] announcements) |
Tutup pegangannya
ICloseHandle
adalah pegangan tutup umum untuk menghapus panggilan balik yang tidak memerlukan antarmuka aktif.
ICcloseHandle | ||
---|---|---|
Deskripsi: Tutup pegangannya. | ||
MENYEMBUNYIKAN 2.0 | close() | |
AIDL | void close() |
Antarmuka panggilan balik
ITunerCallback
adalah antarmuka panggilan balik yang dipanggil oleh radio siaran HAL untuk mengirim pembaruan ke layanan klien HAL.
Panggilan Balik ITuner | ||
---|---|---|
Deskripsi: Dipanggil oleh HAL ketika operasi penyetelan (tune, seek (dalam AIDL) atau scan (dalam HIDL) dan langkah berhasil) gagal secara asinkron. | ||
MENYEMBUNYIKAN 2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Deskripsi: Dipanggil ketika pencarian, pencarian (dalam AIDL) atau pemindaian (dalam HIDL), atau langkah berhasil. | ||
MENYEMBUNYIKAN 2.0 | oneway onTuneFailed(Result result, ProgramSelector selector) | |
AIDL | void onTuneFailed(in Result result, in ProgramSelector selector) | |
Deskripsi: Dipanggil ketika pencarian, pencarian (dalam AIDL) atau pemindaian (dalam HIDL), atau langkah berhasil. | ||
MENYEMBUNYIKAN 2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Deskripsi: Dipanggil ketika daftar program diperbarui; ukuran setiap potongan harus dibatasi hingga 500kiB. | ||
MENYEMBUNYIKAN 2.0 | oneway onProgramListUpdated(ProgramListChunk chunk) | |
AIDL | oneway onProgramListUpdated(ProgramListChunk chunk) | |
Deskripsi: Dipanggil ketika antena terhubung atau terputus. | ||
MENYEMBUNYIKAN 2.0 | oneway onAntennaStateChange(bool connected) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Deskripsi: Dipanggil ketika nilai parameter khusus vendor diperbarui secara internal di HAL (tidak boleh dipanggil setelah memanggil setParameters oleh klien HAL). | ||
MENYEMBUNYIKAN 2.0 | oneway onParametersUpdated(vec<VendorKeyValue> parameters) | |
AIDL | void onParametersUpdated(in VendorKeyValue[] parameters) | |
Deskripsi: Baru di AIDL. Dipanggil ketika flag konfigurasi diperbarui secara internal di HAL (tidak boleh dipanggil setelah memanggil setConfigFlag oleh klien HAL). | ||
MENYEMBUNYIKAN 2.0 | Tak dapat diterapkan. | |
AIDL | void onConfigFlagUpdated(in ConfigFlag flag, in boolean value) |
Antarmuka HAL radio siaran utama
IBroadcastRadio
adalah antarmuka utama untuk siaran radio HAL. Di HIDL 2.0 HAL, gunakan antarmuka ITunerSession
ke tuner untuk memanggil operasi. Namun, paling banyak satu tuner aktif pada satu waktu (asalkan setiap instans radio siaran HAL hanya memiliki satu chip tuner). ITunerSession
telah dihapus dari antarmuka AIDL dan antarmukanya dipindahkan ke IBroadcastRadio
.
IBroadcastRadio | ||
---|---|---|
Deskripsi: Dapatkan deskripsi modul dan kemampuannya. | ||
MENYEMBUNYIKAN 2.0 | getProperties() generates (Properties properties) | |
AIDL | Properties getProperties() | |
Deskripsi: Mengambil konfigurasi wilayah AM/FM saat ini atau yang mungkin. | ||
MENYEMBUNYIKAN 2.0 | getAmFmRegionConfig(bool full) generates (Result result, AmFmRegionConfig config) | |
AIDL | AmFmRegionConfig getAmFmRegionConfig(bool full) | |
Deskripsi: Mengambil konfigurasi wilayah DAB saat ini. | ||
MENYEMBUNYIKAN 2.0 | getDabRegionConfig() generates (Result result, vec<DabTableEntry> config) | |
AIDL | DabTableEntry[] getDabRegionConfig() | |
Deskripsi: Mendapatkan gambar dari cache modul radio. Di AIDL, ukuran gambar harus kurang dari 1MB karena adanya batasan ketat pada buffer transaksi pengikat. | ||
MENYEMBUNYIKAN 2.0 | getImage(uint32_t id) generates (vec<uint8_t> image) | |
AIDL | byte[] getImage(in int id) | |
Deskripsi: Mendaftarkan pendengar pengumuman. | ||
MENYEMBUNYIKAN 2.0 | registerAnnouncementListener(vec<AnnouncementType> enabled,IAnnouncementListener listener) generates (Result result, ICloseHandle closeHandle) | |
AIDL | ICloseHandle registerAnnouncementListener(in IAnnouncementListener listener, in AnnouncementType[] enabled) | |
Keterangan:
| ||
MENYEMBUNYIKAN 2.0 | openSession(ITunerCallback callback) menghasilkan (Result result, ITunerSession session) | |
AIDL | void setTunerCallback(in ITunerCallback callback) | |
Keterangan:
| ||
MENYEMBUNYIKAN 2.0 | close() | |
AIDL | unsetTunerCallback() | |
Deskripsi: Menyesuaikan program tertentu. | ||
MENYEMBUNYIKAN 2.0 | tune(ProgramSelector program) generates (Result result) | |
AIDL | void tune(in ProgramSelector program) | |
Deskripsi: Mencari program valid berikutnya yang mengudara . Untuk menghindari kebingungan di AIDL, scan diganti namanya menjadi seek . | ||
MENYEMBUNYIKAN 2.0 | scan(bool directionUp, bool skipSubChannel) generates (Result result) | |
AIDL | void seek(in boolean directionUp, in boolean skipSubChannel) | |
Deskripsi: Langkah menuju saluran yang berdekatan, yang mungkin tidak ditempati oleh program apa pun. | ||
MENYEMBUNYIKAN 2.0 | step(bool directionUp) generates (Result result) | |
AIDL | void step(in boolean directionUp) | |
Deskripsi: Membatalkan operasi penelusuran, pemindaian (dalam HIDL) atau pencarian (dalam AIDL), atau langkah yang tertunda. | ||
MENYEMBUNYIKAN 2.0 | cancel() | |
AIDL | void cancel() | |
Deskripsi: Menerapkan filter ke daftar program dan mulai mengirimkan pembaruan daftar program melalui panggilan balik onProgramListUpdated . | ||
MENYEMBUNYIKAN 2.0 | startProgramListUpdates(ProgramFilter filter) generates (Result result) | |
AIDL | void startProgramListUpdates(in ProgramFilter filter) | |
Deskripsi: Berhenti mengirim pembaruan daftar program. | ||
MENYEMBUNYIKAN 2.0 | stopProgramListUpdates() | |
AIDL | void stopProgramListUpdates() | |
Deskripsi: Mengambil pengaturan saat ini dari tanda konfigurasi tertentu. | ||
MENYEMBUNYIKAN 2.0 | isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value) | |
AIDL | boolean isConfigFlagSet(in ConfigFlag flag) | |
Deskripsi: Menyetel tanda konfigurasi yang diberikan. | ||
MENYEMBUNYIKAN 2.0 | setConfigFlag(ConfigFlag flag, bool value) generates (Result result) | |
AIDL | void setConfigFlag(in ConfigFlag flag, boolean value) | |
Deskripsi: Menetapkan nilai parameter khusus vendor. | ||
MENYEMBUNYIKAN 2.0 | setParameters(vec<VendorKeyValue> parameters) menghasilkan , (vec<VendorKeyValue> results) | |
AIDL | VendorKeyValue[] setParameters(in VendorKeyValue[] parameters) | |
Deskripsi: Mengambil nilai parameter spesifik vendor. | ||
MENYEMBUNYIKAN 2.0 | getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters) | |
AIDL | VendorKeyValue[] getParameters(in String[] keys) |
Klarifikasi antarmuka
Perilaku asinkron
Karena setiap operasi penyetelan (misalnya, penyetelan, pemindaian (dalam HIDL) atau pencarian (dalam AIDL), dan langkah) mungkin memakan waktu dan thread tidak boleh diblokir untuk waktu yang lama, operasi tersebut harus menjadwalkan operasi yang memakan waktu terjadi kemudian dan dengan cepat mengembalikan status atau hasil. Secara rinci, setiap operasi harus:
- Batalkan semua operasi penyetelan yang tertunda.
- Periksa apakah operasi dapat diproses berdasarkan input metode dan status tuner.
- Jadwalkan tugas penyetelan lalu segera kembalikan
Result
(dalam HIDL) ataustatus
(dalam AIDL). JikaResult
ataustatus
OK
, panggilan balik tunertuneFailed
ataucurrentProgramInfoChanged
harus dipanggil ketika tugas penyetelan gagal (misalnya, karena waktu habis) atau selesai.
Demikian pula, startProgramListUpdates
juga menjadwalkan tugas yang memakan waktu untuk memperbarui daftar program agar dilakukan nanti dan dengan cepat mengembalikan status atau hasil. Metode ini pertama-tama membatalkan permintaan pembaruan yang tertunda, lalu menjadwalkan tugas pembaruan dan dengan cepat mengembalikan hasilnya.
Kondisi balapan
Karena perilaku operasi penyetelan yang tidak sinkron (misalnya, penyetelan, pemindaian (dalam HIDL) atau pencarian (dalam AIDL), dan langkah), terdapat kondisi perlombaan antara pembatalan operasi dan operasi penyetelan. Jika cancel
dipanggil setelah HAL menyelesaikan operasi penyetelan dan sebelum panggilan balik selesai, pembatalan dapat diabaikan dan panggilan balik harus selesai dan diterima oleh klien HAL.
Demikian pula, jika stopProgramListUpdates
dipanggil setelah HAL menyelesaikan pembaruan daftar program dan sebelum callback onCurrentProgramInfoChanged
selesai, stopProgramListUpdates
dapat diabaikan dan callback harus selesai.
Batas ukuran data
Karena ada batasan tegas pada buffer transaksi pengikat, batas data untuk beberapa metode antarmuka yang meneruskan data dengan potensi ukuran besar diklarifikasi dalam AIDL HAL.
-
getImage
mengharuskan gambar yang dikembalikan kurang dari 1 MB. -
onProgramListUpdate
mengharuskan setiapchunk
berukuran kurang dari 500kiB. Daftar program yang lebih besar harus dipecah oleh implementasi HAL menjadi beberapa bagian dan dikirim melalui beberapa callback.
Perubahan struktur data AIDL HAL
Selain perubahan antarmuka, perubahan ini juga diterapkan pada struktur data yang ditentukan dalam radio siaran AIDL HAL, yang memanfaatkan AIDL.
- Enum
Constant
dihapus di AIDL dan didefinisikan sebagai const int diIBroadcastRadio
. Sementara itu,ANTENNA_DISCONNECTED_TIMEOUT_MS
diubah namanya menjadiANTENNA_STATE_CHANGE_TIMEOUT_MS
. Const intTUNER_TIMEOUT_MS
baru ditambahkan. Semua operasi penyetelan, pencarian, dan langkah harus diselesaikan dalam waktu ini. - Enum
RDS
danDeemphasis
dihapus di AIDL dan didefinisikan sebagai const int diAmFmRegionConfig
. Sejalan dengan itu,fmDeemphasis
danfmRds
diProgramInfo
dideklarasikan sebagai int, yang merupakan hasil komputasi bit dari masing-masing flag. Sementara itu,D50
danD75
masing-masing diganti namanya menjadiDEEMPHASIS_D50
danDEEMPHASIS_D75
. - Enum
ProgramInfoFlags
dihapus di AIDL dan didefinisikan sebagai const int diProgramInfo
dengan awalanFLAG_
ditambahkan. Sejalan dengan itu,infoFlags
diProgramInfo
dideklarasikan sebagai int, sebuah bit hasil komputasi dari flag.TUNED
juga diganti namanya menjadiFLAG_TUNABLE
, untuk lebih menjelaskan definisi stasiun yang dapat disetel. - Di
AmFmBandRange
,scanSpacing
diganti namanya menjadiseekSpacing
, karenascan
diganti namanya menjadiseek
di AIDL. - Sejak konsep penyatuan diperkenalkan di AIDL,
MetadataKey
danMetadata
yang didefinisikan dalam HIDL HAL tidak lagi digunakan.Metadata
gabungan AIDL didefinisikan dalam AIDL HAL. Setiap nilai enum yang sebelumnya diMetadataKey
sekarang menjadi bidang diMetadata
dengan tipe string atau int, bergantung pada definisinya.
Implementasi kontrol radio
Implementasi kontrol radio didasarkan pada MediaSession
dan MediaBrowse
, yang memungkinkan aplikasi Media dan asisten suara untuk mengontrol radio. Untuk informasi selengkapnya, lihat Membuat aplikasi media untuk mobil di developer.android.com.
Implementasi pohon penelusuran media disediakan di perpustakaan dukungan siaran mobil di packages/apps/Car/libs
. Perpustakaan ini juga berisi ekstensi ProgramSelector untuk mengkonversi ke dan dari URI. Direkomendasikan agar implementasi radio menggunakan perpustakaan ini untuk membangun pohon penelusuran terkait.
Pengalih sumber media
Untuk memberikan transisi yang mulus antara radio dan aplikasi lain yang ditampilkan di media, perpustakaan umum media mobil berisi kelas yang harus diintegrasikan ke dalam aplikasi radio. MediaAppSelectorWidget
dapat disertakan dalam XML untuk aplikasi radio (ikon dan drop-down yang digunakan di media referensi dan aplikasi radio):
<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" />
Widget ini meluncurkan AppSelectionFragment
, yang menampilkan daftar sumber media yang dapat dialihkan. Jika diinginkan UI selain yang disediakan, Anda dapat membuat widget khusus untuk meluncurkan AppSelectionFragment
saat pengalih harus ditampilkan.
AppSelectionFragment newFragment = AppSelectionFragment.create(widget, packageName, fullScreen); newFragment.show(mActivity.getSupportFragmentManager(), null);
Contoh implementasi disediakan dalam implementasi aplikasi radio referensi, yang terletak di packages/apps/Car/Radio
.
Spesifikasi kontrol terperinci
Antarmuka MediaSession
(melalui MediaSession.Callback
) menyediakan mekanisme kontrol untuk program radio yang sedang diputar:
-
onPlay
,onStop
. (Membatalkan) mematikan pemutaran radio. -
onPause
. Jeda waktu-bergeser (jika didukung). -
onPlayFromMediaId
. Memutar konten apa pun dari folder tingkat atas. Misalnya, "Putar FM" atau "Putar Radio". -
onPlayFromUri
. Mainkan frekuensi tertentu. Misalnya, "Putar 88,5 FM". -
onSkipToNext
,onSkipToPrevious
. Dengarkan stasiun berikutnya atau sebelumnya. -
onSetRating
. Menambah atau menghapus ke atau dari Favorit.
MediaBrowser menampilkan MediaItem yang dapat disetel pada tiga jenis direktori tingkat atas:
- ( Opsional ) Program (stasiun). Mode ini biasanya digunakan oleh radio dual-tuner untuk menunjukkan semua stasiun radio yang tersedia dan dapat disetel di lokasi pengguna.
- Favorit. Program radio ditambahkan ke daftar Favorit, beberapa mungkin tidak tersedia (di luar jangkauan penerimaan).
- Saluran pita. Semua saluran yang memungkinkan secara fisik di wilayah saat ini (87.9, 88.1, 88.3, 88.5, 88.7, 88.9, 89.1, dan seterusnya). Setiap band memiliki direktori tingkat atas yang terpisah.
Setiap elemen di setiap folder ini (AM/FM/Program) adalah MediaItem dengan URI yang dapat digunakan dengan MediaSession untuk melakukan penyesuaian. Setiap folder tingkat atas (AM/FM/Program) adalah MediaItem dengan mediaId yang dapat digunakan dengan MediaSession untuk memicu pemutaran dan bergantung pada kebijaksanaan OEM. Misalnya, "Play FM", "Play AM", dan "Play Radio" adalah kueri radio non-spesifik yang menggunakan mediaId untuk dikirim ke aplikasi radio OEM. Aplikasi radiolah yang menentukan apa yang akan diputar dari permintaan umum dan mediaId.
Sesi Media
Mengingat tidak ada konsep menjeda streaming siaran, tindakan Putar, Jeda, dan Hentikan tidak selalu berlaku untuk radio. Dengan radio, tindakan Stop dikaitkan dengan mematikan streaming sementara Play dikaitkan dengan menghilangkan bisu.
Beberapa penyetel radio (atau aplikasi) menyediakan kemampuan untuk menyimulasikan jeda aliran siaran dengan menyimpan konten dalam cache lalu memutarnya kembali nanti. Dalam kasus seperti itu, gunakan onPause
.
Memutar dari tindakan mediaId dan URI dimaksudkan untuk menyetel stasiun yang diambil dari antarmuka MediaBrowser. mediaId adalah string arbitrer yang disediakan oleh aplikasi radio untuk menerapkan nilai unik (sehingga ID tertentu menunjuk ke satu item saja) dan stabil (sehingga item tertentu memiliki ID yang sama di seluruh sesi) yang dapat digunakan untuk mengidentifikasi stasiun tertentu . URI akan memiliki skema yang terdefinisi dengan baik. Singkatnya, bentuk ProgramSelector yang di-URI. Meskipun hal ini mempertahankan atribut keunikannya, namun tidak harus stabil, meskipun dapat berubah ketika stasiun berpindah ke frekuensi yang berbeda.
Secara desain, onPlayFromSearch
tidak digunakan. Adalah tanggung jawab klien (aplikasi pendamping) untuk memilih hasil pencarian dari pohon MediaBrowser. Memindahkan tanggung jawab tersebut ke aplikasi radio akan meningkatkan kompleksitas, memerlukan kontrak formal tentang bagaimana kueri string akan muncul, dan mengakibatkan pengalaman pengguna yang tidak merata pada platform perangkat keras yang berbeda.
Catatan: Aplikasi radio tidak berisi informasi tambahan yang berguna untuk mencari nama stasiun yang tidak diekspos ke klien melalui antarmuka MediaBrowser.
Melewati ke stasiun berikutnya atau sebelumnya bergantung pada konteks saat ini:
- Saat aplikasi disetel ke stasiun dari daftar Favorit, aplikasi tersebut dapat berpindah ke stasiun berikutnya dari daftar Favorit.
- Mendengarkan stasiun dari daftar Program dapat menyebabkan pencarian stasiun berikutnya yang tersedia, diurutkan berdasarkan nomor saluran.
- Mendengarkan saluran sembarang dapat mengakibatkan penyetelan ke saluran fisik berikutnya, meskipun tidak ada sinyal siaran.
Aplikasi radio menangani tindakan ini.
Penanganan kesalahan
Tindakan TransportControls
(Mainkan, Berhenti, dan Berikutnya) tidak memberikan umpan balik mengenai apakah tindakan tersebut berhasil atau tidak. Satu-satunya cara untuk menunjukkan kesalahan adalah dengan menyetel status MediaSession ke STATE_ERROR
dengan pesan kesalahan.
Aplikasi radio harus menangani tindakan tersebut dan menjalankannya atau menetapkan status kesalahan. Jika perintah Putar tidak langsung dijalankan, status pemutaran harus diubah menjadi STATE_CONNECTING
(jika penalaan langsung) atau STATE_SKIPPING_TO_PREVIOUS
atau NEXT
saat perintah dijalankan.
Klien harus memperhatikan PlaybackState
dan memverifikasi bahwa sesi tersebut mengubah program saat ini sesuai permintaan atau dimasukkan ke dalam status kesalahan. STATE_CONNECTING
tidak boleh lebih dari 30 detik. Namun, penyetelan langsung ke frekuensi AM/FM tertentu akan bekerja lebih cepat.
Tambahkan dan hapus favorit
MediaSession memiliki dukungan rating, yang dapat digunakan untuk mengontrol Favorit. onSetRating
dipanggil dengan peringkat tipe RATING_HEART
menambah atau menghapus stasiun yang sedang disetel ke atau dari daftar Favorit.
Bertentangan dengan preset lama, model ini mengasumsikan daftar Favorit tidak berurutan dan tidak terbatas, ketika setiap favorit yang disimpan dialokasikan ke slot numerik (biasanya, 1 hingga 6). Akibatnya, sistem berbasis preset tidak kompatibel dengan operasi onSetRating
.
Batasan MediaSession API adalah hanya stasiun yang sedang disetel yang dapat ditambahkan atau dihapus. Misalnya, item harus dipilih terlebih dahulu sebelum dapat dihapus. Ini hanya batasan klien MediaBrowser, seperti aplikasi pendamping. Aplikasi radio tidak dibatasi dengan cara yang sama. Bagian ini bersifat opsional ketika aplikasi tidak mendukung Favorit.
Peramban Media
Untuk menyatakan frekuensi atau nama saluran fisik mana (saat menyetel ke saluran sembarang yang sesuai untuk teknologi radio tertentu) yang valid untuk wilayah tertentu, semua saluran (frekuensi) yang valid dicantumkan untuk setiap pita. Di wilayah AS, jumlahnya mencapai 101 saluran FM dalam rentang 87,8 hingga 108,0 MHz (menggunakan spasi 0,2MHz) dan 117 saluran AM dalam rentang 530 hingga 1700 kHz (menggunakan spasi 10kHz). Karena radio HD menggunakan ruang saluran yang sama, maka tidak disajikan secara terpisah.
Daftar program radio yang tersedia saat ini datar karena tidak memungkinkan skema tampilan seperti pengelompokan berdasarkan ansambel siaran audio langsung (DAB).
Entri pada daftar Favorit mungkin tidak dapat disetel. Misalnya jika program tertentu berada di luar jangkauan. Aplikasi radio mungkin mendeteksi atau tidak mendeteksi apakah entri tersebut dapat disetel sebelumnya. Jika demikian, entri tersebut mungkin tidak ditandai sebagai dapat diputar.
Untuk mengidentifikasi folder tingkat atas, mekanisme yang sama yang digunakan oleh Bluetooth diterapkan. Artinya, bundel Ekstra dari objek MediaDescription
berisi bidang khusus tuner seperti yang dilakukan Bluetooth dengan EXTRA_BT_FOLDER_TYPE
. Dalam kasus radio siaran, hal ini mengarah pada penentuan kolom baru berikut di API publik:
-
EXTRA_BCRADIO_FOLDER_TYPE = "android.media.extra.EXTRA_BCRADIO_FOLDER_TYPE"
. Salah satu nilai berikut:-
BCRADIO_FOLDER_TYPE_PROGRAMS = 1
. Program yang tersedia saat ini. -
BCRADIO_FOLDER_TYPE_FAVORITES = 2
. Favorit. -
BCRADIO_FOLDER_TYPE_BAND = 3
. Semua saluran fisik untuk band tertentu.
Tidak perlu menentukan bidang metadata khusus radio apa pun, karena semua data yang relevan cocok dengan skema
MediaBrowser.MediaItem
yang ada:- Nama program (RDS PS, nama layanan DAB).
MediaDescription.getTitle
. - frekuensi FM. URI (lihat ProgramSelector ) atau
MediaDescription.getTitle
(jika entri ada di folderBROADCASTRADIO_FOLDER_TYPE_BAND
). - Pengidentifikasi khusus radio (RDS PI, DAB SId).
MediaDescription.getMediaUri
diuraikan ke ProgramSelector.
Biasanya, tidak perlu mengambil frekuensi FM untuk entri pada program saat ini atau daftar Favorit (karena klien harus beroperasi pada ID media). Namun, jika kebutuhan tersebut muncul (misalnya, untuk tujuan tampilan), kebutuhan tersebut ada di URI dan dapat diurai ke
ProgramSelector
. Meskipun demikian, URI tidak disarankan digunakan untuk memilih item dalam sesi saat ini. Untuk detailnya, lihatProgramSelector
.Untuk menghindari masalah kinerja atau terkait pengikat, layanan MediaBrowser harus mendukung penomoran halaman:
-
EXTRA_PAGE
-
EXTRA_PAGE_SIZE
- Parameter tambahan untuk
subscribe()
Catatan: Secara default, penomoran halaman diterapkan secara default di varian
onLoadChildren()
tanpa penanganan opsi.Entri terkait dari semua jenis daftar (saluran mentah, program yang ditemukan, dan favorit) mungkin memiliki mediaId yang berbeda (terserah pada aplikasi radio; perpustakaan dukungan akan memilikinya berbeda). URI (dalam bentuk ProgramSelector) berbeda antara saluran mentah dan program yang ditemukan di sebagian besar kasus (kecuali untuk FM tanpa RDS), namun sebagian besar sama antara program yang ditemukan dan favorit (kecuali, misalnya, ketika AF diperbarui).
Memiliki mediaId yang berbeda untuk entri dari berbagai jenis daftar memungkinkan untuk mengambil tindakan berbeda terhadapnya. Anda dapat melintasi daftar Favorit atau daftar Semua Program di
onSkipToNext
, bergantung pada folderMediaItem
yang baru saja dipilih (lihat MediaSession ).Tindakan nada khusus
Daftar program memungkinkan pengguna untuk mencari stasiun tertentu, namun tidak memungkinkan pengguna untuk membuat permintaan umum seperti "Tune to FM", yang dapat mengakibatkan penyetelan ke stasiun yang baru-baru ini didengarkan pada pita FM.
Untuk mendukung tindakan tersebut, beberapa direktori tingkat atas memiliki kumpulan tanda
FLAG_PLAYABLE
(bersama denganFLAG_BROWSABLE
untuk folder).Tindakan Lagu ke Bagaimana cara mengeluarkannya Putar radio Saluran radio apa pun startService(ACTION_PLAY_BROADCASTRADIO)
atau
playFromMediaId(MediaBrowser. getRoot() )
Putar FM Saluran FM apa pun Putar dari mediaId
band FM.Penentuan program mana yang akan disesuaikan bergantung pada aplikasi. Biasanya ini adalah saluran yang paling baru disetel dari daftar yang diberikan. Untuk detail tentang
ACTION_PLAY_BROADCASTRADIO
, lihat Maksud bermain secara umum .Penemuan dan koneksi layanan
PackageManager
dapat langsung menemukan pohon radio siaran MediaBrowserService yang menyajikan. Untuk melakukannya, panggilresolveService
dengan maksudACTION_PLAY_BROADCASTRADIO
(lihat Maksud permainan umum ) dan tandaMATCH_SYSTEM_ONLY
. Untuk menemukan semua layanan yang melayani radio (mungkin ada lebih dari satu; misalnya, AM/FM dan satelit terpisah), gunakanqueryIntentServices
.Layanan yang diselesaikan juga menangani maksud pengikatan
android.media.browse.MediaBrowserService
. Ini diverifikasi dengan GTS.Untuk menyambung ke MediaBrowserService yang dipilih, buat instans
MediaBrowser
untuk komponen layanan tertentu danconnect
. Setelah membuat koneksi, pegangan ke MediaSession dapat diperoleh melaluigetSessionToken
.Aplikasi Radio dapat membatasi paket klien yang diizinkan untuk terhubung dalam implementasi
onGetRoot
pada layanan mereka. Aplikasi harus mengizinkan aplikasi sistem untuk terhubung tanpa memasukkan ke daftar putih. Untuk mengetahui detail tentang memasukkan ke daftar putih, lihat Menerima paket dan tanda tangan aplikasi Asisten .Jika aplikasi khusus sumber (misalnya, aplikasi radio) diinstal pada perangkat tanpa dukungan sumber tersebut, aplikasi tersebut akan tetap mengiklankan dirinya sebagai menangani maksud
ACTION_PLAY_BROADCASTRADIO
, namun pohon MediaBrowsernya tidak akan berisi tag khusus radio. Oleh karena itu, klien yang ingin memeriksa apakah sumber tertentu tersedia di perangkat, harus:- Temukan layanan radio (panggil
resolveService
untukACTION_PLAY_BROADCASTRADIO
). - Buat
MediaBrowser
lalu sambungkan ke sana. - Tentukan keberadaan
MediaItem
dengan tambahanEXTRA_BCRADIO_FOLDER_TYPE
.
Catatan: Dalam kebanyakan kasus, klien harus memindai semua pohon MediaBrowser yang tersedia untuk mendeteksi semua sumber yang tersedia untuk perangkat tertentu.
Nama band
Daftar band diwakili oleh sekumpulan direktori tingkat atas dengan tag tipe folder yang disetel ke
BCRADIO_FOLDER_TYPE_BAND
. JudulMediaItem
mereka adalah string lokal yang mewakili nama band. Dalam kebanyakan kasus, terjemahannya akan sama dengan terjemahan bahasa Inggris, namun klien tidak dapat bergantung pada asumsi tersebut.Untuk menyediakan mekanisme yang stabil dalam mencari band tertentu, tag tambahan ditambahkan untuk folder band,
EXTRA_BCRADIO_BAND_NAME_EN
. Ini adalah nama band yang tidak dilokalkan dan hanya dapat mengambil salah satu dari nilai yang telah ditentukan sebelumnya:-
AM
-
FM
-
DAB
Jika band tidak ada dalam daftar ini, tag nama band tidak boleh disetel. Namun, jika band tersebut ada dalam daftar, band tersebut harus memiliki tag yang disetel. Radio HD tidak menyebutkan band-band terpisah karena menggunakan media dasar yang sama seperti AM/FM.
Maksud bermain secara umum
Setiap aplikasi yang didedikasikan untuk memutar sumber tertentu (seperti radio atau CD) harus menangani maksud pemutaran umum untuk mulai memutar beberapa konten yang mungkin dari keadaan tidak aktif (misalnya, setelah boot). Cara memilih konten yang akan diputar bergantung pada aplikasi, namun biasanya yang diputar adalah program radio atau trek CD yang baru diputar. Ada maksud terpisah yang ditentukan untuk setiap sumber audio:
-
android.car.intent.action.PLAY_BROADCASTRADIO
-
android.car.intent.action.PLAY_AUDIOCD
: CD-DA atau CD-Teks -
android.car.intent.action.PLAY_DATADISC
: Disk data optik seperti CD/DVD, tetapi bukan CD-DA (mungkin CD Mode Campuran) -
android.car.intent.action.PLAY_AUX
: Tanpa menentukan port AUX yang mana -
android.car.intent.action.PLAY_BLUETOOTH
-
android.car.intent.action.PLAY_USB
: Tanpa menentukan perangkat USB yang mana -
android.car.intent.action.PLAY_LOCAL
: Penyimpanan media lokal (flash internal)
Intent dipilih untuk digunakan pada perintah main umum, karena maksud tersebut memecahkan dua masalah sekaligus: perintah main umum itu sendiri dan penemuan layanan. Manfaat tambahan dari memiliki maksud tersebut adalah kemungkinan untuk menjalankan tindakan sederhana tersebut tanpa membuka sesi MediaBrowser.
Penemuan layanan sebenarnya adalah masalah yang lebih penting yang diselesaikan dengan maksud ini. Prosedur penemuan layanan mudah dan jelas dengan cara ini (lihat Penemuan dan koneksi layanan ).
Untuk membuat beberapa implementasi klien lebih mudah, ada cara alternatif untuk mengeluarkan perintah Play (yang juga harus diterapkan oleh aplikasi radio): mengeluarkan
playFromMediaId
dengan rootId dari node root (digunakan sebagai mediaId). Meskipun simpul akar tidak dimaksudkan untuk dapat dimainkan, rootId-nya adalah string arbitrer yang dapat digunakan sebagai mediaId. Namun, klien tidak diharuskan untuk memahami nuansa ini.Pemilih Program
Meskipun
mediaId
cukup untuk memilih saluran dariMediaBrowserService
, saluran tersebut menjadi terikat pada satu sesi dan tidak konsisten antar penyedia. Dalam beberapa kasus, klien mungkin memerlukan penunjuk absolut (seperti frekuensi absolut) untuk mempertahankannya antara sesi dan perangkat.Di era siaran radio digital, frekuensi kosong saja tidak cukup untuk menyetel stasiun tertentu. Oleh karena itu, gunakan
ProgramSelector
untuk mencari saluran analog atau digital.ProgramSelector
terdiri dari dua bagian:- Pengidentifikasi utama. Pengidentifikasi unik dan stabil untuk stasiun radio tertentu yang tidak berubah tetapi mungkin tidak cukup untuk menyetel stasiun tersebut. Misalnya kode RDS PI, yang dapat diterjemahkan menjadi tanda panggil di AS.
- Pengidentifikasi sekunder. Pengidentifikasi tambahan yang berguna untuk menyetel stasiun tersebut (misalnya, frekuensi), mungkin termasuk pengidentifikasi dari teknologi radio lainnya. Misalnya, stasiun DAB mungkin memiliki cadangan siaran analog.
Untuk mengaktifkan
ProgramSelector
agar sesuai dengan solusi berbasisMediaBrowser
- atauMediaSession
, tentukan skema URI untuk membuat serialisasinya. Skema ini didefinisikan sebagai berikut:broadcastradio://program/<primary ID type>/<primary ID>? <secondary ID type>=<secondary ID>&<secondary ID type>=<secondary ID>
Dalam contoh ini, bagian Pengidentifikasi sekunder (setelah tanda tanya (
?
)) bersifat opsional dan dapat dihapus untuk memberikan pengidentifikasi yang stabil untuk digunakan sebagaimediaId
. Misalnya:-
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
Bagian yang berwenang (alias tuan rumah) dari
program
memberikan ruang untuk perluasan skema di masa depan. String tipe pengidentifikasi ditentukan secara tepat sebagai namanya dalam definisi HAL 2.x dariIdentifierType
dan format nilainya adalah angka desimal atau heksadesimal (dengan awalan0x
).Semua pengidentifikasi khusus vendor diwakili oleh awalan
VENDOR_
. Misalnya,VENDOR_0
untukVENDOR_START
danVENDOR_1
untukVENDOR_START
ditambah 1. URI tersebut khusus untuk perangkat keras radio tempat URI tersebut dibuat dan tidak dapat ditransfer antar perangkat yang dibuat oleh OEM berbeda.URI ini harus ditetapkan ke setiap MediaItem di bawah folder radio tingkat atas. Selain itu, MediaSession harus mendukung
playFromMediaId
danplayFromUri
. Namun, URI terutama ditujukan untuk ekstraksi metadata radio (seperti frekuensi FM) dan penyimpanan persisten. Tidak ada jaminan URI akan tersedia untuk semua item media (misalnya, ketika jenis ID utama belum didukung oleh framework). Di sisi lain, Media ID selalu berfungsi. Klien tidak disarankan menggunakan URI untuk memilih item dari sesi MediaBrowser saat ini. Sebagai gantinya, gunakanplayFromMediaId
. Meskipun demikian, ini bukan opsional untuk aplikasi penyajian dan URI yang hilang dicadangkan untuk kasus-kasus yang dapat dibenarkan.Desain awal menggunakan titik dua tunggal, bukan urutan
://
setelah bagian skema. Namun, versi pertama tidak didukung olehandroid.net.Uri
untuk referensi URI hierarki absolut.Jenis sumber lainnya
Sumber audio lainnya dapat ditangani dengan cara yang sama. Misalnya input tambahan dan pemutar CD Audio.
Satu aplikasi dapat melayani berbagai jenis sumber. Dalam kasus seperti ini, sebaiknya Anda membuat MediaBrowserService terpisah untuk setiap jenis sumber. Bahkan dalam pengaturan dengan beberapa sumber yang dilayani/Layanan MediaBrowser, sangat disarankan untuk memiliki satu MediaSession dalam satu aplikasi.
CD Audio
Mirip dengan Audio CD, aplikasi yang melayani disk tersebut akan mengekspos MediaBrowser dengan satu entri yang dapat dijelajahi (atau lebih, jika sistem memiliki pengubah CD), yang pada gilirannya akan berisi semua trek dari CD tertentu. Jika sistem tidak memiliki pengetahuan tentang track pada setiap CD (misalnya, ketika semua disk dimasukkan ke dalam kartrid sekaligus dan tidak membaca semuanya), maka MediaItem untuk seluruh disk hanya
PLAYABLE
, bukanBROWSABLE
danPLAYABLE
. Jika tidak ada disk pada slot tertentu, item tersebut tidak DAPATPLAYABLE
atauBROWSABLE
(tetapi setiap slot harus selalu ada di pohon).Entri-entri ini akan ditandai dengan cara yang sama seperti folder radio siaran; kolom tersebut akan berisi kolom tambahan tambahan yang ditentukan di MediaDescription API:
-
EXTRA_CD_TRACK
: Untuk setiapMediaItem
pada CD Audio, 1 nomor track berdasarkan. -
EXTRA_CD_DISK
: nomor disk berdasarkan 1.
Untuk sistem yang mendukung CD-Teks dan disk yang kompatibel, MediaItem tingkat atas akan memiliki judul disk. Demikian pula, MediaItems untuk trek, akan memiliki judul lagu.
Masukan tambahan
Aplikasi yang menyajikan input tambahan menampilkan pohon MediaBrowser dengan satu entri (atau lebih, jika ada beberapa port) yang mewakili port AUX in. MediaSession masing-masing mengambil mediaId-nya dan beralih ke sumber tersebut setelah mendapatkan permintaan
playFromMediaId
.Setiap entri AUX MediaItem akan memiliki bidang tambahan
EXTRA_AUX_PORT_NAME
yang disetel ke nama port yang tidak dilokalkan tanpa frasa "AUX". Misalnya, "AUX 1" akan disetel ke "1", "AUX front" ke "front" dan "AUX" ke string kosong. Di lokasi non-Inggris, tag nama akan tetap menggunakan string bahasa Inggris yang sama. Tidak sepertiEXTRA_BCRADIO_BAND_NAME_EN
, nilainya ditentukan oleh OEM dan tidak dibatasi pada daftar yang telah ditentukan sebelumnya.Jika perangkat keras dapat mendeteksi perangkat yang terhubung ke port AUX, perangkat keras harus menandai mediaitem sebagai
PLAYABLE
, hanya jika input terhubung. Perangkat keras masih harus disebutkan (tetapi tidakPLAYABLE
) jika tidak ada yang terhubung ke port ini. Jika perangkat keras tidak memiliki kemampuan seperti itu, mediaitem harus selalu diatur untukPLAYABLE
.Bidang tambahan
Tentukan bidang berikut:
-
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"
Klien perlu meninjau media tingkat atas untuk elemen-elemen yang memiliki
EXTRA_CD_DISK
atauEXTRA_AUX_PORT_NAME
Set bidang tambahan.Contoh rinci
Contoh -contoh berikut membahas struktur pohon mediabrowser untuk jenis sumber yang merupakan bagian dari desain ini.
Siaran radio mediabrowserService (menangani
ACTION_PLAY_BROADCASTRADIO
):- Stasiun (browsable)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_PROGRAMS
- BBC One (Playable) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=90500
- ABC 88.1 (dapat dimainkan) URI:
broadcastradio://program/RDS_PI/5678?AMFM_FREQUENCY=88100
- ABC 88.1 HD1 (dapat dimainkan) URI:
broadcastradio://program/HD_STATION_ID_EXT/158241DEADBEEF?AMFM_FREQUENCY=88100&RDS_PI=5678
- ABC 88.1 HD2 (dapat dimainkan) URI:
broadcastradio://program/HD_STATION_ID_EXT/158242DEADBEFE
- 90.5 FM (dapat dimainkan) - FM TANPA RDSURI:
broadcastradio://program/AMFM_FREQUENCY/90500
- 620 AM (dapat dimainkan) URI:
broadcastradio://program/AMFM_FREQUENCY/620
- BBC One (Playable) URI:
broadcastradio://program/DAB_SID_EXT/1E24102?RDS_PI=1234
- BBC One (Playable) URI:
- Favorit (browsable, dapat dimainkan)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_FAVORITES
- BBC One (Playable) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=101300
- BBC Two (tidak dapat dimainkan) URI:
broadcastradio://program/RDS_PI/1300?AMFM_FREQUENCY=102100
- BBC One (Playable) URI:
- Am (browsable, playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="AM"
- 530 AM (dapat dimainkan) URI:
broadcastradio://program/AMFM_FREQUENCY/530
- 540 AM (dapat dimainkan) URI:
broadcastradio://program/AMFM_FREQUENCY/540
- 550 AM (dapat dimainkan) URI:
broadcastradio://program/AMFM_FREQUENCY/550
- 530 AM (dapat dimainkan) URI:
- Fm (browsable, dapat dimainkan):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="FM"
- 87.7 FM (dapat dimainkan) URI:
broadcastradio://program/AMFM_FREQUENCY/87700
- 87.9 FM (dapat dimainkan) URI:
broadcastradio://program/AMFM_FREQUENCY/87900
- 88.1 FM (dapat dimainkan) URI:
broadcastradio://program/AMFM_FREQUENCY/88100
- 87.7 FM (dapat dimainkan) URI:
- DAB (dapat dimainkan):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="DAB"
Audio CD MediaBrowserService (menangani
ACTION_PLAY_AUDIOCD
):- Disc 1 (dapat dimainkan)
EXTRA_CD_DISK=1
- Disc 2 (Browsable, dapat dimainkan)
EXTRA_CD_DISK=2
- Lacak 1 (dapat dimainkan)
EXTRA_CD_TRACK=1
- Lacak 2 (dapat dimainkan)
EXTRA_CD_TRACK=2
- Lacak 1 (dapat dimainkan)
- CD Musik Saya (Browsable, Dapat Dimainkan)
EXTRA_CD_DISK=3
- All By Myself (dapat dimainkan)
EXTRA_CD_TRACK=1
- Reise, Reise (dapat dimainkan)
EXTRA_CD_TRACK=2
- All By Myself (dapat dimainkan)
- Slot kosong 4 (tidak dapat dimainkan)
EXTRA_CD_DISK=4
Aux mediabrowserService (menangani
ACTION_PLAY_AUX
):- Aux front (playable)
EXTRA_AUX_PORT_NAME="front"
- Aux belakang (dapat dimainkan)
EXTRA_AUX_PORT_NAME="rear"
-