Bật tính năng Truyền cho ứng dụng Android TV

1. Tổng quan

Biểu trưng Google Cast

Lớp học lập trình này sẽ hướng dẫn bạn cách sửa đổi một ứng dụng cho Android TV hiện có để hỗ trợ truyền và giao tiếp từ các ứng dụng gửi Cast hiện có.

Google Cast và Cast Connect là gì?

Google Cast cho phép người dùng truyền nội dung từ thiết bị di động lên TV. Một phiên Google Cast thông thường bao gồm 2 thành phần: ứng dụng người gửi và ứng dụng người nhận. Các ứng dụng gửi, chẳng hạn như ứng dụng di động hoặc trang web như Youtube.com, sẽ khởi chạy và kiểm soát việc phát ứng dụng nhận Cast. Ứng dụng nhận truyền là các ứng dụng HTML 5 chạy trên thiết bị Chromecast và Android TV.

Hầu hết trạng thái trong một phiên truyền đều được lưu trữ trên ứng dụng nhận. Khi trạng thái cập nhật (ví dụ: nếu một mục nội dung nghe nhìn mới được tải), trạng thái nội dung nghe nhìn sẽ được truyền đến tất cả người gửi. Các thông báo này chứa trạng thái hiện tại của phiên truyền. Các ứng dụng người gửi sử dụng trạng thái nội dung nghe nhìn này để hiển thị thông tin phát trong giao diện người dùng.

Cast Connect được xây dựng dựa trên cơ sở hạ tầng này, trong đó ứng dụng cho Android TV của bạn đóng vai trò là một bộ nhận. Thư viện Cast Connect cho phép ứng dụng cho Android TV nhận tin nhắn và truyền phát trạng thái nội dung nghe nhìn như thể đó là một ứng dụng nhận Cast.

Chúng ta sẽ xây dựng những gì?

Khi hoàn tất lớp học lập trình này, bạn sẽ có thể dùng ứng dụng truyền để truyền video đến một ứng dụng cho Android TV. Ứng dụng cho Android TV cũng có thể giao tiếp với ứng dụng truyền thông qua giao thức Truyền.

Kiến thức bạn sẽ học được

  • Cách thêm thư viện Cast Connect vào một ứng dụng ATV mẫu.
  • Cách kết nối thiết bị truyền Cast và chạy ứng dụng ATV.
  • Cách bắt đầu phát nội dung nghe nhìn trên ứng dụng ATV từ một ứng dụng truyền.
  • Cách gửi trạng thái nội dung nghe nhìn từ ứng dụng ATV đến các ứng dụng trên thiết bị phát Cast.

Bạn cần có

2. Nhận mã mẫu

Bạn có thể tải tất cả mã mẫu xuống máy tính...

và giải nén tệp zip đã tải xuống.

3. Chạy ứng dụng mẫu

Trước tiên, hãy xem ứng dụng mẫu hoàn chỉnh trông như thế nào. Ứng dụng cho Android TV sử dụng giao diện người dùng Leanback và một trình phát video cơ bản. Người dùng có thể chọn một video trong danh sách, sau đó video đó sẽ phát trên TV khi được chọn. Với ứng dụng người gửi di động đi kèm, người dùng cũng có thể truyền video đến ứng dụng cho Android TV.

Hình ảnh một loạt hình thu nhỏ của video (một trong số đó được đánh dấu) phủ lên bản xem trước toàn màn hình của một video; từ "Cast Connect" xuất hiện ở phía trên bên phải

Đăng ký thiết bị dành cho nhà phát triển

Để bật các chức năng của Cast Connect cho quá trình phát triển ứng dụng, bạn phải đăng ký số sê-ri của Google Cast trên thiết bị Android TV mà bạn sẽ sử dụng trong Cast Developer Console. Bạn có thể tìm thấy số sê-ri bằng cách chuyển đến phần Cài đặt > Tuỳ chọn ưu tiên về thiết bị > Google Cast > Số sê-ri trên Android TV. Xin lưu ý rằng đây không phải là số sê-ri của thiết bị thực và bạn phải lấy số này bằng phương thức được mô tả ở trên.

Hình ảnh màn hình Android TV cho thấy màn hình "Google Cast", Số phiên bản và Số sê-ri

