הפעלה של אפליקציית Android TV

קל לארגן דפים בעזרת אוספים אפשר לשמור ולסווג תוכן על סמך ההעדפות שלך.

1. סקירה כללית

הלוגו של Google Cast

ה-Codelab הזה ילמד אתכם איך לשנות אפליקציה קיימת ב-Android TV, כדי לתמוך בהעברה (cast) ובתקשורת מאפליקציות Chrome קיימות.

מה זה Google Cast ו-Cast Connect?

Google Cast מאפשר למשתמשים להעביר תוכן מהנייד לטלוויזיה. סשן אופייני ב-Google Cast מורכב משני רכיבים – שולח ואפליקציית מקבל. אפליקציות שולח, כמו אפליקציה לנייד או אתר כמו youtube.com, מעודדות הפעלה של אפליקציית רסיבר (cast) ושולטות בה. אפליקציות מקלט העברה הן אפליקציות HTML 5 שפועלות במכשירי Chromecast ו-Android TV.

כמעט כל המדינה בסשן העברה (cast) מאוחסנת באפליקציית המקבל. כאשר המדינה מתעדכנת, למשל, אם פריט מדיה חדש נטען, סטטוס מדיה משודר לכל השולחים. שידורים אלה מכילים את המצב הנוכחי של פעילות ההעברה. אפליקציות של שולחים משתמשות בסטטוס המדיה הזה כדי להציג מידע על הפעלה בממשק המשתמש שלהן.

Cast Connect נשען על התשתית הזו, ואפליקציית Android TV פועלת כמקלט. ספריית Cast Connect מאפשרת לאפליקציה ל-Android TV לקבל הודעות, ולשדר את סטטוס המדיה, כאילו היא אפליקציה למקלט העברה.

מה תכננת לבנות?

לאחר השלמת ה-Codelab הזה, תוכלו להשתמש באפליקציות של שליחת Cast כדי להעביר סרטונים לאפליקציית Android TV. אפליקציית Android TV גם יכולה לתקשר עם אפליקציות של שולחים באמצעות פרוטוקול Cast.

מה תלמדו

  • איך להוסיף את הספרייה של Cast Connect לאפליקציית טרקטורונים לדוגמה.
  • איך לחבר שולח Cast ולהפעיל את האפליקציה לטרקטורון.
  • איך להפעיל הפעלה של מדיה באפליקציית ATV מאפליקציית שולח CAST.
  • איך לשלוח סטטוס מדיה מאפליקציית ATV לאפליקציות של שליחת Cast.

מה הדרישות כדי להצטרף לתוכנית?

2. קבל את הקוד לדוגמה

אפשר להוריד למחשב את כל הקוד לדוגמה...

ופרקים את קובץ ה-ZIP שהורדתם.

3. הרצת האפליקציה לדוגמה

קודם צריך לבדוק איך האפליקציה לדוגמה מסתיימת. האפליקציה Android TV משתמשת בממשק המשתמש BrailleBack ובנגן וידאו בסיסי. המשתמש יכול לבחור סרטון מתוך רשימה המופעלת בטלוויזיה לאחר בחירתה. באמצעות האפליקציה המלווה לנייד, המשתמש יכול גם להעביר סרטון לאפליקציית Android TV.

תמונה של סדרת תמונות ממוזערות של סרטונים (שאחת מהן מודגשת) מוצגת כתצוגה מקדימה במסך מלא של סרטון; המילים 'העברה (cast)' מופיעות בפינה השמאלית העליונה

רישום של מכשירי פיתוח

כדי להפעיל את יכולות Cast Connect לפיתוח אפליקציות, עליך לרשום את המספר הסידורי של ה-Chromecast המובנה של מכשיר ה-Android TV שבו ברצונך להשתמש במסוף Cast Cast. כדי למצוא את המספר הסידורי, עוברים אל הגדרות > העדפות מכשיר > Chromecast מובנה > מספר סידורי ב-Android TV. חשוב לזכור שהמספר הזה שונה מהמספר הסידורי של המכשיר הפיזי, וצריך לקבל אותו מהשיטה שמתוארת למעלה.

