Управление оборудованием для телевизоров

Аппаратное обеспечение телевизоров существенно отличается от других устройств 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 TV… Если ваше приложение использует одну или несколько функций, которые не поддерживаются на телевизорах, измените значение атрибута 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

Некоторые телевизоры поддерживают только подключение через Ethernet.

Полный список запросов разрешений, которые подразумевают требование к аппаратной функции, можно найти в руководстве uses-feature. Если ваше приложение запрашивает одну из перечисленных выше функций, добавьте в манифест декларацию uses-feature для подразумеваемой аппаратной функции, чтобы указать, что она не требуется. android:required="false".

Примечание. Если ваше приложение предназначено для Android 5.0 (уровень API 21) или более поздней версии и использует разрешение ACCESS_COARSE_LOCATION или ACCESS_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.");
}

Сенсорный экран

Большинство телевизоров не имеют сенсорных экранов или возможностей ввода указателя и полностью полагаются на пульты дистанционного управления с направленной панелью (D-pad) для навигации. Приложения для телевизоров должны поддерживать пульт ДУ с кнопками направления.

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

Объявление поддержки сенсорного экрана

Некоторые телевизоры поддерживают пульты с указкой и сенсорные экраны. Чтобы приложение было удобнее использовать на устройствах, поддерживающих клики, наведение указателя и прокрутку, вы можете добавить поддержку этих действий.

Если ваше приложение поддерживает сенсорный режим, вы можете объявить об этом для всего приложения или для отдельных действий, добавив элемент android.software.leanback.supports_touch <property> со значением true внутри элемента <application> или <activity> в файле AndroidManifest.xml:

<application ...>
    <property
        android:name="android.software.leanback.supports_touch"
        android:value="true|false" />
    ...
</application>

Примечание. На устройствах, поддерживающих пульт дистанционного управления с указкой (например, аэромышь или сенсорную панель), включение этого параметра активирует режим курсора и сенсорного ввода, а не эмуляцию совместимости платформы. Объявление на уровне действия переопределяет объявление на уровне приложения для этого действия. Если это свойство не указано, по умолчанию используется значение false.

Камера

Хотя у телевизора обычно нет камеры, вы все равно можете предоставить приложение, связанное с фотографией, на телевизоре. Например, если у вас есть приложение, которое позволяет делать, просматривать и редактировать фотографии, вы можете отключить функцию съемки для телевизоров, но оставить возможность просматривать и редактировать фотографии. Если вы решите разрешить работу приложения, связанного с камерой, на телевизоре, добавьте в манифест приложения следующее объявление функции:

<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 = locationManager.getLastKnownLocation("static")
if (location == null) {
    Log.e(TAG, "Location is null")
    return
}

// 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)?.firstOrNull()
                    ?.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, если ваше приложение активно. Подробнее о том, как запускать и останавливать действия, рассказывается в статье Жизненный цикл объекта activity.