Để sử dụng khung MediaRouter trong ứng dụng, bạn phải lấy một thực thể
của đối tượng MediaRouter
và đính kèm một
Đối tượng MediaRouter.Callback
để theo dõi các sự kiện định tuyến.
Nội dung được gửi qua tuyến nội dung đa phương tiện sẽ đi qua
MediaRouteProvider
được liên kết (ngoại trừ trong một vài trường hợp đặc biệt,
chẳng hạn như thiết bị đầu ra Bluetooth). Hình 1 cung cấp chế độ xem cấp cao của
các lớp dùng để định tuyến nội dung giữa các thiết bị.
Lưu ý: Nếu bạn muốn ứng dụng của mình hỗ trợ Thiết bị Google Cast, bạn nên dùng SDK Truyền và tạo ứng dụng của bạn như một thiết bị gửi Truyền. Làm theo hướng dẫn trong Tài liệu về tính năng truyền thay vì sử dụng trực tiếp khung MediaRouter.
Nút định tuyến nội dung nghe nhìn
Ứng dụng Android nên sử dụng nút định tuyến nội dung nghe nhìn để kiểm soát việc định tuyến nội dung nghe nhìn. Khung MediaRouter cung cấp giao diện chuẩn cho nút, giúp người dùng nhận dạng và sử dụng tính năng định tuyến khi ứng dụng có sẵn. Nút định tuyến nội dung đa phương tiện thường được đặt ở bên phải của thanh thao tác của ứng dụng, như được minh hoạ trong Hình 2.
Khi người dùng nhấn nút định tuyến nội dung đa phương tiện, các tuyến nội dung đa phương tiện có sẵn sẽ xuất hiện trong danh sách như minh hoạ trong hình 3.
Làm theo các bước sau để tạo nút định tuyến nội dung nghe nhìn:
- Sử dụng AppCompatActivity
- Xác định mục trong trình đơn nút định tuyến nội dung nghe nhìn
- Tạo MediaRouteSelector
- Thêm nút định tuyến nội dung nghe nhìn vào thanh thao tác
- Tạo và quản lý các phương thức MediaRouter.Callback trong vòng đời của hoạt động
Phần này mô tả bốn bước đầu tiên. Phần tiếp theo mô tả các phương thức Gọi lại.
Sử dụng AppCompatActivity
Khi sử dụng khung bộ định tuyến đa phương tiện trong một hoạt động, bạn nên mở rộng
hoạt động từ AppCompatActivity
và nhập
gói androidx.appcompat.app
. Bạn phải thêm
androidx.appcompat:appcompat
và androidx.mediarouter:mediarouter
các thư viện hỗ trợ vào dự án phát triển ứng dụng của bạn. Để biết thêm thông tin về cách thêm thư viện hỗ trợ
đối với dự án của bạn, hãy xem bài viết Bắt đầu sử dụng Android Jetpack.
Thận trọng: Hãy nhớ sử dụng androidx
khung bộ định tuyến phương tiện. Không sử dụng gói android.media
cũ.
Xác định mục trong trình đơn nút định tuyến nội dung nghe nhìn
Tạo tệp xml xác định một mục trong trình đơn cho nút định tuyến nội dung nghe nhìn.
Thao tác của mục phải là lớp MediaRouteActionProvider
.
Dưới đây là tệp ví dụ:
// 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>
Tạo MediaRouteSelector
Các tuyến xuất hiện trong trình đơn của nút định tuyến nội dung nghe nhìn được xác định bằng MediaRouteSelector
.
Mở rộng hoạt động của bạn từ AppCompatActivity
đồng thời tạo bộ chọn khi hoạt động được tạo gọi MediaRouteSelector.Builder
từ phương thức onCreate() như được hiển thị
trong mã mẫu sau. Lưu ý rằng bộ chọn được lưu trong biến lớp và các loại tuyến được phép sẽ được chỉ định
bằng cách thêm đối tượng 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(); } }
Đối với hầu hết các ứng dụng,
loại tuyến đường cần thiết là CATEGORY_REMOTE_PLAYBACK
. Loại tuyến này coi thiết bị đang chạy ứng dụng là điều khiển từ xa.
Thiết bị nhận được kết nối xử lý tất cả việc truy xuất, giải mã và phát dữ liệu nội dung.
Đây là cách các ứng dụng hỗ trợ Google Cast, chẳng hạn như
Chromecast, cơ quan.
Một số nhà sản xuất hỗ trợ một tuỳ chọn định tuyến đặc biệt có tên là "đầu ra phụ". Với định tuyến này,
ứng dụng đa phương tiện truy xuất, kết xuất và phát trực tuyến video hoặc nhạc trực tiếp lên màn hình và/hoặc loa trên thiết bị thu từ xa đã chọn.
Sử dụng đầu ra phụ để gửi nội dung tới hệ thống âm nhạc hoặc màn hình video có hỗ trợ không dây. Để bật tính năng khám phá và
trong số các thiết bị này, bạn cần thêm
CATEGORY_LIVE_AUDIO
hoặc
CATEGORY_LIVE_VIDEO
kiểm soát các danh mục vào MediaRouteSelector. Bạn cũng cần tạo và xử lý hộp thoại Presentation
của riêng mình.
Thêm nút định tuyến nội dung nghe nhìn vào thanh thao tác
Khi đã xác định trình đơn tuyến nội dung nghe nhìn và MediaRouteSelector, giờ đây, bạn có thể thêm nút tuyến nội dung nghe nhìn vào một hoạt động.
Ghi đè phương thức onCreateOptionsMenu()
cho từng hoạt động để thêm tuỳ chọn
.
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; }
Để biết thêm thông tin về cách triển khai thanh thao tác trong ứng dụng, xem Thanh tác vụ hướng dẫn cho nhà phát triển.
Bạn cũng có thể thêm nút định tuyến nội dung nghe nhìn dưới dạng MediaRouteButton
trong bất kỳ
chế độ xem. Bạn phải đính kèm một MediaRouteSelector vào nút bằng phương thức setRouteSelector()
. Xem
Danh sách kiểm tra cho thiết kế của Google Cast
để biết hướng dẫn về cách kết hợp nút định tuyến nội dung đa phương tiện vào ứng dụng của bạn.
Lệnh gọi lại MediaRouter
Tất cả ứng dụng chạy trên cùng một thiết bị đều có chung một thực thể MediaRouter
và các tuyến của phiên bản đó
(được lọc theo từng ứng dụng bởi MediaRouteSelector của ứng dụng). Mỗi hoạt động giao tiếp với MediaRouter
bằng cách sử dụng cách triển khai MediaRouter.Callback
riêng
. MediaRouter gọi các phương thức gọi lại bất cứ khi nào người dùng chọn, thay đổi hoặc ngắt kết nối một tuyến.
Có một số phương thức trong lệnh gọi lại mà bạn có thể ghi đè để nhận thông tin về
các sự kiện định tuyến. Ở mức tối thiểu, việc triển khai lớp MediaRouter.Callback
của bạn sẽ ghi đè
onRouteSelected()
và
onRouteUnselected()
.
Vì MediaRouter là một tài nguyên dùng chung, nên ứng dụng của bạn cần quản lý các lệnh gọi lại MediaRouter nhằm phản hồi các lệnh gọi lại vòng đời hoạt động thông thường:
- Khi hoạt động được tạo (
onCreate(Bundle)
), hãy lấy một con trỏ đếnMediaRouter
và giữ con trỏ đó trong suốt thời gian hoạt động của ứng dụng. - Đính kèm các lệnh gọi lại vào MediaRouter khi hoạt động hiển thị (
onStart()
) và tách chúng khi hoạt động bị ẩn (onStop()
).
Mã mẫu sau đây minh hoạ cách
tạo và lưu đối tượng gọi lại, cách
lấy một phiên bản của MediaRouter
và cách quản lý lệnh gọi lại.
Hãy lưu ý đến việc sử dụng cờ CALLBACK_FLAG_REQUEST_DISCOVERY
khi đính kèm các lệnh gọi lại trong onStart()
.
Việc này cho phép MediaRouteSelector làm mới nút định tuyến nội dung đa phương tiện
danh sách tuyến đường có thể sử dụng.
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(); } ... }
Khung bộ định tuyến phương tiện cũng cung cấp
Lớp MediaRouteDiscoveryFragment
, lớp này đảm nhận việc thêm và
xoá lệnh gọi lại cho một hoạt động.
Lưu ý: Nếu bạn đang viết một ứng dụng phát nhạc và muốn ứng dụng đó phát
nhạc phát trong nền, bạn phải tạo Service
để phát lại
và gọi khung bộ định tuyến nội dung đa phương tiện từ các phương thức gọi lại trong vòng đời của Dịch vụ.
Điều khiển tuyến phát lại từ xa
Khi bạn chọn một tuyến phát lại từ xa, ứng dụng của bạn hoạt động như một điều khiển từ xa. Thiết bị ở đầu bên kia của tuyến đường
xử lý tất cả các chức năng truy xuất, giải mã và phát lại dữ liệu nội dung. Các thành phần điều khiển trong giao diện người dùng của ứng dụng sẽ giao tiếp với thiết bị nhận bằng một
Đối tượng RemotePlaybackClient
.
Lớp RemotePlaybackClient
cung cấp các phương thức bổ sung
để quản lý việc phát nội dung. Sau đây là một số phương thức phát chính trong lớp RemotePlaybackClient
:
play()
— Phát một bản nhạc cụ thể tệp đa phương tiện doUri
chỉ định.pause()
— Tạm dừng hiện đang phát bản nhạc nội dung nghe nhìn.resume()
— Tiếp tục phát bản nhạc hiện tại sau lệnh tạm dừng.seek()
— Di chuyển đến một vị trí cụ thể vị trí trong kênh hiện tại.release()
— Giảm bớt kết nối từ ứng dụng của bạn với thiết bị phát từ xa.
Bạn có thể dùng các phương pháp sau để đính kèm thao tác vào bộ điều khiển chế độ phát mà bạn cung cấp trong . Hầu hết các phương thức này cũng cho phép bạn bao gồm đối tượng gọi lại để bạn có thể theo dõi tiến trình của tác vụ phát hoặc yêu cầu điều khiển.
Lớp RemotePlaybackClient
cũng hỗ trợ xếp hàng
nhiều mục nội dung nghe nhìn để phát và quản lý hàng đợi nội dung nghe nhìn.
Mã mẫu
Android BasicMediaRouter và MediaRouter các mẫu minh hoạ thêm về việc sử dụng API MediaRouter.