テレビ ハードウェアに対応する

テレビのハードウェアは、他の Android デバイスとは大きく異なります。テレビにはタッチスクリーン、カメラ、GPS 受信機など、他の Android デバイスでよく使われるハードウェア機能がありません。また、テレビは、2 次ハードウェア デバイスに完全に依存しています。 つまり、ユーザーはリモコンやコントローラでテレビアプリを操作する必要があります。テレビアプリをビルドする際は、ハードウェア上の制限やテレビ向けハードウェアの操作要件を慎重に考慮する必要があります。

このレッスンでは、テレビでアプリが正常に動作するかどうかチェックする方法と、サポートされていないハードウェア機能を処理する方法について説明します。入力方法の種類については、テレビ コントローラの管理をご覧ください。

テレビデバイスをチェックする

テレビデバイスとその他のデバイスの両方で動作するアプリを作成している場合、アプリを実行するデバイスの種類をチェックし、アプリの動作を調整する必要があります。たとえば、Intent で起動するアプリの場合、テレビ向けアクティビティを起動するか、スマートフォン向けアクティビティを起動するかを判断するために、アプリ側でデバイスのプロパティをチェックする必要があります。

テレビデバイスでアプリが正常に動作するかどうかを判断するには、UiModeManager.getCurrentModeType() メソッドを使用して、そのデバイスがアプリのテレビモードで正常に動作するかどうかをチェックすることをおすすめします。次のサンプルコードは、テレビデバイスでアプリが正常に動作するかどうかをチェックする方法を示しています。

Kotlin

    const val TAG = "DeviceTypeRuntimeCheck"

    val uiModeManager = getSystemService(UI_MODE_SERVICE) as UiModeManager
    if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
        Log.d(TAG, "Running on a TV Device")
    } else {
        Log.d(TAG, "Running on a non-TV Device")
    }
    

Java

    public static final String TAG = "DeviceTypeRuntimeCheck";

    UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);
    if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
        Log.d(TAG, "Running on a TV Device");
    } else {
        Log.d(TAG, "Running on a non-TV Device");
    }
    

サポートされていないハードウェア機能を処理する

アプリのデザインと機能によっては、特定のハードウェア機能を利用できないという事態を回避できる場合があります。ここでは、通常テレビで使用できないハードウェア機能やその検出方法と、代替機能について説明します。

サポートされていないテレビ ハードウェア機能

テレビの用途は他のデバイスと異なるので、他の Android デバイスで提供されることの多いハードウェア機能がない場合があります。このため、テレビデバイス向け Android システムでは次の機能をサポートしていません。

ハードウェア Android の機能記述子
タッチスクリーン android.hardware.touchscreen
タッチスクリーン エミュレータ android.hardware.faketouch
電話 android.hardware.telephony
カメラ android.hardware.camera
近距離無線通信(NFC) android.hardware.nfc
GPS android.hardware.location.gps
マイク [1] android.hardware.microphone
センサー android.hardware.sensor
縦向きの画面 android.hardware.screen.portrait

[1] 一部のテレビ コントローラにはマイクがありますが、ここで説明するマイクのハードウェア機能と同じものではありません。コントローラのマイクは完全にサポートされます。

機能、サブ機能とその記述子の全一覧については、機能リファレンスをご覧ください。

テレビのハードウェア要件を宣言する

Android アプリでは、機能提供がないデバイスにインストールされないように、アプリのマニフェストでハードウェア機能の要件を宣言できます。テレビ向けに既存のアプリを拡張している場合は、テレビデバイスへのインストールを阻害する可能性のあるハードウェア要件を宣言しているかどうかについて、アプリのマニフェストを詳細に見直す必要があります。

テレビで使用できないハードウェア機能(タッチスクリーンやカメラなど)をアプリで使用しているものの、テレビではその機能がなくても構わない場合は、アプリのマニフェストを編集してそれが不要な機能であることを示します。次のマニフェストのコード スニペットでは、テレビデバイスで使用できないハードウェア機能を不要と宣言する方法を示しています。これらの機能は、テレビ以外のデバイスでは使用できます。

    <uses-feature android:name="android.hardware.touchscreen"
            android:required="false"/>
    <uses-feature android:name="android.hardware.faketouch"
            android:required="false"/>
    <uses-feature android:name="android.hardware.telephony"
            android:required="false"/>
    <uses-feature android:name="android.hardware.camera"
            android:required="false"/>
    <uses-feature android:name="android.hardware.nfc"
            android:required="false"/>
    <uses-feature android:name="android.hardware.location.gps"
            android:required="false"/>
    <uses-feature android:name="android.hardware.microphone"
            android:required="false"/>
    <uses-feature android:name="android.hardware.sensor"
            android:required="false"/>
    

