TV 入力サービスを開発する

TV 入力サービスは、メディア ストリーム ソースを表し、メディア コンテンツを 地上波 TV のファッションをチャンネルや番組として利用している。TV 入力サービスでは、 保護者による使用制限、番組ガイド情報、コンテンツのレーティング。TV 入力サービスが機能する Android システムテレビ アプリで操作できます。最終的にはこのアプリがチャンネル コンテンツを管理、表示 。システムテレビ アプリはデバイス専用に開発されており、不変である 管理することもできます。TV 入力フレームワーク(TIF)の詳細 コンポーネントの詳細については、 <ph type="x-smartling-placeholder"></ph> TV 入力フレームワーク

TIF Companion Library を使用してテレビ入力サービスを作成する

TIF Companion ライブラリは、 一般的な TV 入力サービス機能の実装。OEM がビルド / アプリケーション開発に使用することを意図しています。 Android 5.0(API レベル 21)から Android 7.1(API レベル 25)でのみサポートされます。

プロジェクトを更新する

TIF Companion Library は、 androidtv-sample-inputs できます。アプリにライブラリを組み込む方法の例については、こちらのリポジトリをご覧ください。

マニフェストでテレビ入力サービスを宣言する

アプリは TvInputService 互換 サービス。TIF コンパニオン ライブラリの BaseTvInputService クラスは、 TvInputService のデフォルト実装を提供します。 カスタマイズできます。BaseTvInputService のサブクラスを作成します。 マニフェストでサブクラスをサービスとして宣言します。

マニフェストの宣言で、 BIND_TV_INPUT 権限が付与され、 サービスを使用してテレビ入力をシステムに接続します。システム サービス バインディングを実行して BIND_TV_INPUT 権限。 システム TV アプリがテレビ入力サービスにリクエストを送信する TvInputManager インターフェース経由。

サービスの宣言に、指定するインテント フィルタを含めます。 TvInputService で実行するアクションとして、 使用します。また、サービス メタデータを個別の XML リソースとして宣言します。「 サービス宣言、インテント フィルタ、サービス メタデータの宣言が表示されています 使用します。

<service android:name=".rich.RichTvInputService"
    android:label="@string/rich_input_label"
    android:permission="android.permission.BIND_TV_INPUT">
    <!-- Required filter used by the system to launch our account service. -->
    <intent-filter>
        <action android:name="android.media.tv.TvInputService" />
    </intent-filter>
    <!-- An XML file which describes this input. This provides pointers to
    the RichTvInputSetupActivity to the system/TV app. -->
    <meta-data
        android:name="android.media.tv.input"
        android:resource="@xml/richtvinputservice" />
</service>

サービス メタデータを個別の XML ファイルで定義します。サービス メタデータ XML ファイルには、TV 入力の 初期構成とチャンネル スキャンの 2 つがあります。また、メタデータ ファイルには、 ユーザーがコンテンツを録画できるかどうかを示すフラグ。詳細 アプリでのコンテンツの録画をサポートする方法については、 コンテンツの録画をサポートする

サービス メタデータ ファイルは XML リソース ディレクトリにある で宣言したリソースの名前と一致する必要があります。 使用します。前の例のマニフェスト エントリを使用して、次の操作を行います。 XML ファイルを res/xml/richtvinputservice.xml に作成し、 次の内容が含まれます。

<?xml version="1.0" encoding="utf-8"?>
<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
  android:canRecord="true"
  android:setupActivity="com.example.android.sampletvinput.rich.RichTvInputSetupActivity" />

チャンネルを定義してセットアップ アクティビティを作成する

TV 入力サービスでは、ユーザーが利用するチャンネルを少なくとも 1 つ定義する必要があります。 アクセスできます。チャンネルを登録する必要があります。 セットアップ アクティビティを提供し、システム側での は、アプリのチャネルが見つからない場合に呼び出されます。

まず、アプリでシステムの電子通信システムに対する読み取りと書き込みができるようにします。 番組ガイド(EPG)(データには利用可能なチャンネルと番組が含まれる) 提供します。アプリがこれらのアクションを実行できるようにし、 デバイスの再起動後に EPG を表示するには、アプリ マニフェストに次の要素を追加します。

<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED "/>

次の要素を追加して、アプリが Android TV でコンテンツ チャンネルを提供するアプリとしての Google Play ストア:

<uses-feature
    android:name="android.software.live_tv"
    android:required="true" />

次に、EpgSyncJobService を拡張するクラスを作成します。 クラスです。この抽象クラスを使用すると、Terraform で記述されたジョブサービスを システム データベースでチャンネルの作成と更新を行います。

サブクラスで、すべてのチャネルのリストを getChannels()。チャンネルが XMLTV ファイルからのものである場合、 XmlTvParser クラスを使用します。それ以外の場合は、 Channel.Builder クラスを使用してプログラムでチャンネルを作成する。