Nếu không đăng ký, Cast Connect sẽ chỉ hoạt động đối với các ứng dụng được cài đặt qua Cửa hàng Google Play vì lý do bảo mật. Sau 15 phút kể từ khi bắt đầu quá trình đăng ký, hãy khởi động lại thiết bị.

Cài đặt ứng dụng người gửi Android

Để kiểm thử việc gửi yêu cầu từ thiết bị di động, chúng tôi đã cung cấp một ứng dụng gửi đơn giản có tên là Cast Videos dưới dạng tệp mobile-sender-0629.apk trong tệp tải xuống zip mã nguồn. Chúng ta sẽ tận dụng ADB để cài đặt APK. Nếu bạn đã cài đặt một phiên bản khác của ứng dụng Cast Videos, vui lòng gỡ cài đặt phiên bản đó khỏi tất cả hồ sơ trên thiết bị trước khi tiếp tục.

  1. Bật tuỳ chọn cho nhà phát triển và gỡ lỗi qua USB trên điện thoại Android.
  2. Cắm cáp dữ liệu USB để kết nối điện thoại Android với máy tính bạn dùng để phát triển.
  3. Cài đặt mobile-sender-0629.apk vào điện thoại Android.

Hình ảnh về một cửa sổ thiết bị đầu cuối đang chạy lệnh adb install để cài đặt mobile-sender.apk

  1. Bạn có thể tìm thấy ứng dụng gửi Truyền video trên điện thoại Android. Biểu tượng ứng dụng gửi video truyền

Hình ảnh ứng dụng người gửi Video truyền đang chạy trên màn hình điện thoại Android

Cài đặt ứng dụng cho Android TV

Các hướng dẫn sau đây mô tả cách mở và chạy ứng dụng mẫu đã hoàn tất trong Android Studio:

  1. Chọn Import Project (Nhập dự án) trên màn hình chào mừng hoặc chọn File > New > Import Project... (Tệp > Mới > Nhập dự án...) trong trình đơn.
  2. Chọn thư mục biểu tượng thư mụcapp-done trong thư mục mã mẫu rồi nhấp vào OK.
  3. Nhấp vào File > Nút Đồng bộ hoá dự án với Gradle của Android App Studio Sync Project with Gradle Files (Tệp > Nút Đồng bộ hoá dự án với Gradle của Android App Studio Đồng bộ hoá dự án với các tệp Gradle).
  4. Bật tuỳ chọn cho nhà phát triển và gỡ lỗi qua USB trên thiết bị Android TV.
  5. Kết nối ADB với thiết bị Android TV, thiết bị sẽ xuất hiện trong Android Studio. Hình ảnh cho thấy thiết bị Android TV xuất hiện trên thanh công cụ Android Studio
  6. Nhấp vào nút Nút Run (Chạy) trên Android Studio, một hình tam giác màu xanh lục chỉ sang phảiRun (Chạy), bạn sẽ thấy ứng dụng ATV có tên là Cast Connect Codelab xuất hiện sau vài giây.

Hãy chơi Cast Connect bằng ứng dụng ATV

  1. Chuyển đến Màn hình chính của Android TV.
  2. Mở ứng dụng Cast Videos sender trên điện thoại Android. Nhấp vào nút Truyền Biểu tượng nút Truyền rồi chọn thiết bị ATV của bạn.
  3. Ứng dụng Cast Connect Codelab ATV sẽ được chạy trên ATV và nút Truyền trong ứng dụng người gửi sẽ cho biết rằng ứng dụng đã kết nối Biểu tượng nút Truyền có màu sắc đảo ngược.
  4. Chọn một video trong ứng dụng ATV và video đó sẽ bắt đầu phát trên ATV.
  5. Trên điện thoại di động, một bộ điều khiển thu nhỏ hiện xuất hiện ở cuối ứng dụng gửi. Bạn có thể dùng nút phát/tạm dừng để điều khiển việc phát.
  6. Chọn một video trên điện thoại di động rồi phát. Video sẽ bắt đầu phát trên ATV và bộ điều khiển mở rộng sẽ xuất hiện trên thiết bị di động gửi.
  7. Khoá điện thoại, sau đó mở khoá. Lúc này, bạn sẽ thấy một thông báo trên màn hình khoá để điều khiển chế độ phát nội dung nghe nhìn hoặc dừng truyền.

