Включение Cast в приложении Android TV

1. Обзор

Логотип Google Cast

Эта лаборатория научит вас, как изменить существующее приложение Android TV для поддержки трансляции и связи из существующих приложений Cast Sender.

Что такое Google Cast и Cast Connect?

Google Cast позволяет пользователям транслировать контент с мобильного устройства на телевизор. Типичный сеанс Google Cast состоит из двух компонентов — приложения-отправителя и приложения- получателя . Приложения-отправители, такие как мобильное приложение или веб-сайт, например Youtube.com, инициируют и управляют воспроизведением приложения-приемника Cast. Приложения Cast-приемника — это приложения HTML 5, которые работают на устройствах Chromecast и Android TV.

Почти все состояние сеанса Cast хранится в приложении-получателе. Когда состояние обновляется, например, если загружается новый элемент мультимедиа, статус мультимедиа передается всем отправителям. Эти трансляции содержат текущее состояние сеанса Cast. Приложения-отправители используют этот статус мультимедиа для отображения информации о воспроизведении в своем пользовательском интерфейсе.

Cast Connect построен на основе этой инфраструктуры, а ваше приложение Android TV выступает в качестве приемника. Библиотека Cast Connect позволяет вашему приложению Android TV получать сообщения и транслировать статус мультимедиа, как если бы это было приложение-приемник трансляции.

Что мы собираемся строить?

После завершения этой лабораторной работы вы сможете использовать приложения Cast Sender для трансляции видео в приложение Android TV. Приложение Android TV также может взаимодействовать с приложениями-отправителями через протокол Cast.

Что вы узнаете

  • Как добавить библиотеку Cast Connect в образец приложения ATV.
  • Как подключить отправитель Cast и запустить приложение ATV.
  • Как запустить воспроизведение мультимедиа в приложении ATV из приложения Cast sender.
  • Как отправить статус мультимедиа из приложения ATV в приложения-отправители Cast.

Что вам понадобится

2. Получите пример кода

Вы можете загрузить весь пример кода на свой компьютер...

и распакуйте загруженный zip-файл.

3. Запустите пример приложения.

Сначала давайте посмотрим, как выглядит готовый пример приложения. Приложение Android TV использует пользовательский интерфейс Leanback и базовый видеоплеер. Пользователь может выбрать видео из списка, которое затем воспроизводится на телевизоре при выборе. С помощью прилагаемого мобильного приложения-отправителя пользователь также может транслировать видео в приложение Android TV.

Изображение серии миниатюр видео (один из которых выделен), наложенных на полноэкранный предварительный просмотр видео; слова «Cast Connect» появляются в правом верхнем углу

Регистрация устройств разработчика

Чтобы включить возможности Cast Connect для разработки приложений, вам необходимо зарегистрировать серийный номер встроенного Chromecast устройства Android TV, который вы собираетесь использовать, в консоли разработчика Cast . Вы можете найти серийный номер, выбрав «Настройки» > «Настройки устройства» > «Встроенный Chromecast» > «Серийный номер» на вашем Android TV. Обратите внимание, что он отличается от серийного номера вашего физического устройства и должен быть получен методом, описанным выше.

Изображение экрана Android TV со встроенным экраном Chromecast, номером версии и серийным номером.

Без регистрации Cast Connect будет работать только с приложениями, установленными из Google Play Store, из соображений безопасности. Через 15 минут после начала процесса регистрации перезагрузите устройство.

Установите Android-приложение отправителя.

Чтобы протестировать отправку запросов с мобильного устройства, мы предоставили простое приложение-отправитель под названием Cast Videos в виде файла mobile-sender-0629.apk в zip-архиве с исходным кодом. Мы будем использовать ADB для установки APK. Если вы уже установили другую версию Cast Videos, удалите эту версию из всех профилей, расположенных на устройстве, прежде чем продолжить.

  1. Включите параметры разработчика и отладку по USB на своем телефоне Android.
  2. Подключите USB-кабель для передачи данных, чтобы соединить телефон Android с компьютером для разработки.
  3. Установите mobile-sender-0629.apk на свой телефон Android.

Изображение окна терминала, в котором выполняется команда установки adb для установки mobile-sender.apk

  1. Вы можете найти приложение отправителя Cast Videos на своем телефоне Android. Значок приложения отправителя Cast Videos

Изображение приложения-отправителя Cast Videos, работающего на экране телефона Android

Установите приложение Android TV.

Следующие инструкции описывают, как открыть и запустить готовый пример приложения в Android Studio:

  1. Выберите «Импорт проекта» на экране приветствия или пункты меню «Файл» > «Создать» > «Импортировать проект...» .
  2. Выберите значок папки app-done из папки примера кода и нажмите «ОК».
  3. Нажмите Файл > Проект синхронизации Android App Studio с кнопкой 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. Откройте приложение-отправитель Cast Videos на своем телефоне Android. Нажмите кнопку Трансляция Значок кнопки трансляции и выберите устройство ATV.
  3. Приложение Cast Connect Codelab ATV будет запущено на вашем квадроцикле, и кнопка Cast на отправителе укажет, что оно подключено. Значок кнопки трансляции с инвертированными цветами .
  4. Выберите видео в приложении ATV, и оно начнет воспроизводиться на вашем квадроцикле.
  5. На вашем мобильном телефоне в нижней части приложения-отправителя теперь виден мини-контроллер. Вы можете использовать кнопку воспроизведения/паузы для управления воспроизведением.
  6. Выберите видео с мобильного телефона и воспроизведите. Видео начнет воспроизводиться на вашем квадроцикле, а расширенный контроллер отобразится на вашем мобильном отправителе.
  7. Заблокируйте свой телефон, и когда вы его разблокируете, вы увидите уведомление на экране блокировки, позволяющее управлять воспроизведением мультимедиа или остановить трансляцию.