システムはチャネルごとに getProgramsForChannel() を呼び出します。 特定の時間枠内で表示できる番組のリストを必要とするとき チャンネルに投稿されます。次のクラスの Program オブジェクトのリストを返す: 。XmlTvParser クラスを使用して、プログラムを XMLTV ファイルを使用するか、 Program.Builder クラス。

Program オブジェクトごとに、 InternalProviderData オブジェクトを使用して、 サポートしています。利用できるプログラムの数が限られている場合は、 繰り返してチャンネルを再生するには、 値を持つ InternalProviderData.setRepeatable() メソッド プログラムに関する情報を設定する場合は true

ジョブサービスを実装したら、アプリ マニフェストに追加します。

<service
    android:name=".sync.SampleJobService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="true" />

最後に、セットアップ アクティビティを作成します。セットアップ アクティビティでは、 チャンネルと番組データを同期します。これを行う方法の 1 つは、ユーザーが アクティビティの UI を介して行いますアプリによって自動的に 呼び出すことができます。セットアップ アクティビティでチャンネルとの同期が必要な場合 アプリはジョブサービスを開始します。

Kotlin

val inputId = getActivity().intent.getStringExtra(TvInputInfo.EXTRA_INPUT_ID)
EpgSyncJobService.cancelAllSyncRequests(getActivity())
EpgSyncJobService.requestImmediateSync(
        getActivity(),
        inputId,
        ComponentName(getActivity(), SampleJobService::class.java)
)

Java

String inputId = getActivity().getIntent().getStringExtra(TvInputInfo.EXTRA_INPUT_ID);
EpgSyncJobService.cancelAllSyncRequests(getActivity());
EpgSyncJobService.requestImmediateSync(getActivity(), inputId,
        new ComponentName(getActivity(), SampleJobService.class));

requestImmediateSync() メソッドを使用して同期する 表示されます。ユーザーは同期が完了するまで待つ必要があるため、 リクエスト期間を比較的短く保ちます。

setUpPeriodicSync() メソッドを使用してジョブサービスを取得する チャンネルと番組のデータをバックグラウンドで定期的に同期:

Kotlin

EpgSyncJobService.setUpPeriodicSync(
        context,
        inputId,
        ComponentName(context, SampleJobService::class.java)
)

Java

EpgSyncJobService.setUpPeriodicSync(context, inputId,
        new ComponentName(context, SampleJobService.class));

TIF Companion Library には、追加のオーバーロード メソッドも用意されています。 requestImmediateSync(): 次の期間を指定できます。 ミリ秒単位で同期できます。デフォルトのメソッドでは、1 時間の チャンネルデータの価値です

TIF Companion Library には、追加のオーバーロード メソッドも用意されています。 setUpPeriodicSync(): 次の期間を指定できます。 定期的な同期を行う頻度を指定します。「 デフォルトのメソッドでは、48 時間のチャンネル データが 12 時間ごとに同期されます。

チャンネル データと EPG について詳しくは、以下をご覧ください。 チャンネル データを使用する

チューニング リクエストとメディア再生を処理する

ユーザーが特定のチャンネルを選択すると、システム テレビアプリは リクエストされたチャンネルに合わせてアプリによって作成された Session 操作できます。TIF Companion Library には、 システムからのチャネル呼び出しとセッション呼び出しを処理するために拡張できるクラス。

BaseTvInputService サブクラスは、 作成できます。オーバーライドする onCreateSession() メソッドを使用して、外部 IP アドレスから拡張されたセッションを作成します。 BaseTvInputService.Session クラスを呼び出して、 super.sessionCreated() を新しいセッションに置き換えます。実際に たとえば、onCreateSession() は 拡張する RichTvInputSessionImpl オブジェクト BaseTvInputService.Session:

Kotlin

override fun onCreateSession(inputId: String): Session =
        RichTvInputSessionImpl(this, inputId).apply {
            setOverlayViewEnabled(true)
        }

Java

@Override
public final Session onCreateSession(String inputId) {
    RichTvInputSessionImpl session = new RichTvInputSessionImpl(this, inputId);
    session.setOverlayViewEnabled(true);
    return session;
}

ユーザーがシステム テレビアプリを使用して、いずれかのチャンネルの視聴を開始すると、 システムがセッションの onPlayChannel() メソッドを呼び出します。オーバーライド 初期化前に特別なチャネルの初期化が必要な場合は、このメソッドを使用します。 再生が開始されます。

システムは現在スケジュールされている番組を取得し、 セッションの onPlayProgram() メソッド(プログラムを指定) ミリ秒単位で表示されます。こちらの プログラムの再生を開始するための TvPlayer インターフェース。

メディア プレーヤーのコードでは、TvPlayer を実装して 特定の再生イベントを指定できます。TvPlayer クラスが特徴を処理する タイムシフトなどの操作を簡単に行えるため、 BaseTvInputService の実装。

セッションの getTvPlayer() メソッドで、次を返します。 TvPlayer を実装するメディア プレーヤー。「 <ph type="x-smartling-placeholder"></ph> TV 入力サービスのサンプルアプリは、 ExoPlayer