תמונה של מסך Android TV שבו מוצגים המסך 'Chromecast Built-In' מספר הגרסה ומספר הסידורי

ללא רישום, אפליקציית Cast Connect תפעל רק באפליקציות שהותקנו מחנות Google Play מסיבות אבטחה. לאחר 15 דקות מתחילת תהליך הרישום, יש להפעיל מחדש את המכשיר.

יש להתקין את אפליקציית השולח ל-Android

כדי לבדוק בקשות שליחה ממכשיר נייד, סיפקנו אפליקציית שליחה פשוטה שנקראת 'העברת סרטונים' כקובץ mobile-sender-0629.apk בקוד ההורדה של קוד המקור. אנחנו נמנף את ADB כדי להתקין את ה-APK. אם כבר התקנת גרסה אחרת של סרטוני Cast, עליך להסיר את הגרסה הזו מכל הפרופילים הנמצאים במכשיר לפני המשך התהליך.

  1. מפעילים אפשרויות למפתחים וניפוי באגים ב-USB בטלפון Android.
  2. מחברים את כבל הנתונים של ה-USB כדי לחבר את טלפון Android למחשב הפיתוח.
  3. מתקינים את mobile-sender-0629.apk בטלפון Android.

תמונה של חלון טרמינל שמריצים את פקודת ההתקנה של adb, כדי להתקין את mobile-sender.APK

  1. ניתן למצוא את אפליקציית השולח העברה של סרטונים בטלפון Android. סמל של אפליקציית שליחת סרטונים בהעברה

תמונה של אפליקציית השולח 'סרטונים בהעברה' המופעלת במסך טלפון Android

מתקינים את אפליקציית Android TV

בהוראות הבאות מתואר איך לפתוח ולהפעיל את האפליקציה לדוגמה ב-Android Studio:

  1. בוחרים באפשרות Import Project (ייבוא פרויקט) או בתפריט File > New > Import Project....
  2. מאתרים את הספרייה סמל תיקייהapp-done מהתיקייה של הקוד לדוגמה ולוחצים על 'אישור'.
  3. לוחצים על קובץ > Android Sync Studio's Project עם לחצן Gradle סנכרון פרויקט עם קובצי Gradle.
  4. מפעילים את האפשרויות למפתחים וניפוי באגים ב-USB במכשיר ה-Android TV.
  5. אפליקציית ADB מתחברת למכשיר ה-Android TV שלכם, והמכשיר אמור להופיע ב-Android Studio. תמונה המציגה את מכשיר ה-Android TV שמופיע בסרגל הכלים של Android Studio
  6. לוחצים על הלחצן לחצן להפעלת Android Studio, משולש ירוק שמצביע ימינההפעלה, שאמורים להופיע האפליקציה ATV שנקראת Cast Connect Codelab אחרי כמה שניות.

רוצה לשחק ב-Cast Connect באמצעות אפליקציית ATV?

  1. עוברים למסך הבית של Android TV.
  2. פותחים את אפליקציית השולח 'סרטונים להעברה' בטלפון Android. לוחצים על לחצן ההעברה סמל של לחצן הפעלת Cast ובוחרים את מכשיר הטרקטורון.
  3. אפליקציית Cast Connect Codelab ATV תופעל בטרקטורון, ולחצן ההעברה בשולח יציין שהוא מחובר סמל של לחצן העברה (cast) בצבעים.
  4. בוחרים סרטון מאפליקציית ATV, והסרטון יתחיל לפעול בטרקטורון.
  5. בטלפון הנייד שלך, מיני שלט רחוק גלוי עכשיו בחלק התחתון של אפליקציית השולח. אפשר להשתמש בלחצן ההפעלה/השהיה כדי לשלוט בהפעלה.
  6. בוחרים סרטון מהטלפון הנייד ומפעילים אותו. הסרטון יתחיל לפעול בטרקטורון, והבקר המורחב יוצג אצל השולח בנייד.
  7. לנעול את הטלפון וכשמבטלים את הנעילה שלו, אמורה להופיע התראה במסך הנעילה כדי לשלוט בהפעלת המדיה או להפסיק את ההעברה.

