Ringkasan MediaRouter

Untuk menggunakan framework MediaRouter dalam aplikasi, Anda harus mendapatkan instance objek MediaRouter dan melampirkan MediaRouter.Callback untuk memproses peristiwa pemilihan rute. Konten yang dikirim melalui rute media akan melewati MediaRouteProvider terkait (kecuali dalam beberapa kasus khusus, seperti perangkat output Bluetooth). Gambar 1 memberikan tampilan tingkat tinggi yang digunakan untuk merutekan konten antar-perangkat.

Gambar 1. Ringkasan class router media utama yang digunakan oleh aplikasi.

Catatan: Jika Anda ingin aplikasi Anda mendukung Perangkat Google Cast, Anda harus menggunakan Cast SDK dan membangun aplikasi sebagai pengirim Cast. Ikuti petunjuk di Dokumentasi Cast alih-alih menggunakan kerangka kerja MediaRouter secara langsung.

Tombol rute media

Aplikasi Android harus menggunakan tombol rute media untuk mengontrol perutean media. Framework MediaRouter menyediakan antarmuka standar untuk tombol, yang membantu pengguna mengenali dan menggunakan perutean saat tersedia. Tombol rute media biasanya ditempatkan di sisi kanan panel tindakan aplikasi Anda, seperti yang ditampilkan dalam Gambar 2.

Gambar 2. Tombol rute media di panel tindakan.

Saat pengguna menekan tombol rute media, rute media yang tersedia akan muncul dalam daftar seperti pada gambar 3.

Gambar 3. Daftar rute media yang tersedia, yang ditampilkan setelah menekan tombol rute media.

Ikuti langkah-langkah berikut untuk membuat tombol rute media:

  1. Menggunakan AppCompatActivity
  2. Tentukan item menu tombol rute media
  3. Buat MediaRouteSelector
  4. Tambahkan tombol rute media ke panel tindakan
  5. Buat dan kelola metode MediaRouter.Callback dalam siklus hidup aktivitas Anda

Bagian ini menjelaskan empat langkah pertama. Bagian berikutnya menjelaskan metode Callback.

Menggunakan AppCompatActivity

Saat menggunakan kerangka kerja router media dalam aktivitas, Anda harus memperluas aktivitas dari AppCompatActivity lalu impor paket androidx.appcompat.app. Anda harus menambahkan androidx.compat:compat dan androidx.mediarouter:mediarouter library dukungan ke project pengembangan aplikasi Anda. Untuk informasi selengkapnya tentang cara menambahkan support library ke project Anda, lihat Mulai menggunakan Android Jetpack.

Perhatian: Pastikan Anda menggunakan androidx dan implementasi framework router media. Jangan gunakan paket android.media yang lama.

Buat file xml yang menentukan item menu untuk tombol rute media. Tindakan item harus berupa class MediaRouteActionProvider. Berikut adalah file contohnya:

// myMediaRouteButtonMenuItem.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      >

    <item android:id="@+id/media_route_menu_item"
        android:title="@string/media_route_menu_title"
        app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
        app:showAsAction="always"
    />
</menu>

Membuat MediaRouteSelector

Rute yang muncul dalam menu tombol rute media ditentukan oleh MediaRouteSelector. Perluas aktivitas Anda dari AppCompatActivity dan membuat pemilih saat aktivitas dibuat dengan memanggil MediaRouteSelector.Builder dari metode onCreate() seperti yang ditunjukkan dalam contoh kode berikut. Perhatikan bahwa pemilih disimpan dalam variabel class, dan jenis rute yang diizinkan ditetapkan dengan menambahkan objek MediaControlIntent:

Kotlin

class MediaRouterPlaybackActivity : AppCompatActivity() {

    private var mSelector: MediaRouteSelector? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Create a route selector for the type of routes your app supports.
        mSelector = MediaRouteSelector.Builder()
                // These are the framework-supported intents
                .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
                .build()
    }
}

Java

public class MediaRouterPlaybackActivity extends AppCompatActivity {
    private MediaRouteSelector mSelector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create a route selector for the type of routes your app supports.
        mSelector = new MediaRouteSelector.Builder()
                // These are the framework-supported intents
                .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
                .build();
    }
}

Untuk sebagian besar aplikasi, satu-satunya jenis rute yang diperlukan adalah CATEGORY_REMOTE_PLAYBACK. Jenis rute ini memperlakukan perangkat yang menjalankan aplikasi Anda sebagai remote control. Perangkat penerima yang terhubung akan menangani semua pemutaran, dekode, dan pengambilan data konten. Berikut adalah cara aplikasi yang mendukung Google Cast, seperti Chromecast, berfungsi.

Beberapa produsen mendukung opsi perutean khusus yang disebut "output sekunder". Dengan {i>routing<i} ini, aplikasi media mengambil, merender, dan melakukan streaming video atau musik langsung ke layar dan/atau speaker di perangkat penerima jarak jauh yang dipilih. Gunakan output sekunder untuk mengirim konten ke sistem musik atau layar video yang didukung fitur nirkabel. Untuk memungkinkan penemuan dan pilihan perangkat ini, Anda perlu menambahkan CATEGORY_LIVE_AUDIO atau CATEGORY_LIVE_VIDEO mengontrol kategori ke MediaRouteSelector. Anda juga harus membuat dan menangani dialog Presentation Anda sendiri.

