Framework router media Android memungkinkan produsen mengaktifkan pemutaran di perangkat mereka
melalui antarmuka standar yang disebut MediaRouteProvider
.
Penyedia rute menentukan antarmuka umum untuk
memutar media di perangkat penerima, sehingga
dapat memutar media di peralatan Anda dari aplikasi Android apa pun yang mendukung
rute perjalanan.
Panduan ini membahas cara membuat penyedia rute media untuk perangkat penerima dan membuatnya
yang tersedia untuk aplikasi pemutaran media lain
yang berjalan di Android. Untuk menggunakan API ini, Anda
harus terbiasa dengan class utama
MediaRouteProvider
,
MediaRouteProviderDescriptor
, dan
RouteController
.
Ringkasan
Framework router media Android memungkinkan developer aplikasi media dan perangkat pemutaran media
produsen untuk terhubung melalui API umum
dan antarmuka pengguna umum. Developer aplikasi yang
mengimplementasikan antarmuka MediaRouter
kemudian dapat terhubung ke
dan memutar konten ke perangkat yang berpartisipasi dalam kerangka kerja {i>router<i} media. Media
produsen perangkat pemutaran dapat berpartisipasi dalam framework dengan memublikasikan MediaRouteProvider
yang memungkinkan aplikasi lain terhubung ke dan
memutar media di perangkat penerima. Gambar 1 mengilustrasikan cara aplikasi terhubung ke jaringan penerima
perangkat tertentu melalui framework router media.
Saat Anda membangun penyedia rute media untuk perangkat penerima, penyedia tersebut akan menyajikan untuk tujuan berikut:
- Menjelaskan dan memublikasikan kemampuan perangkat penerima agar aplikasi lain dapat menemukannya dan menggunakan fitur pemutarannya.
- Menggabungkan antarmuka pemrograman perangkat penerima dan komunikasinya mekanisme transportasi umum untuk membuat perangkat kompatibel dengan kerangka kerja {i>router<i} media.
Distribusi penyedia rute
Penyedia rute media didistribusikan sebagai bagian dari aplikasi Android. Penyedia rute Anda dapat berupa
tersedia untuk aplikasi lain dengan memperluas
MediaRouteProviderService
atau menggabungkan penerapan
MediaRouteProvider
dengan layanan Anda sendiri dan mendeklarasikan intent
untuk penyedia rute media. Langkah-langkah ini memungkinkan aplikasi lain untuk menemukan dan memanfaatkan
rute media Anda.
Catatan: Aplikasi yang berisi penyedia rute media juga dapat menyertakan Antarmuka MediaRouter ke penyedia rute, tetapi ini tidak wajib.
Support Library MediaRouter
API router media didefinisikan dalam Library MediaRouter AndroidX Anda harus menambahkan library ini ke project pengembangan aplikasi Anda. Untuk informasi selengkapnya tentang cara menambahkan support library ke project Anda, lihat Penyiapan Support Library.
Perhatian: Pastikan Anda menggunakan AndroidX
dan implementasi framework router media.
Jangan gunakan paket android.media
yang lama.
Membuat Layanan Penyedia
Framework router media harus dapat menemukan dan terhubung ke penyedia rute media Anda
untuk mengizinkan aplikasi lain menggunakan rute Anda. Untuk melakukannya, kerangka kerja {i>router<i} media
akan mencari aplikasi yang mendeklarasikan tindakan intent penyedia rute media. Saat aplikasi lain ingin
terhubung ke penyedia Anda, framework harus dapat memanggil dan terhubung dengannya, jadi
harus dienkapsulasi dalam Service
.
Kode contoh berikut menunjukkan deklarasi layanan penyedia rute media dan atribut filter intent dalam manifes, yang memungkinkannya ditemukan dan digunakan oleh router media kerangka kerja:
<service android:name=".provider.SampleMediaRouteProviderService" android:label="@string/sample_media_route_provider_service" android:process=":mrp"> <intent-filter> <action android:name="android.media.MediaRouteProviderService" /> </intent-filter> </service>
Contoh manifes ini mendeklarasikan layanan yang menggabungkan class penyedia rute media yang sebenarnya.
Framework router media Android menyediakan
Class MediaRouteProviderService
untuk digunakan sebagai wrapper layanan untuk
penyedia rute media. Kode contoh berikut menunjukkan cara menggunakan wrapper ini
:
Kotlin
class SampleMediaRouteProviderService : MediaRouteProviderService() { override fun onCreateMediaRouteProvider(): MediaRouteProvider { return SampleMediaRouteProvider(this) } }
Java
public class SampleMediaRouteProviderService extends MediaRouteProviderService { @Override public MediaRouteProvider onCreateMediaRouteProvider() { return new SampleMediaRouteProvider(this); } }
Menentukan Kemampuan Rute
Aplikasi yang terhubung ke framework router media dapat menemukan rute media melalui deklarasi manifes aplikasi, tetapi juga perlu mengetahui kemampuan rute media yang Anda yang Anda sediakan. Rute media dapat terdiri dari berbagai jenis dan memiliki fitur yang berbeda, serta aplikasi lainnya harus dapat menemukan detail ini untuk menentukan apakah mereka kompatibel dengan rute Anda.
Framework router media memungkinkan Anda mendefinisikan dan memublikasikan kemampuan media
rute melalui objek IntentFilter
, objek MediaRouteDescriptor
, dan MediaRouteProviderDescriptor
. Bagian ini menjelaskan cara menggunakan
guna memublikasikan detail rute media Anda untuk aplikasi lain.
Kategori rute
Sebagai bagian dari deskripsi terprogram penyedia rute media, Anda harus menentukan apakah penyedia Anda mendukung pemutaran jarak jauh, output sekunder, atau keduanya. Ini adalah rutenya yang disediakan oleh framework router media:
CATEGORY_LIVE_AUDIO
— Output audio ke perangkat output sekunder, seperti sistem musik berkemampuan nirkabel.CATEGORY_LIVE_VIDEO
— Output video ke perangkat output sekunder, seperti perangkat Layar Nirkabel.CATEGORY_REMOTE_PLAYBACK
— Putar video atau audio di perangkat terpisah yang menangani media pengambilan, decoding, dan pemutaran, seperti Perangkat Chromecast.
Untuk memasukkan setelan ini dalam deskripsi rute media Anda, masukkan setelan ini ke dalam
objek IntentFilter
, yang nantinya Anda tambahkan ke
Objek MediaRouteDescriptor
:
Kotlin
class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) { companion object { private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = IntentFilter().run { addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) arrayListOf(this) } } }
Java
public final class SampleMediaRouteProvider extends MediaRouteProvider { private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC; static { IntentFilter videoPlayback = new IntentFilter(); videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>(); CONTROL_FILTERS_BASIC.add(videoPlayback); } }
Jika menentukan intent CATEGORY_REMOTE_PLAYBACK
, Anda juga harus menentukan jenis dan jenis media
kontrol pemutaran didukung oleh penyedia rute media Anda. Bagian selanjutnya menjelaskan cara
menentukan setelan ini untuk perangkat Anda.
Jenis media dan protokol
Penyedia rute media untuk perangkat pemutaran jarak jauh harus menentukan jenis media dan transfer
protokol yang didukungnya. Anda menentukan setelan ini menggunakan IntentFilter
addDataScheme()
, dan
Metode addDataType()
objek tersebut. Tujuan
cuplikan kode berikut menunjukkan cara menentukan filter intent untuk mendukung video jarak jauh
pemutaran menggunakan http, https, dan Real Time Streaming Protocol (RTSP):
Kotlin
class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) { companion object { private fun IntentFilter.addDataTypeUnchecked(type: String) { try { addDataType(type) } catch (ex: IntentFilter.MalformedMimeTypeException) { throw RuntimeException(ex) } } private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = IntentFilter().run { addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) addAction(MediaControlIntent.ACTION_PLAY) addDataScheme("http") addDataScheme("https") addDataScheme("rtsp") addDataTypeUnchecked("video/*") arrayListOf(this) } } ... }
Java
public final class SampleMediaRouteProvider extends MediaRouteProvider { private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC; static { IntentFilter videoPlayback = new IntentFilter(); videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); videoPlayback.addAction(MediaControlIntent.ACTION_PLAY); videoPlayback.addDataScheme("http"); videoPlayback.addDataScheme("https"); videoPlayback.addDataScheme("rtsp"); addDataTypeUnchecked(videoPlayback, "video/*"); CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>(); CONTROL_FILTERS_BASIC.add(videoPlayback); } ... private static void addDataTypeUnchecked(IntentFilter filter, String type) { try { filter.addDataType(type); } catch (MalformedMimeTypeException ex) { throw new RuntimeException(ex); } } }
Kontrol pemutaran
Penyedia rute media yang menawarkan pemutaran jarak jauh harus menentukan jenis kontrol media yang didukungnya. Berikut adalah jenis kontrol umum yang dapat disediakan oleh rute media:
- Kontrol pemutaran, seperti putar, jeda, putar ulang, dan maju cepat.
- Fitur antrean, yang memungkinkan aplikasi pengirim menambahkan dan menghapus item dari daftar putar yang dikelola oleh perangkat penerima.
- Fitur sesi, yang mencegah aplikasi pengirim mengganggu masing-masing sesi lainnya dengan meminta perangkat penerima memberikan ID sesi ke aplikasi yang meminta dan kemudian memeriksanya ID tersebut dengan setiap permintaan kontrol pemutaran berikutnya.
Contoh kode berikut menunjukkan cara membuat filter intent untuk mendukung kontrol pemutaran rute media dasar:
Kotlin
class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) { companion object { ... private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = run { val videoPlayback: IntentFilter = ... ... val playControls = IntentFilter().apply { addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) addAction(MediaControlIntent.ACTION_SEEK) addAction(MediaControlIntent.ACTION_GET_STATUS) addAction(MediaControlIntent.ACTION_PAUSE) addAction(MediaControlIntent.ACTION_RESUME) addAction(MediaControlIntent.ACTION_STOP) } arrayListOf(videoPlayback, playControls) } } ... }
Java
public final class SampleMediaRouteProvider extends MediaRouteProvider { private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC; static { ... IntentFilter playControls = new IntentFilter(); playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); playControls.addAction(MediaControlIntent.ACTION_SEEK); playControls.addAction(MediaControlIntent.ACTION_GET_STATUS); playControls.addAction(MediaControlIntent.ACTION_PAUSE); playControls.addAction(MediaControlIntent.ACTION_RESUME); playControls.addAction(MediaControlIntent.ACTION_STOP); CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>(); CONTROL_FILTERS_BASIC.add(videoPlayback); CONTROL_FILTERS_BASIC.add(playControls); } ... }
Untuk informasi selengkapnya tentang intent kontrol pemutaran yang tersedia, lihat class
Class MediaControlIntent
.
MediaRouteProviderDescriptor
Setelah menentukan kemampuan rute media menggunakan objek IntentFilter
, Anda kemudian dapat membuat objek deskriptor untuk dipublikasikan ke
framework router media Android. Objek deskriptor ini berisi detail media Anda
kemampuan rute agar aplikasi lain dapat menentukan cara berinteraksi dengan media Anda
rute perjalanan.
Kode contoh berikut menunjukkan cara menambahkan filter intent yang dibuat sebelumnya ke
MediaRouteProviderDescriptor
dan tetapkan deskriptor untuk digunakan oleh
framework router media:
Kotlin
class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) { init { publishRoutes() } private fun publishRoutes() { val resources = context.resources val routeName: String = resources.getString(R.string.variable_volume_basic_route_name) val routeDescription: String = resources.getString(R.string.sample_route_description) // Create a route descriptor using previously created IntentFilters val routeDescriptor: MediaRouteDescriptor = MediaRouteDescriptor.Builder(VARIABLE_VOLUME_BASIC_ROUTE_ID, routeName) .setDescription(routeDescription) .addControlFilters(CONTROL_FILTERS_BASIC) .setPlaybackStream(AudioManager.STREAM_MUSIC) .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) .setVolumeMax(VOLUME_MAX) .setVolume(mVolume) .build() // Add the route descriptor to the provider descriptor val providerDescriptor: MediaRouteProviderDescriptor = MediaRouteProviderDescriptor.Builder() .addRoute(routeDescriptor) .build() // Publish the descriptor to the framework descriptor = providerDescriptor } ... }
Java
public SampleMediaRouteProvider(Context context) { super(context); publishRoutes(); } private void publishRoutes() { Resources r = getContext().getResources(); // Create a route descriptor using previously created IntentFilters MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder( VARIABLE_VOLUME_BASIC_ROUTE_ID, r.getString(R.string.variable_volume_basic_route_name)) .setDescription(r.getString(R.string.sample_route_description)) .addControlFilters(CONTROL_FILTERS_BASIC) .setPlaybackStream(AudioManager.STREAM_MUSIC) .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) .setVolumeMax(VOLUME_MAX) .setVolume(mVolume) .build(); // Add the route descriptor to the provider descriptor MediaRouteProviderDescriptor providerDescriptor = new MediaRouteProviderDescriptor.Builder() .addRoute(routeDescriptor) .build(); // Publish the descriptor to the framework setDescriptor(providerDescriptor); }
Untuk informasi selengkapnya tentang setelan deskriptor yang tersedia, lihat dokumentasi referensi
untuk MediaRouteDescriptor
dan MediaRouteProviderDescriptor
.
Mengontrol Rute
Jika aplikasi terhubung ke penyedia rute media Anda, penyedia akan menerima pemutaran
perintah melalui framework router media yang
dikirim ke rute Anda oleh aplikasi lain. Untuk menangani hal ini
permintaan, Anda harus menyediakan implementasi class MediaRouteProvider.RouteController
, yang memproses perintah
dan menangani komunikasi aktual
ke perangkat penerima Anda.
Framework router media memanggil onCreateRouteController()
penyedia rute Anda untuk mendapatkan instance class ini, lalu merutekan permintaan ke instance tersebut.
Ini adalah metode utama class MediaRouteProvider.RouteController
, yang harus Anda implementasikan untuk
penyedia rute media Anda:
onSelect()
— Dipanggil bila aplikasi memilih rute Anda untuk pemutaran. Anda menggunakan metode ini untuk melakukan persiapan yang mungkin diperlukan sebelum pemutaran media dimulai.onControlRequest()
- Mengirimkan perintah pemutaran spesifik ke perangkat penerima.onSetVolume()
— Mengirim permintaan ke perangkat penerima untuk menyetel volume pemutaran ke nilai tertentu.onUpdateVolume()
— Mengirim permintaan ke perangkat penerima untuk mengubah pemutaran volume dengan besaran tertentu.onUnselect()
- Dipanggil ketika aplikasi batal memilih rute.onRelease()
— Dipanggil ketika rute tidak lagi dibutuhkan oleh framework, memungkinkannya untuk membebaskan Google Cloud Platform.
Semua permintaan kontrol pemutaran, kecuali untuk perubahan volume, diarahkan ke onControlRequest()
. Implementasi Anda terhadap metode ini harus mengurai permintaan kontrol dan meresponsnya
dengan tepat. Berikut adalah contoh implementasi metode ini yang memproses perintah untuk
rute media pemutaran jarak jauh:
Kotlin
private class SampleRouteController : MediaRouteProvider.RouteController() { ... override fun onControlRequest( intent: Intent, callback: MediaRouter.ControlRequestCallback? ): Boolean { return if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { val action = intent.action when (action) { MediaControlIntent.ACTION_PLAY -> handlePlay(intent, callback) MediaControlIntent.ACTION_ENQUEUE -> handleEnqueue(intent, callback) MediaControlIntent.ACTION_REMOVE -> handleRemove(intent, callback) MediaControlIntent.ACTION_SEEK -> handleSeek(intent, callback) MediaControlIntent.ACTION_GET_STATUS -> handleGetStatus(intent, callback) MediaControlIntent.ACTION_PAUSE -> handlePause(intent, callback) MediaControlIntent.ACTION_RESUME -> handleResume(intent, callback) MediaControlIntent.ACTION_STOP -> handleStop(intent, callback) MediaControlIntent.ACTION_START_SESSION -> handleStartSession(intent, callback) MediaControlIntent.ACTION_GET_SESSION_STATUS -> handleGetSessionStatus(intent, callback) MediaControlIntent.ACTION_END_SESSION -> handleEndSession(intent, callback) else -> false }.also { Log.d(TAG, sessionManager.toString()) } } else { false } } ... }
Java
private final class SampleRouteController extends MediaRouteProvider.RouteController { ... @Override public boolean onControlRequest(Intent intent, ControlRequestCallback callback) { String action = intent.getAction(); if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { boolean success = false; if (action.equals(MediaControlIntent.ACTION_PLAY)) { success = handlePlay(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) { success = handleEnqueue(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) { success = handleRemove(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_SEEK)) { success = handleSeek(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) { success = handleGetStatus(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) { success = handlePause(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_RESUME)) { success = handleResume(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_STOP)) { success = handleStop(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) { success = handleStartSession(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) { success = handleGetSessionStatus(intent, callback); } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) { success = handleEndSession(intent, callback); } Log.d(TAG, sessionManager.toString()); return success; } return false; } ... }
Penting untuk dipahami bahwa class MediaRouteProvider.RouteController
dimaksudkan untuk bertindak sebagai wrapper
untuk API ke peralatan pemutaran media Anda. Implementasi metode di class ini
sepenuhnya bergantung pada antarmuka terprogram
yang disediakan oleh perangkat penerima.
Contoh Kode
MediaRouter contoh ini menunjukkan cara membuat penyedia rute media kustom.