תמונה של קטע של מסך טלפון Android עם מיני-נגן שמפעיל סרטון

4. מכינים את פרויקט ההתחלה

עכשיו, אחרי שאימתנו את השילוב הושלם של Cast Connect, אנחנו צריכים להוסיף תמיכה ב-Cast Connect לאפליקציית ההתחלה שהורדתם. עכשיו אפשר לבנות מעל הפרויקט למתחילים באמצעות Android Studio:

  1. בוחרים באפשרות Import Project (ייבוא פרויקט) או בתפריט File > New > Import Project....
  2. מאתרים את הספרייה סמל תיקייהapp-start מהתיקייה של הקוד לדוגמה ולוחצים על 'אישור'.
  3. לוחצים על קובץ > Android Sync&33;s Project עם לחצן Gradle סנכרון פרויקט עם קובצי Gradle.
  4. בוחרים מכשיר טרקטורונים ולוחצים על הלחצן לחצן הפעלה של Android Studio& 33, משולש ירוק שמצביע ימינההפעלה כדי להפעיל את האפליקציה ולעיין בממשק המשתמש. סרגל הכלים של Android Studio שבו מוצג מכשיר ה-Android TV שנבחר

תמונה של סדרת תמונות ממוזערות של סרטונים (שאחת מהן מודגשת) מוצגת כתצוגה מקדימה במסך מלא של סרטון; המילים 'העברה (cast)' מופיעות בפינה השמאלית העליונה

עיצוב אפליקציות

האפליקציה מספקת רשימה של סרטונים עבור המשתמש. משתמשים יכולים לבחור סרטון להפעלה ב-Android TV. האפליקציה מורכבת משתי פעילויות עיקריות: MainActivity וPlaybackActivity.

MainActivity

פעילות זו מכילה שבר (MainFragment). רשימת הסרטונים והמטא נתונים המשויכים אליהם מוגדרים בכיתה MovieList, ושיטת setupMovies() נקראת לבניית רשימה של אובייקטים מסוג Movie.

אובייקט Movie מייצג ישות וידאו בעלת שם, תיאור, תמונות ממוזערות וכתובת URL של סרטון. כל אובייקט Movie קשור אל CardPresenter כדי להציג את התמונה הממוזערת של הסרטון עם השם והסטודיו ולהעביר אל ArrayObjectAdapter.

כשבוחרים פריט, האובייקט התואם Movie מועבר אל PlaybackActivity.

פעילות הפעלה

פעילות זו מכילה שבר (PlaybackVideoFragment) שמארח VideoView עם ExoPlayer, פקדי מדיה ואזור טקסט כדי להציג את תיאור הסרטון שנבחר ומאפשר למשתמש להפעיל את הסרטון ב-Android TV. המשתמש יכול להשתמש בשלט הרחוק כדי להפעיל/להשהות או לבקש הפעלה של סרטונים.

דרישות מוקדמות ל-Cast Connect

ב-Cast Connect נעשה שימוש בגרסאות חדשות של שירותי Google Play שדורשות עדכון של אפליקציית הטרקטורון כדי להשתמש במרחב השמות AndroidX.

כדי לתמוך ב-Cast Connect באפליקציית Android TV, עליכם ליצור אירועים ולתמוך בהם מסשן מדיה. ספריית Cast Connect יוצרת סטטוס מדיה על סמך הסטטוס של סשן המדיה. ספריית המדיה משתמשת גם בסשן המדיה שלכם כדי לציין מתי היא קיבלה הודעות מסוימות משולח, כמו השהיה.

5. הגדרת תמיכה בהעברה

יחסי תלות

צריך לעדכן את קובץ האפליקציה build.gradle כך שיכלול את יחסי התלות הנדרשים של הספרייה:

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'
}

צריך לסנכרן את הפרויקט כדי לאשר את יצירת הפרויקט ללא שגיאות.

אתחול

CastReceiverContext הוא אובייקט יחיד שמשמש לתיאום כל האינטראקציות עם Cast. עליך ליישם את הממשק ReceiverOptionsProvider כדי לספק את CastReceiverOptions כש-CastReceiverContext מופעל.