注: 機能リファレンスで説明されているように、一部の機能には android.hardware.camera.front のようなサブ機能があります。アプリで使用されるサブ機能も required="false" としてマークしてください。

テレビアプリのビルドを開始するで説明したように、テレビデバイス向けのすべてのアプリで、タッチ スクリーン機能が不要であることを宣言する必要があります。アプリで上記の機能を 1 つ以上使用している場合は、マニフェストで該当する機能の android:required 属性の設定を false に変更します。

注: この値を true に設定してハードウェア機能が必要であることを宣言すると、アプリはテレビデバイスにインストールされず、Android TV のホーム画面ランチャーにも表示されません。

アプリのハードウェア機能をオプションにする場合は、実行時にこれらの機能が利用できるかをチェックしてからアプリの動作を調整する必要があります。次のセクションでは、ハードウェア機能をチェックする方法を説明した後、アプリの動作を変更するためのアプローチをいくつかご紹介します。

マニフェスト内での機能のフィルタリングと宣言について詳しくは、uses-feature ガイドをご覧ください。

ハードウェア機能を暗示するパーミッションを宣言する

uses-permission のマニフェストにおける宣言には、ハードウェア機能を暗示するものがあります。つまり、アプリのマニフェストでリクエストするパーミッションによっては、アプリがテレビデバイスにインストールされず、使用できないことがあります。よくリクエストされる次のパーミッションでは、暗黙的なハードウェア機能の要件が作成されます。

権限 暗黙的なハードウェア機能
RECORD_AUDIO android.hardware.microphone
CAMERA android.hardware.camera
android.hardware.camera.autofocus
ACCESS_COARSE_LOCATION

android.hardware.location

android.hardware.location.network(ターゲット API レベル 20 以前のみ)

ACCESS_FINE_LOCATION

android.hardware.location

android.hardware.location.gps(ターゲット API レベル 20 以前のみ)

暗黙的なハードウェア機能要件のパーミッション リクエストの一覧については、uses-feature ガイドを参照してください。アプリが上記の機能のいずれかをリクエストする場合は、暗黙的なハードウェア機能に関する uses-feature 宣言をマニフェストに含めて、不要であることを示します(android:required="false")。

注: アプリのターゲットが Android 5.0(API レベル 21)以降で、ACCESS_COARSE_LOCATION または ACCESS_FINE_LOCATION パーミッションが使用されている場合は、テレビデバイスにネットワーク カードまたは GPS 受信機がなくてもそのテレビデバイスにアプリをインストールできます。

ハードウェア機能を確認する

Android のフレームワークでは、アプリが実行されているデバイスでハードウェア機能を使用できるかどうかを判断できます。実行時に特定の機能をチェックするには、hasSystemFeature(String) メソッドを使用します。このメソッドは、チェック対象の機能を指定する因数を 1 つ使用します。

次のコードサンプルでは、実行時にハードウェア機能が利用できるかどうかを検出する方法を示しています。

Kotlin

    // Check if the telephony hardware feature is available.
    if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
        Log.d("HardwareFeatureTest", "Device can make phone calls")
    }

    // Check if android.hardware.touchscreen feature is available.
    if (packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
        Log.d("HardwareFeatureTest", "Device has a touch screen.")
    }
    

Java

    // Check if the telephony hardware feature is available.
    if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
        Log.d("HardwareFeatureTest", "Device can make phone calls");
    }

    // Check if android.hardware.touchscreen feature is available.
    if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
        Log.d("HardwareFeatureTest", "Device has a touch screen.");
    }
    

タッチ スクリーン

