处理电视硬件

电视硬件与其他 Android 设备有很大不同。电视不包括其他 Android 设备上的一些硬件功能,例如触摸屏、摄像头和 GPS 接收器。电视还完全依赖于辅助硬件设备:用户必须使用遥控器或游戏手柄才能与电视应用进行交互。(要了解各种输入方法,请参阅 管理电视控制器。)

构建电视应用时,请仔细考虑在电视硬件上运行的硬件限制和要求。检查您的应用是否在电视上运行,并处理不支持的硬件功能。

检查电视设备

如果您正在构建一个在电视设备和其他设备上运行的应用,则可能需要检查您的应用在何种设备上运行并调整应用的操作。例如,如果您有一个可以通过 Intent 启动的应用,请检查设备属性以确定是启动面向电视的活动还是手机活动。

确定您的应用是否在电视设备上运行的推荐方法是使用 PackageManager.hasSystemFeature() 方法检查设备是否在电视模式下运行。以下示例代码展示了如何检查您的应用是否在电视设备上运行

Kotlin

const val TAG = "DeviceTypeRuntimeCheck"

val isTelevision = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
if (isTelevision) {
    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";

boolean isTelevision = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
if (isTelevision) {
    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
麦克风 android.hardware.microphone
传感器 android.hardware.sensor
纵向屏幕 android.hardware.screen.portrait

注意:一些电视遥控器带有麦克风,这与此处描述的麦克风硬件功能不同。遥控器麦克风完全受支持。

有关功能、子功能及其描述符的完整列表,请参见功能参考

声明电视的硬件要求

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"/>
<!-- Some TV devices have an ethernet connection only -->
<uses-feature android:name="android.hardware.wifi"
        android:required="false"/>

注意:功能参考中所述,一些功能具有子功能,例如android.hardware.camera.front。请确保将应用中使用的任何子功能也标记为required="false"

所有旨在用于电视设备的应用都必须声明触摸屏功能不是必需的,如开始使用电视应用中所述。如果您的应用通常使用电视设备不支持的一种或多种功能,请将清单中这些功能的android:required属性设置为false

警告:将硬件功能声明为必需(通过将其值设置为true)将阻止您的应用安装在电视设备上或出现在 Android TV 主屏幕启动器中。

了解暗示硬件功能的权限

某些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 或更低版本)

ACCESS_WIFI_STATE
CHANGE_WIFI_STATE

android.hardware.wifi

一些电视设备仅具有以太网连接。

有关暗示硬件功能要求的权限请求的完整列表,请参见uses-feature指南。如果您的应用请求前面列出的某项功能,请在清单中包含uses-feature声明,以指示该隐式硬件功能不是必需的。android:required="false"

注意:如果您的应用面向 Android 5.0(API 级别 21)或更高版本并使用ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION权限,即使电视设备没有网卡或 GPS 接收器,用户仍然可以在电视设备上安装您的应用。

在将硬件功能对应用设置为可选之后,您必须在运行时检查这些功能的可用性,然后调整应用的行为。下一节将讨论如何检查硬件功能,并建议一些更改应用行为的方法。

有关在清单中过滤和声明功能的更多信息,请参见uses-feature指南。

检查硬件功能

Android 框架可以告诉您运行应用的设备上是否不可用硬件功能。使用hasSystemFeature(String)方法在运行时检查特定功能。此方法采用一个字符串参数,指定要检查的功能。

以下代码示例演示了如何在运行时检测硬件功能的可用性

Kotlin

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

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

Java

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

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

触摸屏

由于大多数电视都没有触摸屏,因此 Android 不支持电视设备的触摸屏交互。此外,使用触摸屏与用户坐在距离显示屏 10 英尺的地方观看的环境不一致。确保您的 UI 元素和文本不需要也不暗示使用触摸屏。

对于电视设备,请设计您的应用以支持使用电视遥控器上的方向键(D 键)进行导航。有关使用适合电视的控件正确支持导航的更多信息,请参见电视导航

摄像头

虽然电视通常没有摄像头,但您仍然可以在电视上提供与摄影相关的应用。例如,如果您有一个用于拍摄、查看和编辑照片的应用,您可以为电视禁用其拍照功能,但仍然允许用户查看甚至编辑照片。如果您决定启用与摄像头相关的应用以在电视上运行,请将以下功能声明添加到应用清单

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

如果您启用应用在没有摄像头的情况下运行,请在应用中添加代码以检测摄像头功能是否可用,并对应用的操作进行调整。以下代码示例演示了如何检测摄像头是否存在

Kotlin

// Check whether 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 whether 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 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 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("Postal 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()。有关启动和停止活动的更多信息,请参见活动生命周期