יצירה של קובץ CastReceiverOptionsProvider.kt והוספת הכיתה הבאה לפרויקט:

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()
    }
}

לאחר מכן צריך לציין את ספק האפשרויות של המקלט בתג <application> של קובץ האפליקציה AndroidManifest.xml:

<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>

כדי להתחבר לאפליקציית ATV משולח ההעברה, בוחרים פעילות שרוצים להפעיל. בשיעור Lab זה, נשיק את MainActivity של האפליקציה כשיתחיל סשן העברה. בקובץ AndroidManifest.xml, מוסיפים את המסנן 'כוונת השקה' 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>

מחזור החיים של הקשר במקלט ההעברה

יש להפעיל את CastReceiverContext כשהאפליקציה מופעלת ולהפסיק את CastReceiverContext כשהאפליקציה מועברת לרקע. כדי לנהל את השיחות CastReceiverContext.start() ו-CastReceiverContext.stop() מומלץ להשתמש בLifecycleObserver מהספרייה androidx.lifecycle

יש לפתוח את הקובץ MyApplication.kt, כדי להפעיל את ההקשר של ההעברה באמצעות קריאה ל-initInstance() בשיטה onCreate של האפליקציה. במחלקה AppLifeCycleObserver start() CastReceiverContext כשההפעלה מחדש של הבקשה ו-stop() עבורה כשהאפליקציה מושהית:

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()
        }
    }
}

חיבור MediaSession אל MediaManager

MediaManager הוא נכס של הסינגל CastReceiverContext, הוא מנהל את סטטוס המדיה, מטפל בכוונת הטעינה, מתרגם את הודעות מרחב השמות של המדיה משולחים לפקודות מדיה ושולח את סטטוס המדיה בחזרה לשולחים.

כשיוצרים MediaSession, צריך לספק גם את אסימון MediaSession הנוכחי ל-MediaManager כדי לדעת לאן לשלוח את הפקודות ולאחזר את מצב הפעלת המדיה. בקובץ PlaybackVideoFragment.kt, יש לוודא שהאתחול של MediaSession מתבצע לפני שמגדירים את האסימון כ-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())
            }

        }
    }
}

כשמשחררים את MediaSession עקב הפעלה לא פעילה, צריך להגדיר אסימון null ב-MediaManager:

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

רוצה להפעיל את האפליקציה לדוגמה?

לוחצים על הלחצן לחצן הפעלה של Android Studio& 33, משולש ירוק שמצביע ימינההפעלה כדי לפרוס את האפליקציה במכשיר הטלוויזיה, לסגור את האפליקציה ולחזור למסך הבית של ATV. מהשולח, לוחצים על לחצן ההעברה סמל של לחצן הפעלת Cast ובוחרים את מכשיר הטרקטורון. תופיע האפליקציה 'טרקטורון' במכשיר ה-ATV והמצב של לחצן ההעברה מחובר.

6. המדיה בטעינה

פקודת הטעינה נשלחת באמצעות כוונה עם שם החבילה שהגדרת במסוף המפתחים. עליכם להוסיף את מסנן Intent הבא שהוגדר מראש באפליקציית Android TV כדי לציין את פעילות היעד שיקבלה את הכוונה הזו. בקובץ AndroidManifest.xml, מוסיפים את המסנן 'כוונת טעינה' ל-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>

טיפול בבקשות לעומס ב-Android TV

עכשיו, לאחר שהפעילות מוגדרת לקבלת כוונה זו, הכוללת בקשת טעינה, נצטרך לטפל בה.

האפליקציה תתחיל להשתמש בשיטה פרטית שנקראת processIntent כשהפעילות תתחיל. השיטה הזו משלבת את הלוגיקה לעיבוד כוונות נכנסות. כדי לטפל בבקשת טעינה, נשנה את השיטה הזו ונשלח את הבקשה לעיבוד נוסף באמצעות קריאה לשיטה onNewIntent של המכונה MediaManager. אם המדיניות MediaManager מזהה את הכוונה היא בקשת טעינה, היא מחלצת את האובייקט MediaLoadRequestData מתוך כוונת הרכישה ומפעילה את MediaLoadCommandCallback.onLoad(). יש לשנות את השיטה processIntent בקובץ PlaybackVideoFragment.kt כדי לטפל בכוונה שמכילה את בקשת הטעינה:

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.
    ...
}