Hình ảnh một phần màn hình điện thoại Android có một trình phát thu nhỏ đang phát video

4. Chuẩn bị dự án khởi đầu

Giờ đây, sau khi xác minh quá trình tích hợp Cast Connect của ứng dụng đã hoàn tất, chúng ta cần thêm tính năng hỗ trợ Cast Connect vào ứng dụng khởi động mà bạn đã tải xuống. Bây giờ, bạn đã sẵn sàng xây dựng dựa trên dự án khởi đầu bằng Android Studio:

  1. Chọn Import Project (Nhập dự án) trên màn hình chào mừng hoặc chọn File > New > Import Project... (Tệp > Mới > Nhập dự án...) trong trình đơn.
  2. Chọn thư mục biểu tượng thư mụcapp-start trong thư mục mã mẫu rồi nhấp vào OK.
  3. Nhấp vào File > Nút Đồng bộ hoá dự án với Gradle của Android Studio Sync Project with Gradle Files (Tệp > Nút Đồng bộ hoá dự án với Gradle của Android Studio Đồng bộ hoá dự án với các tệp Gradle).
  4. Chọn thiết bị ATV rồi nhấp vào nút Nút Run (Chạy) của Android Studio, một hình tam giác màu xanh lục chỉ sang phảiRun (Chạy) để chạy ứng dụng và khám phá giao diện người dùng. Thanh công cụ Android Studio cho thấy thiết bị Android TV đã chọn

Hình ảnh một loạt hình thu nhỏ của video (một trong số đó được đánh dấu) phủ lên bản xem trước toàn màn hình của một video; từ "Cast Connect" xuất hiện ở phía trên bên phải

Thiết kế ứng dụng

Ứng dụng cung cấp một danh sách video để người dùng duyệt xem. Người dùng có thể chọn một video để phát trên Android TV. Ứng dụng này bao gồm 2 hoạt động chính: MainActivityPlaybackActivity.

MainActivity

Hoạt động này chứa một mảnh (MainFragment). Danh sách video và siêu dữ liệu liên kết được định cấu hình trong lớp MovieList và phương thức setupMovies() được gọi để tạo danh sách các đối tượng Movie.

Đối tượng Movie đại diện cho một thực thể video có tiêu đề, nội dung mô tả, hình thu nhỏ và URL của video. Mỗi đối tượng Movie được liên kết với một CardPresenter để trình bày hình thu nhỏ video kèm theo tiêu đề và hãng phim, đồng thời được truyền đến ArrayObjectAdapter.

Khi một mục được chọn, đối tượng Movie tương ứng sẽ được truyền đến PlaybackActivity.

PlaybackActivity

Hoạt động này chứa một Fragment (PlaybackVideoFragment) lưu trữ một VideoViewExoPlayer, một số nút điều khiển nội dung nghe nhìn và một vùng văn bản để hiện nội dung mô tả của video đã chọn, đồng thời cho phép người dùng phát video trên Android TV. Người dùng có thể dùng điều khiển từ xa để phát/tạm dừng hoặc tua video.

Điều kiện tiên quyết của Cast Connect

Cast Connect sử dụng các phiên bản mới của Dịch vụ Google Play. Các phiên bản này yêu cầu bạn phải cập nhật ứng dụng ATV để sử dụng không gian tên AndroidX.

Để hỗ trợ Cast Connect trong ứng dụng cho Android TV, bạn phải tạo và hỗ trợ các sự kiện từ một phiên nội dung đa phương tiện. Thư viện Cast Connect tạo trạng thái nội dung nghe nhìn dựa trên trạng thái của phiên nội dung nghe nhìn. Phiên phát nội dung nghe nhìn của bạn cũng được thư viện Cast Connect dùng để báo hiệu thời điểm nhận được một số thông báo nhất định từ người gửi, chẳng hạn như thông báo tạm dừng.

5. Định cấu hình tính năng hỗ trợ truyền

Phần phụ thuộc

Cập nhật tệp build.gradle của ứng dụng để thêm các phần phụ thuộc cần thiết của thư viện:

dependencies {
    ....

    // Cast Connect libraries
    implementation 'com.google.android.gms:play-services-cast-tv:20.0.0'
    implementation 'com.google.android.gms:play-services-cast:21.1.0'
}