Menambahkan tombol rute media ke panel tindakan

Setelah menu rute media dan MediaRouteSelector ditentukan, Anda sekarang dapat menambahkan tombol rute media ke aktivitas. Ganti metode onCreateOptionsMenu() untuk setiap aktivitas Anda guna menambahkan opsi Google Spreadsheet.

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    super.onCreateOptionsMenu(menu)

    // Inflate the menu and configure the media router action provider.
    menuInflater.inflate(R.menu.sample_media_router_menu, menu)

    // Attach the MediaRouteSelector to the menu item
    val mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item)
    val mediaRouteActionProvider =
            MenuItemCompat.getActionProvider(mediaRouteMenuItem) as MediaRouteActionProvider

    // Attach the MediaRouteSelector that you built in onCreate()
    selector?.also(mediaRouteActionProvider::setRouteSelector)

    // Return true to show the menu.
    return true
}

Java

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    // Inflate the menu and configure the media router action provider.
    getMenuInflater().inflate(R.menu.sample_media_router_menu, menu);

    // Attach the MediaRouteSelector to the menu item
    MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
    MediaRouteActionProvider mediaRouteActionProvider =
            (MediaRouteActionProvider)MenuItemCompat.getActionProvider(
            mediaRouteMenuItem);
    // Attach the MediaRouteSelector that you built in onCreate()
    mediaRouteActionProvider.setRouteSelector(selector);

    // Return true to show the menu.
    return true;
}

Untuk informasi selengkapnya tentang cara menerapkan panel tindakan di aplikasi Anda, lihat Panel Tindakan panduan developer.

Anda juga dapat menambahkan tombol rute media sebagai MediaRouteButton di {i>view<i}. Anda harus melampirkan MediaRouteSelector ke tombol tersebut menggunakan metode setRouteSelector(). Lihat Checklist Desain Google Cast untuk mendapatkan panduan tentang cara menggabungkan tombol rute media ke dalam aplikasi Anda.

Callback MediaRouter

Semua aplikasi yang berjalan di perangkat yang sama memiliki satu instance MediaRouter yang sama dan rutenya (difilter per aplikasi oleh MediaRouteSelector aplikasi). Setiap aktivitas berkomunikasi dengan MediaRouter menggunakan implementasi MediaRouter.Callback-nya sendiri metode. MediaRouter akan memanggil metode callback setiap kali pengguna memilih, mengubah, atau memutuskan sambungan rute.

Ada beberapa metode dalam callback yang bisa Anda ganti untuk menerima informasi tentang peristiwa pemilihan rute. Setidaknya, penerapan class MediaRouter.Callback Anda harus menggantikan onRouteSelected() dan onRouteUnselected().

Karena MediaRouter adalah sumber daya bersama, aplikasi Anda perlu mengelola callback MediaRouter-nya sebagai respons terhadap callback siklus proses aktivitas biasa:

  • Saat aktivitas dibuat (onCreate(Bundle)), arahkan penunjuk ke MediaRouter dan pertahankan selama masa pakai aplikasi.
  • Melampirkan callback ke MediaRouter saat aktivitas terlihat (onStart()), dan melepaskannya saat disembunyikan (onStop()).

Contoh kode berikut menunjukkan cara membuat dan menyimpan objek callback, cara mendapatkan instance MediaRouter, dan cara mengelola callback. Perhatikan penggunaan tanda CALLBACK_FLAG_REQUEST_DISCOVERY saat melampirkan callback dalam onStart(). Tindakan ini memungkinkan MediaRouteSelector memuat ulang tombol rute media daftar rute yang tersedia.

Kotlin

class MediaRouterPlaybackActivity : AppCompatActivity() {

    private var mediaRouter: MediaRouter? = null
    private var mSelector: MediaRouteSelector? = null

    // Variables to hold the currently selected route and its playback client
    private var mRoute: MediaRouter.RouteInfo? = null
    private var remotePlaybackClient: RemotePlaybackClient? = null

    // Define the Callback object and its methods, save the object in a class variable
    private val mediaRouterCallback = object : MediaRouter.Callback() {

        override fun onRouteSelected(router: MediaRouter, route: MediaRouter.RouteInfo) {
            Log.d(TAG, "onRouteSelected: route=$route")
            if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
                // Stop local playback (if necessary)
                // ...

                // Save the new route
                mRoute = route

                // Attach a new playback client
                remotePlaybackClient =
                    RemotePlaybackClient(this@MediaRouterPlaybackActivity, mRoute)

                // Start remote playback (if necessary)
                // ...
            }
        }