בשלב הבא, נרחיב את הכיתה המופשטת MediaLoadCommandCallback שתגרום לביטול של שיטת onLoad() שנקראת MediaManager. שיטה זו מקבלת את נתוני בקשת הטעינה וממירה אותה לאובייקט Movie. לאחר ההמרה, הסרט מופעל על ידי הנגן המקומי. לאחר מכן, MediaManager מעודכן במספר MediaLoadRequest ושולח את MediaStatus לכל השולחים המחוברים. אתם יכולים ליצור מחלקה פרטית מקננת בשם MyMediaLoadCommandCallback בקובץ 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
}

עכשיו, לאחר הגדרת השיחה החוזרת, עלינו לרשום אותה ב-MediaManager. יש להתקשר למוקד החוזר לפני שמתקשרים אל MediaManager.onNewIntent(). הוספת setMediaLoadCommandCallback כשהנגן מופעל:

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())
        }
    }
}

רוצה להפעיל את האפליקציה לדוגמה?

לוחצים על הלחצן לחצן הפעלה של Android Studio& 33, משולש ירוק שמצביע ימינההפעלה כדי לפרוס את האפליקציה במכשיר הטרקטורון. מהשולח, לוחצים על לחצן ההעברה סמל של לחצן הפעלת Cast ובוחרים את מכשיר הטרקטורון. אפליקציית ATV תופעל במכשיר הטרקטורון. בוחרים סרטון בנייד. הוא יתחיל לפעול בטרקטורון. בודקים אם מתקבלת התראה בטלפון שבו יש פקדי הפעלה. מנסים להשתמש בפקדים כמו השהיה, צריך להשהות את הסרטון במכשיר הטרקטורון.

7. פקודות לשליטה בהעברה (cast)

האפליקציה הנוכחית תומכת עכשיו בפקודות בסיסיות שתואמות לסשן במדיה, כמו הפעלה, השהיה וחיפוש. עם זאת, יש פקודות מסוימות של העברה (cast) שלא זמינות בסשן המדיה. עליך לרשום MediaCommandCallback כדי לתמוך בפקודות הבקרה האלה להעברה.

צריך להוסיף את MyMediaCommandCallback למופע של MediaManager באמצעות setMediaCommandCallback כשהנגן מופעל:

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

יצירת מחלקה MyMediaCommandCallback כדי לבטל את השיטות, כמו onQueueUpdate(), לצורך תמיכה בפקודות הבקרה של Cast:

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. עבודה עם סטטוס מדיה

שינוי סטטוס המדיה

העברה (cast) מקבלת את סטטוס המדיה הבסיסית בסשן המדיה. כדי לתמוך בתכונות מתקדמות, האפליקציה שלך ל-Android TV יכולה לציין ולשנות מאפייני סטטוס נוספים באמצעות MediaStatusModifier. MediaStatusModifier תמיד תפעל ב-MediaSession שהגדרת ב-CastReceiverContext.

לדוגמה, כדי לציין את setMediaCommandSupported כשהשיחה החוזרת מסוג onLoad מופעלת:

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
        })
    }
}

מחיקת סטטוס מדיה לפני שליחה

בדומה ל-SDK של מקלט האינטרנט MessageInterceptor, אפשר לציין MediaStatusWriter ב-MediaManager כדי לבצע שינויים נוספים ב-MediaStatus לפני שליחתו לשולחים המחוברים.

לדוגמה, אפשר להגדיר נתונים מותאמים אישית ב-MediaStatus לפני ששולחים לשולחים לנייד:

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. מזל טוב

עכשיו אתם יודעים איך להעביר אפליקציה ל-Android TV באמצעות ספריית החיבור ל-Cast.

פרטים נוספים זמינים במדריך למפתחים: /cast/docs/android_tv_receiptr.