Đồng bộ hoá dự án để xác nhận dự án tạo bản dựng mà không gặp lỗi.

Khởi chạy

CastReceiverContext là một đối tượng singleton để điều phối tất cả các lượt tương tác với Cast. Bạn phải triển khai giao diện ReceiverOptionsProvider để cung cấp CastReceiverOptions khi CastReceiverContext được khởi chạy.

Tạo tệp CastReceiverOptionsProvider.kt rồi thêm lớp sau vào dự án:

package com.google.sample.cast.castconnect

import android.content.Context
import com.google.android.gms.cast.tv.ReceiverOptionsProvider
import com.google.android.gms.cast.tv.CastReceiverOptions

class CastReceiverOptionsProvider : ReceiverOptionsProvider {
    override fun getOptions(context: Context): CastReceiverOptions {
        return CastReceiverOptions.Builder(context)
                .setStatusText("Cast Connect Codelab")
                .build()
    }
}

Sau đó, hãy chỉ định trình cung cấp các lựa chọn về bộ nhận trong thẻ <application> của tệp AndroidManifest.xml ứng dụng:

<application>
  ...
  <meta-data
    android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
    android:value="com.google.sample.cast.castconnect.CastReceiverOptionsProvider" />
</application>

Để kết nối với ứng dụng ATV từ thiết bị truyền, hãy chọn một hoạt động bạn muốn khởi chạy. Trong lớp học lập trình này, chúng ta sẽ khởi chạy MainActivity của ứng dụng khi một phiên truyền bắt đầu. Trong tệp AndroidManifest.xml, hãy thêm bộ lọc ý định khởi chạy vào MainActivity.

<activity android:name=".MainActivity">
  ...
  <intent-filter>
    <action android:name="com.google.android.gms.cast.tv.action.LAUNCH" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

Vòng đời của ngữ cảnh thiết bị nhận nội dung truyền

Bạn nên bắt đầu CastReceiverContext khi ứng dụng được khởi chạy và dừng CastReceiverContext khi ứng dụng chuyển sang chế độ nền. Bạn nên dùng LifecycleObserver trong thư viện androidx.lifecycle để quản lý việc gọi CastReceiverContext.start()CastReceiverContext.stop()

Mở tệp MyApplication.kt, khởi chạy ngữ cảnh truyền bằng cách gọi initInstance() trong phương thức onCreate của ứng dụng. Trong lớp AppLifeCycleObserver start(), CastReceiverContext khi ứng dụng tiếp tục và stop() khi ứng dụng tạm dừng:

package com.google.sample.cast.castconnect

import com.google.android.gms.cast.tv.CastReceiverContext
...

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        CastReceiverContext.initInstance(this)
        ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleObserver())
    }

    class AppLifecycleObserver : DefaultLifecycleObserver {
        override fun onResume(owner: LifecycleOwner) {
            Log.d(LOG_TAG, "onResume")
            CastReceiverContext.getInstance().start()
        }

        override fun onPause(owner: LifecycleOwner) {
            Log.d(LOG_TAG, "onPause")
            CastReceiverContext.getInstance().stop()
        }
    }
}

Kết nối MediaSession với MediaManager

MediaManager là một thuộc tính của singleton CastReceiverContext, thuộc tính này quản lý trạng thái nội dung nghe nhìn, xử lý ý định tải, dịch các thông báo không gian tên nội dung nghe nhìn từ người gửi thành các lệnh nội dung nghe nhìn và gửi trạng thái nội dung nghe nhìn trở lại cho người gửi.

Khi tạo một MediaSession, bạn cũng cần cung cấp mã thông báo MediaSession hiện tại cho MediaManager để biết nơi gửi các lệnh và truy xuất trạng thái phát nội dung nghe nhìn. Trong tệp PlaybackVideoFragment.kt, hãy đảm bảo MediaSession được khởi động trước khi đặt mã thông báo thành MediaManager.

import com.google.android.gms.cast.tv.CastReceiverContext
import com.google.android.gms.cast.tv.media.MediaManager
...

class PlaybackVideoFragment : VideoSupportFragment() {
    private var castReceiverContext: CastReceiverContext? = null
    ...