        override fun onRouteUnselected(
                router: MediaRouter,
                route: MediaRouter.RouteInfo,
                reason: Int
        ) {
            Log.d(TAG, "onRouteUnselected: route=$route")
            if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {

                // Changed route: tear down previous client
                mRoute?.also {
                    remotePlaybackClient?.release()
                    remotePlaybackClient = null
                }

                // Save the new route
                mRoute = route

                when (reason) {
                    MediaRouter.UNSELECT_REASON_ROUTE_CHANGED -> {
                        // Resume local playback (if necessary)
                        // ...
                    }
                }
            }
        }
    }


    // Retain a pointer to the MediaRouter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Get the media router service.
        mediaRouter = MediaRouter.getInstance(this)
        ...
    }

    // Use this callback to run your MediaRouteSelector to generate the
    // list of available media routes
    override fun onStart() {
        mSelector?.also { selector ->
            mediaRouter?.addCallback(selector, mediaRouterCallback,
                    MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY)
        }
        super.onStart()
    }

    // Remove the selector on stop to tell the media router that it no longer
    // needs to discover routes for your app.
    override fun onStop() {
        mediaRouter?.removeCallback(mediaRouterCallback)
        super.onStop()
    }
    ...
}

Java

public class MediaRouterPlaybackActivity extends AppCompatActivity {
    private MediaRouter mediaRouter;
    private MediaRouteSelector mSelector;

    // Variables to hold the currently selected route and its playback client
    private MediaRouter.RouteInfo mRoute;
    private RemotePlaybackClient remotePlaybackClient;

    // Define the Callback object and its methods, save the object in a class variable
    private final MediaRouter.Callback mediaRouterCallback =
            new MediaRouter.Callback() {

        @Override
        public void onRouteSelected(MediaRouter router, RouteInfo route) {
            Log.d(TAG, "onRouteSelected: route=" + route);

            if (route.supportsControlCategory(
                MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)){
                // Stop local playback (if necessary)
                // ...

                // Save the new route
                mRoute = route;

                // Attach a new playback client
                remotePlaybackClient = new RemotePlaybackClient(this, mRoute);

                // Start remote playback (if necessary)
                // ...
            }
        }

        @Override
        public void onRouteUnselected(MediaRouter router, RouteInfo route, int reason) {
            Log.d(TAG, "onRouteUnselected: route=" + route);

            if (route.supportsControlCategory(
                MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)){

                // Changed route: tear down previous client
                if (mRoute != null && remotePlaybackClient != null) {
                    remotePlaybackClient.release();
                    remotePlaybackClient = null;
                }

                // Save the new route
                mRoute = route;

                if (reason != MediaRouter.UNSELECT_REASON_ROUTE_CHANGED) {
                    // Resume local playback  (if necessary)
                    // ...
                }
            }
        }
    }


    // Retain a pointer to the MediaRouter
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Get the media router service.
        mediaRouter = MediaRouter.getInstance(this);
        ...
    }

    // Use this callback to run your MediaRouteSelector to generate the list of available media routes
    @Override
    public void onStart() {
        mediaRouter.addCallback(mSelector, mediaRouterCallback,
                MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
        super.onStart();
    }

    // Remove the selector on stop to tell the media router that it no longer
    // needs to discover routes for your app.
    @Override
    public void onStop() {
        mediaRouter.removeCallback(mediaRouterCallback);
        super.onStop();
    }
    ...
}

Framework router media juga menyediakan MediaRouteDiscoveryFragment, yang menangani penambahan dan menghapus callback untuk aktivitas.

Catatan: Jika Anda menulis aplikasi pemutaran musik dan ingin aplikasi tersebut diputar musik saat diputar di latar belakang, Anda harus membangun Service agar dapat diputar dan memanggil framework router media dari callback siklus proses Layanan.

Mengontrol rute pemutaran jarak jauh

Jika Anda memilih rute pemutaran jarak jauh, aplikasi Anda akan berfungsi sebagai remote control. Perangkat di ujung lain rute menangani semua fungsi pengambilan, decoding, dan pemutaran data konten. Kontrol dalam UI aplikasi Anda berkomunikasi dengan perangkat penerima menggunakan Objek RemotePlaybackClient.

Class RemotePlaybackClient menyediakan metode tambahan untuk mengelola pemutaran konten. Berikut adalah beberapa metode pemutaran utama dari class RemotePlaybackClient:

  • play() — Putar file media yang ditentukan oleh Uri.
  • pause() — Menjeda sedang memutar trek media.
  • resume() — Lanjutkan memutar lagu saat ini setelah perintah jeda.
  • seek() — Memindahkan ke pada {i>track <i}yang sedang digunakan.
  • release() — Merombak dari aplikasi Anda ke perangkat pemutaran jarak jauh.

Anda bisa menggunakan metode ini untuk melampirkan tindakan ke kontrol pemutaran yang Anda berikan dalam . Sebagian besar metode ini juga memungkinkan Anda untuk menyertakan objek callback sehingga Anda bisa memantau progres tugas pemutaran atau permintaan kontrol.

Class RemotePlaybackClient juga mendukung pengantrean beberapa item media untuk pemutaran dan pengelolaan antrean media.

Kode contoh

Android BasicMediaRouter dan MediaRouter contoh ini menunjukkan penggunaan MediaRouter API lebih lanjut.