Изображение части экрана телефона Android с мини-плеером, воспроизводящим видео

4. Подготовьте стартовый проект

Теперь, когда мы проверили интеграцию Cast Connect завершенного приложения, нам нужно добавить поддержку Cast Connect в загруженное вами начальное приложение. Теперь вы готовы работать над стартовым проектом с помощью Android Studio:

  1. Выберите «Импорт проекта» на экране приветствия или пункты меню «Файл» > «Создать» > «Импортировать проект...» .
  2. Выберите значок папки app-start из папки примера кода и нажмите «ОК».
  3. Нажмите Файл > Проект синхронизации Android Studio с кнопкой Gradle Синхронизировать проект с файлами Gradle .
  4. Выберите устройство ATV и нажмите кнопку Кнопка «Выполнить» Android Studio: зеленый треугольник, направленный вправо. Кнопка «Выполнить» , чтобы запустить приложение и изучить пользовательский интерфейс. Панель инструментов Android Studio, показывающая выбранное устройство Android TV

Изображение серии миниатюр видео (один из которых выделен), наложенных на полноэкранный предварительный просмотр видео; слова «Cast Connect» появляются в правом верхнем углу

Дизайн приложения

Приложение предоставляет пользователю список видео для просмотра. Пользователи могут выбрать видео для воспроизведения на Android TV. Приложение состоит из двух основных действий: MainActivity и PlaybackActivity .

Основная деятельность

Это действие содержит фрагмент ( MainFragment ). Список видео и связанные с ними метаданные настраиваются в классе MovieList , а метод setupMovies() вызывается для создания списка объектов Movie .

Объект Movie представляет собой объект видео с заголовком, описанием, миниатюрами изображений и URL-адресом видео. Каждый объект Movie привязан к CardPresenter , чтобы представить миниатюру видео с названием и студией и передать ее в ArrayObjectAdapter .

Когда элемент выбран, соответствующий объект Movie передается в PlaybackActivity .

Воспроизведение активности

Это действие содержит фрагмент ( PlaybackVideoFragment ), в котором размещается VideoView с ExoPlayer , некоторые элементы управления мультимедиа и текстовая область для отображения описания выбранного видео и позволяет пользователю воспроизводить видео на Android TV. Пользователь может использовать пульт дистанционного управления для воспроизведения/паузы или поиска воспроизведения видео.

Предварительные требования для Cast Connect

Cast Connect использует новые версии сервисов Google Play, которые требуют обновления вашего приложения ATV для использования пространства имен AndroidX .

Чтобы поддерживать Cast Connect в приложении Android TV, вам необходимо создавать и поддерживать события из медиа-сеанса . Библиотека Cast Connect генерирует статус мультимедиа на основе статуса медиасеанса. Ваш медиа-сеанс также используется библиотекой 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 через отправителя Cast, выберите действие, которое хотите запустить. В этой лаборатории кода мы запустим MainActivity приложения при запуске сеанса Cast. В файле 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 , когда ваше приложение перемещается в фоновый режим. Мы рекомендуем вам использовать LifecycleObserver из библиотеки androidx.lifecycle для управления вызовами CastReceiverContext.start() и CastReceiverContext.stop()

Откройте файл 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 из-за неактивного воспроизведения, вам следует установить нулевой токен в MediaManager :

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

Давайте запустим пример приложения

Нажмите кнопку Кнопка «Выполнить» Android Studio: зеленый треугольник, направленный вправо. Нажмите кнопку «Запустить», чтобы развернуть приложение на устройстве ATV, закройте приложение и вернитесь на главный экран ATV. От отправителя нажмите кнопку Cast. Значок кнопки трансляции и выберите устройство ATV. Вы увидите, что приложение ATV запущено на устройстве ATV и состояние кнопки Cast подключено.

6. Загрузка мультимедиа

Команда загрузки отправляется через намерение с именем пакета, которое вы определили в консоли разработчика. Вам необходимо добавить следующий предопределенный фильтр намерений в приложение 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: зеленый треугольник, направленный вправо. Кнопка «Запустить» , чтобы развернуть приложение на вашем устройстве ATV. От отправителя нажмите кнопку Cast. Значок кнопки трансляции и выберите устройство ATV. Приложение ATV будет запущено на устройстве ATV. Выберите видео на мобильном устройстве, оно начнет воспроизводиться на квадроцикле. Проверьте, получаете ли вы уведомление на свой телефон, где у вас есть элементы управления воспроизведением. Попробуйте использовать такие элементы управления, как пауза, видео на устройстве ATV должно быть приостановлено.

7. Поддержка команд управления трансляцией

Текущее приложение теперь поддерживает основные команды, совместимые с мультимедийным сеансом, такие как воспроизведение, пауза и поиск. Однако существуют некоторые команды управления трансляцией, которые недоступны в сеансе мультимедиа. Вам необходимо зарегистрировать MediaCommandCallback для поддержки этих команд управления трансляцией.

Добавьте MyMediaCommandCallback в экземпляр MediaManager , используя setMediaCommandCallback при инициализации проигрывателя:

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

Создайте класс MyMediaCommandCallback , чтобы переопределить методы, такие как onQueueUpdate() , для поддержки этих команд управления трансляцией:

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 Connect получает базовый статус мультимедиа из медиа-сеанса. Для поддержки расширенных функций ваше приложение 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
        })
    }
}

Перехват MediaStatus перед отправкой

Подобно MessageInterceptor SDK веб-приемника, вы можете указать 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. Поздравления

Теперь вы знаете, как включить Cast в приложении Android TV с помощью библиотеки Cast Connect.

Более подробную информацию можно найти в руководстве для разработчиков: /cast/docs/android_tv_receiver .