    private fun initializePlayer() {
        if (mPlayer == null) {
            ...
            mMediaSession = MediaSessionCompat(getContext(), LOG_TAG)
            ...
            castReceiverContext = CastReceiverContext.getInstance()
            if (castReceiverContext != null) {
                val mediaManager: MediaManager = castReceiverContext!!.getMediaManager()
                mediaManager.setSessionCompatToken(mMediaSession!!.getSessionToken())
            }

        }
    }
}

Khi phát hành MediaSession do không phát lại, bạn nên đặt mã thông báo rỗng trên MediaManager:

private fun releasePlayer() {
    mMediaSession?.release()
    castReceiverContext?.mediaManager?.setSessionCompatToken(null)
    ...
}

Hãy chạy ứng dụng mẫu

Nhấp vào nút Nút Run (Chạy) của Android Studio, một hình tam giác màu xanh lục chỉ sang phảiChạy để triển khai ứng dụng trên thiết bị ATV, đóng ứng dụng và quay lại Màn hình chính của ATV. Trên thiết bị gửi, hãy nhấp vào nút Truyền Biểu tượng nút Truyền rồi chọn thiết bị ATV. Bạn sẽ thấy ứng dụng ATV được khởi chạy trên thiết bị ATV và trạng thái nút Truyền là đã kết nối.

6. Đang tải nội dung nghe nhìn

Lệnh tải được gửi thông qua một ý định có tên gói mà bạn đã xác định trong Developer Console. Bạn cần thêm bộ lọc ý định được xác định trước sau đây vào ứng dụng cho Android TV để chỉ định hoạt động đích sẽ nhận được ý định này. Trong tệp AndroidManifest.xml, hãy thêm bộ lọc ý định tải vào PlayerActivity:

<activity android:name="com.google.sample.cast.castconnect.PlaybackActivity"
          android:launchMode="singleTask"
          android:exported="true">
  <intent-filter>
     <action android:name="com.google.android.gms.cast.tv.action.LOAD"/>
     <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

Xử lý các yêu cầu tải trên Android TV

Bây giờ, khi hoạt động được định cấu hình để nhận ý định này chứa yêu cầu tải, chúng ta sẽ cần xử lý yêu cầu đó.

Ứng dụng gọi một phương thức riêng tư có tên là processIntent khi hoạt động bắt đầu. Phương thức này chứa logic để xử lý các ý định đến. Để xử lý yêu cầu tải, chúng ta sẽ sửa đổi phương thức này và gửi ý định để được xử lý thêm bằng cách gọi phương thức onNewIntent của thực thể MediaManager. Nếu MediaManager phát hiện ý định là một yêu cầu tải, thì nó sẽ trích xuất đối tượng MediaLoadRequestData từ ý định và gọi MediaLoadCommandCallback.onLoad(). Sửa đổi phương thức processIntent trong tệp PlaybackVideoFragment.kt để xử lý ý định chứa yêu cầu tải:

fun processIntent(intent: Intent?) {
    val mediaManager: MediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass intent to Cast SDK
    if (mediaManager.onNewIntent(intent)) {
        return
    }

    // Clears all overrides in the modifier.
    mediaManager.getMediaStatusModifier().clear()

    // If the SDK doesn't recognize the intent, handle the intent with your own logic.
    ...
}

Tiếp theo, chúng ta sẽ mở rộng lớp trừu tượng MediaLoadCommandCallback. Lớp này sẽ ghi đè phương thức onLoad() do MediaManager gọi. Phương thức này nhận dữ liệu của yêu cầu tải và chuyển đổi dữ liệu đó thành một đối tượng Movie. Sau khi chuyển đổi, bộ phim sẽ được phát bằng trình phát cục bộ. Sau đó, MediaManager sẽ được cập nhật bằng MediaLoadRequest và phát MediaStatus cho những người gửi được kết nối. Tạo một lớp riêng tư lồng nhau có tên là MyMediaLoadCommandCallback trong tệp PlaybackVideoFragment.kt:

import com.google.android.gms.cast.MediaLoadRequestData
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.cast.MediaError
import com.google.android.gms.cast.tv.media.MediaException
import com.google.android.gms.cast.tv.media.MediaCommandCallback
import com.google.android.gms.cast.tv.media.QueueUpdateRequestData
import com.google.android.gms.cast.tv.media.MediaLoadCommandCallback
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import android.widget.Toast
...