TV 入力フレームワークを使用して TV 入力サービスを作成する

テレビ入力サービスが TIF コンパニオン ライブラリを使用できない場合は、以下が必要です。 を使用して、次のコンポーネントを実装します。

  • TvInputService は、リソースの長時間実行とバックグラウンドの可用性を提供します。 テレビ入力
  • TvInputService.Session: テレビ入力状態を維持し、通信 使用した場合
  • TvContract は、テレビで利用可能なチャンネルと番組を表します。 入力
  • TvContract.Channels: テレビ チャンネルに関する情報を表します。
  • TvContract.Programs は、テレビ番組 タイトルと開始時間
  • TvTrackInfo: 音声、動画、または字幕トラックを表します。
  • TvContentRating はコンテンツのレーティングを表します。カスタム コンテンツを許可します。 レーティング方式
  • TvInputManager: システム TV アプリに API を提供し、管理します。 テレビ入力とアプリとのやり取り

また、次の処理も行う必要があります。

  1. マニフェストで次のように TV 入力サービスを宣言します。 使用します
  2. サービス メタデータ ファイルを作成する。
  3. チャンネルと番組の情報を作成して登録する。
  4. セットアップ アクティビティを作成する。

テレビ入力サービスを定義する

サービス用に、TvInputService クラスを拡張します。 TvInputService の実装は バインドされたサービス バインドするクライアントです。サービス ライフサイクルのメソッド 図 1 のとおりです。

onCreate() メソッドは、コマンドを初期化して HandlerThread: UI スレッドとは別のプロセス スレッドを提供し、 システム主導のアクションを処理できます。次の例では、onCreate() メソッドは CaptioningManager を初期化し、 ACTION_BLOCKED_RATINGS_CHANGEDACTION_PARENTAL_CONTROLS_ENABLED_CHANGED 件のアクション。これらの アクションは、ユーザーが保護者による使用制限の設定を変更したとき、および変更したときに起動されるシステム インテントを表します。 ブロックした評価のリストに変更があります。

Kotlin

override fun onCreate() {
    super.onCreate()
    handlerThread = HandlerThread(javaClass.simpleName).apply {
        start()
    }
    dbHandler = Handler(handlerThread.looper)
    handler = Handler()
    captioningManager = getSystemService(Context.CAPTIONING_SERVICE) as CaptioningManager

    setTheme(android.R.style.Theme_Holo_Light_NoActionBar)

    sessions = mutableListOf<BaseTvInputSessionImpl>()
    val intentFilter = IntentFilter().apply {
        addAction(TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED)
        addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED)
    }
    registerReceiver(broadcastReceiver, intentFilter)
}

Java

@Override
public void onCreate() {
    super.onCreate();
    handlerThread = new HandlerThread(getClass()
      .getSimpleName());
    handlerThread.start();
    dbHandler = new Handler(handlerThread.getLooper());
    handler = new Handler();
    captioningManager = (CaptioningManager)
      getSystemService(Context.CAPTIONING_SERVICE);

    setTheme(android.R.style.Theme_Holo_Light_NoActionBar);

    sessions = new ArrayList<BaseTvInputSessionImpl>();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(TvInputManager
      .ACTION_BLOCKED_RATINGS_CHANGED);
    intentFilter.addAction(TvInputManager
      .ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
    registerReceiver(broadcastReceiver, intentFilter);
}

図 1.TvInputService のライフサイクル

<ph type="x-smartling-placeholder"></ph>をご覧ください。 コンテンツを管理するをご覧ください。ブロックされたコンテンツの処理と提供について詳しくは、 保護者による使用制限。その他のシステム駆動型アクションについては、TvInputManagerをご覧ください 処理したい場合もあります

TvInputService は、 Handler.Callback を実装する TvInputService.Session プレーヤーの状態変化を処理できます。あり onSetSurface(), TvInputService.SessionSurface を 提供します。プレーヤーを Surface と統合するをご覧ください。 Surface を使用した動画のレンダリングに関する詳細をご覧ください。

TvInputService.Session は、 onTune() イベントを受信してシステム TV アプリにコンテンツの変更を通知し、 提供します。これらの notify() メソッドの説明については、 <ph type="x-smartling-placeholder"></ph> コンテンツを制御するトラック選択を処理する このトレーニングで詳しく説明します

セットアップ アクティビティを定義する

システム TV アプリは、デベロッパーが TV 入力用に定義したセットアップ アクティビティで動作します。「 設定アクティビティは必須です。システム データベース用に少なくとも 1 つのチャンネル レコードが必要です。「 システム TV アプリは、TV 入力用のチャンネルが見つからない場合、セットアップ アクティビティを呼び出します。

セットアップ アクティビティでは、テレビを通じて視聴できるチャンネルをシステム テレビアプリに記述します。 次のレッスンで説明するように、 チャンネル データの更新をご覧ください。

その他の関連情報