テレビには通常タッチ スクリーンがないため、テレビデバイス向けタッチ スクリーン操作は Android ではサポートされません。そもそも、ユーザーが 3 メートルほど離れた場所から視聴するというテレビ特有の使用環境にタッチ スクリーン操作は適していません。UI 要素とテキストがタッチスクリーンの使用を必要としないこと、または暗黙的に示さないことを確認してください。

テレビデバイスではリモコンの矢印ボタンによるナビゲーションをサポートして、テレビ特有のインタラクション モデルに適したアプリをデザインする必要があります。テレビ向けコントロールを使用してナビゲーションを適切にサポートする方法について詳しくは、テレビ用のナビゲーションを作成するをご覧ください。

カメラ

テレビには通常カメラがありませんが、テレビにカメラ関連アプリを提供することは可能です。たとえば、写真を撮影、表示、編集する機能があるアプリの場合、テレビ向けに撮影機能を無効にする一方で写真の表示や編集は可能にすることができます。カメラ関連アプリをテレビ向けにする場合は、アプリのマニフェストに次の機能の宣言を追加します。

    <uses-feature android:name="android.hardware.camera" android:required="false" />
    

カメラ機能を除いてアプリを動作させる場合は、コードをアプリに追加してカメラ機能が使用可能かどうかを検出し、そのアプリの動作を調整します。次のコードサンプルでは、カメラの存在を検出する方法を示しています。

Kotlin

    // Check if the camera hardware feature is available.
    if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        Log.d("Camera test", "Camera available!")
    } else {
        Log.d("Camera test", "No camera available. View and edit features only.")
    }
    

Java

    // Check if the camera hardware feature is available.
    if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        Log.d("Camera test", "Camera available!");
    } else {
        Log.d("Camera test", "No camera available. View and edit features only.");
    }
    

GPS

テレビは据え付けタイプの室内用デバイスであり、全地球測位システム(GPS)の受信機を内蔵していません。アプリで位置情報が使用されている場合は、ユーザーによる位置情報の検索を許可したり、テレビデバイスのセットアップ時に設定した郵便番号などの静的なロケーション プロバイダを使用したりできます。

Kotlin

    // Request a static location from the location manager
    val locationManager = this.getSystemService(Context.LOCATION_SERVICE) as LocationManager
    val location: Location = locationManager.getLastKnownLocation("static")

    // Attempt to get postal or zip code from the static location object
    val geocoder = Geocoder(this)
    val address: Address? =
            try {
                geocoder.getFromLocation(location.latitude, location.longitude, 1)[0]
                        .apply {
                            Log.d(TAG, postalCode)
                        }
            } catch (e: IOException) {
                Log.e(TAG, "Geocoder error", e)
                null
            }
    

Java

    // Request a static location from the location manager
    LocationManager locationManager = (LocationManager) this.getSystemService(
            Context.LOCATION_SERVICE);
    Location location = locationManager.getLastKnownLocation("static");

    // Attempt to get postal or zip code from the static location object
    Geocoder geocoder = new Geocoder(this);
    Address address = null;
    try {
      address = geocoder.getFromLocation(location.getLatitude(),
              location.getLongitude(), 1).get(0);
      Log.d("Zip code", address.getPostalCode());

    } catch (IOException e) {
      Log.e(TAG, "Geocoder error", e);
    }
    

省電力モードのときに再生を一時停止する

テレビデバイスの中には、ユーザーがデバイスをオフにしたときに省電力モードに切り替わるものがあります。このようなデバイスでは、Android TV はシャットダウンされません。表示は無効になりますが、バックグラウンドでは実行されたままです。省電力モードでも音声出力は引き続き有効なので、省電力モードのときはアプリで現在再生されているコンテンツを停止する必要があります。

省電力モードのときに再生されないようにするには、onStop() をオーバーライドして現在再生されているコンテンツを停止します。

Kotlin

    override fun onStop() {
        // App-specific method to stop playback
        stopPlayback()
        super.onStop()
    }
    

Java

    @Override
    public void onStop() {
      // App-specific method to stop playback
      stopPlayback();
      super.onStop();
    }
    

ユーザーが電源を再度オンにしたときにアプリがフォアグラウンドでアクティブになっている場合は、onStart() が呼び出されます。アクティビティの起動と停止について詳しくは、アクティビティのライフサイクルをご覧ください。