private inner class MyMediaLoadCommandCallback :  MediaLoadCommandCallback() {
    override fun onLoad(
        senderId: String?, mediaLoadRequestData: MediaLoadRequestData): Task<MediaLoadRequestData> {
        Toast.makeText(activity, "onLoad()", Toast.LENGTH_SHORT).show()
        return if (mediaLoadRequestData == null) {
            // Throw MediaException to indicate load failure.
            Tasks.forException(MediaException(
                MediaError.Builder()
                    .setDetailedErrorCode(MediaError.DetailedErrorCode.LOAD_FAILED)
                    .setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
                    .build()))
        } else Tasks.call {
            play(convertLoadRequestToMovie(mediaLoadRequestData)!!)
            // Update media metadata and state
            val mediaManager = castReceiverContext!!.mediaManager
            mediaManager.setDataFromLoad(mediaLoadRequestData)
            mediaLoadRequestData
        }
    }
}

private fun convertLoadRequestToMovie(mediaLoadRequestData: MediaLoadRequestData?): Movie? {
    if (mediaLoadRequestData == null) {
        return null
    }
    val mediaInfo: MediaInfo = mediaLoadRequestData.getMediaInfo() ?: return null
    var videoUrl: String = mediaInfo.getContentId()
    if (mediaInfo.getContentUrl() != null) {
        videoUrl = mediaInfo.getContentUrl()
    }
    val metadata: MediaMetadata = mediaInfo.getMetadata()
    val movie = Movie()
    movie.videoUrl = videoUrl
    movie.title = metadata?.getString(MediaMetadata.KEY_TITLE)
    movie.description = metadata?.getString(MediaMetadata.KEY_SUBTITLE)
    if(metadata?.hasImages() == true) {
        movie.cardImageUrl = metadata.images[0].url.toString()
    }
    return movie
}

Bây giờ, sau khi xác định Callback, chúng ta cần đăng ký Callback này với MediaManager. Bạn phải đăng ký lệnh gọi lại trước khi gọi MediaManager.onNewIntent(). Thêm setMediaLoadCommandCallback khi trình phát được khởi chạy:

private fun initializePlayer() {
    if (mPlayer == null) {
        ...
        mMediaSession = MediaSessionCompat(getContext(), LOG_TAG)
        ...
        castReceiverContext = CastReceiverContext.getInstance()
        if (castReceiverContext != null) {
            val mediaManager: MediaManager = castReceiverContext.getMediaManager()
            mediaManager.setSessionCompatToken(mMediaSession.getSessionToken())
            mediaManager.setMediaLoadCommandCallback(MyMediaLoadCommandCallback())
        }
    }
}

Hãy chạy ứng dụng mẫu

Nhấp vào nút Nút Run (Chạy) của Android Studio, một hình tam giác màu xanh lục chỉ sang phảiRun (Chạy) để triển khai ứng dụng trên thiết bị ATV. Trên thiết bị gửi, hãy nhấp vào nút Truyền Biểu tượng nút Truyền rồi chọn thiết bị ATV. Ứng dụng ATV sẽ được khởi chạy trên thiết bị ATV. Chọn một video trên thiết bị di động, video đó sẽ bắt đầu phát trên ATV. Kiểm tra xem bạn có nhận được thông báo trên điện thoại có các nút điều khiển phát hay không. Hãy thử dùng các nút điều khiển như tạm dừng. Video trên thiết bị ATV sẽ tạm dừng.

7. Hỗ trợ các lệnh điều khiển truyền

Ứng dụng hiện tại hiện hỗ trợ các lệnh cơ bản tương thích với một phiên nội dung nghe nhìn, chẳng hạn như phát, tạm dừng và tìm kiếm. Tuy nhiên, có một số lệnh điều khiển truyền không có trong phiên nội dung nghe nhìn. Bạn cần đăng ký một MediaCommandCallback để hỗ trợ các lệnh điều khiển truyền đó.

Thêm MyMediaCommandCallback vào thực thể MediaManager bằng cách sử dụng setMediaCommandCallback khi trình phát được khởi động:

private fun initializePlayer() {
    ...
    castReceiverContext = CastReceiverContext.getInstance()
    if (castReceiverContext != null) {
        val mediaManager = castReceiverContext!!.mediaManager
        ...
        mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
    }
}

Tạo lớp MyMediaCommandCallback để ghi đè các phương thức, chẳng hạn như onQueueUpdate() để hỗ trợ các lệnh điều khiển truyền sau:

private inner class MyMediaCommandCallback : MediaCommandCallback() {
    override fun onQueueUpdate(
        senderId: String?,
        queueUpdateRequestData: QueueUpdateRequestData
    ): Task<Void> {
        Toast.makeText(getActivity(), "onQueueUpdate()", Toast.LENGTH_SHORT).show()
        // Queue Prev / Next
        if (queueUpdateRequestData.getJump() != null) {
            Toast.makeText(
                getActivity(),
                "onQueueUpdate(): Jump = " + queueUpdateRequestData.getJump(),
                Toast.LENGTH_SHORT
            ).show()
        }
        return super.onQueueUpdate(senderId, queueUpdateRequestData)
    }
}

8. Làm việc với trạng thái nội dung nghe nhìn

Sửa đổi trạng thái nội dung nghe nhìn

Cast Connect lấy trạng thái cơ bản của nội dung nghe nhìn từ phiên nội dung nghe nhìn. Để hỗ trợ các tính năng nâng cao, ứng dụng cho Android TV có thể chỉ định và ghi đè các thuộc tính trạng thái bổ sung thông qua một MediaStatusModifier. MediaStatusModifier sẽ luôn hoạt động trên MediaSession mà bạn đã đặt trong CastReceiverContext.

Ví dụ: để chỉ định setMediaCommandSupported khi lệnh gọi lại onLoad được kích hoạt:

import com.google.android.gms.cast.MediaStatus
...
private class MyMediaLoadCommandCallback : MediaLoadCommandCallback() {
    fun onLoad(
        senderId: String?,
        mediaLoadRequestData: MediaLoadRequestData
    ): Task<MediaLoadRequestData> {
        Toast.makeText(getActivity(), "onLoad()", Toast.LENGTH_SHORT).show()
        ...
        return Tasks.call({
            play(convertLoadRequestToMovie(mediaLoadRequestData)!!)
            ...
            // Use MediaStatusModifier to provide additional information for Cast senders.
            mediaManager.getMediaStatusModifier()
                .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT, true)
                .setIsPlayingAd(false)
            mediaManager.broadcastMediaStatus()
            // Return the resolved MediaLoadRequestData to indicate load success.
            mediaLoadRequestData
        })
    }
}

Chặn MediaStatus trước khi gửi

Tương tự như MessageInterceptor của Web Receiver SDK, bạn có thể chỉ định MediaStatusWriter trong MediaManager để thực hiện các sửa đổi bổ sung cho MediaStatus trước khi phát đến các thiết bị gửi đã kết nối.

Ví dụ: bạn có thể đặt dữ liệu tuỳ chỉnh trong MediaStatus trước khi gửi cho người gửi trên thiết bị di động:

import com.google.android.gms.cast.tv.media.MediaManager.MediaStatusInterceptor
import com.google.android.gms.cast.tv.media.MediaStatusWriter
import org.json.JSONObject
import org.json.JSONException
...

private fun initializePlayer() {
    if (mPlayer == null) {
        ...
        if (castReceiverContext != null) {
            ...
            val mediaManager: MediaManager = castReceiverContext.getMediaManager()
            ...
            // Use MediaStatusInterceptor to process the MediaStatus before sending out.
            mediaManager.setMediaStatusInterceptor(
                MediaStatusInterceptor { mediaStatusWriter: MediaStatusWriter ->
                    try {
                        mediaStatusWriter.setCustomData(JSONObject("{myData: 'CustomData'}"))
                    } catch (e: JSONException) {
                        Log.e(LOG_TAG,e.message,e);
                    }
            })
        }
    }
}        

9. Xin chúc mừng

Giờ đây, bạn đã biết cách bật tính năng Hỗ trợ Cast cho ứng dụng Android TV bằng Thư viện Cast Connect.

Hãy xem hướng dẫn cho nhà phát triển để biết thêm thông tin chi tiết: /cast/docs/android_tv_receiver.