Gerenciar o hardware da TV

O hardware de TV é substancialmente diferente de outros dispositivos Android. TVs não incluem alguns dos recursos de hardware encontrados em outros dispositivos Android, como touchscreens, câmeras e receptores de GPS. TVs também são completamente dependentes de dispositivos de hardware secundários: para que os usuários interajam com apps de TV, eles precisam usar um controle remoto ou um gamepad. Ao criar um app para TV, considere cuidadosamente as limitações e os requisitos de hardware para operar em hardwares de TV.

Este guia mostra como verificar se o app está sendo executado em uma TV e como lidar com recursos de hardware sem suporte. Para saber mais sobre vários métodos de entrada, consulte Gerenciar controladores de TV.

Verificar se há um dispositivo de TV

Se você está criando um app que funciona em dispositivos de TV e de outros dispositivos, pode ser necessário verificar em que tipo de dispositivo ele está sendo executado e ajustar a operação do app. Por exemplo, se você tiver um app que pode ser iniciado por uma Intent, confira as propriedades do dispositivo para determinar se é necessário iniciar uma atividade para TV ou smartphone.

A maneira recomendada de determinar se o app está sendo executado em um dispositivo de TV é usar o método PackageManager.hasSystemFeature() para verificar se o dispositivo está sendo executado no modo de televisão. O código de exemplo a seguir mostra como verificar se o app está sendo executado em um dispositivo de TV:

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");
}

Lidar com recursos de hardware incompatíveis

Dependendo do design e da funcionalidade do app, você pode contornar alguns recursos de hardware indisponíveis. Esta seção discute quais recursos de hardware normalmente não estão disponíveis para TV, como detectar recursos de hardware ausentes e quais alternativas são sugeridas para esses recursos.

Recursos de hardware de TV incompatíveis

TVs têm uma finalidade diferente de outros dispositivos e, por isso, não têm recursos de hardware que outros dispositivos Android geralmente têm. Por esse motivo, o sistema Android não oferece suporte aos seguintes recursos para um dispositivo de TV:

Hardware Descritor de recurso do Android
Touchscreen android.hardware.touchscreen
Emulador de touchscreen android.hardware.faketouch
Telefonia android.hardware.telephony
Câmera android.hardware.camera
Comunicação a curta distância (NFC) android.hardware.nfc
GPS android.hardware.location.gps
Microfone android.hardware.microphone
Sensores android.hardware.sensor
Tela na orientação retrato android.hardware.screen.portrait

Observação:alguns controladores de TV têm um microfone diferente do recurso de hardware de microfone descrito aqui. O microfone do controle é totalmente compatível.

Consulte a Referência de recursos para uma lista completa de recursos, recursos secundários e descritores.

Declarar os requisitos de hardware para TV

Os apps Android podem declarar requisitos de recursos de hardware no manifesto para garantir que eles não sejam instalados em dispositivos que não ofereçam esses recursos. Se você estiver estendendo um app já existente para uso na TV, revise com atenção o manifesto do app para verificar se há declarações de requisito de hardware que possam impedir a instalação dele em dispositivos de TV.

Se o app usa recursos de hardware, como touchscreen ou câmera, que não estão disponíveis na TV, mas podem operar sem esses recursos, modifique o manifesto do app para indicar que esses recursos não são necessários. O snippet de código do manifesto a seguir demonstra como declarar que o app não exige recursos de hardware indisponíveis em dispositivos de TV, mas usa esses recursos em outros aparelhos:

<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"/>

Observação:alguns dos recursos têm subrecursos, como android.hardware.camera.front, conforme descrito em Referência de recursos. Marque todos os subrecursos que também são usados no seu app como required="false".

Todos os apps destinados ao uso em dispositivos de TV precisam declarar que o recurso de tela touchscreen não é necessário, conforme descrito em Introdução a apps para TV. Se o app usa normalmente um ou mais recursos não compatíveis com dispositivos de TV, mude a configuração do atributo android:required para false para esses recursos no manifesto.

Cuidado:declarar um recurso de hardware como obrigatório definindo o valor dele como true evita que o app seja instalado em dispositivos de TV ou apareça na tela de início do Android TV.

Preste atenção nas permissões que implicam recursos de hardware

Algumas declarações de manifesto uses-permission implicam recursos de hardware. Esse comportamento significa que a solicitação de algumas permissões no manifesto do app pode impedir que ele seja instalado e usado em dispositivos de TV. As seguintes permissões solicitadas com frequência criam um requisito implícito de recurso de hardware:

Permissão Recurso de hardware afetado
RECORD_AUDIO android.hardware.microphone
CAMERA android.hardware.camera e
android.hardware.camera.autofocus
ACCESS_COARSE_LOCATION

android.hardware.location

android.hardware.location.network (somente API de destino 20 ou anterior)

ACCESS_FINE_LOCATION

android.hardware.location

android.hardware.location.gps (somente API de destino 20 ou anterior)

ACCESS_WIFI_STATE
CHANGE_WIFI_STATE

android.hardware.wifi

Alguns dispositivos de TV têm apenas conexão Ethernet.

Para ver uma lista completa de solicitações de permissão que implicam um requisito de recurso de hardware, consulte o guia uses-feature. Se o app solicitar um dos recursos listados anteriormente, inclua uma declaração uses-feature no manifesto para o recurso de hardware implícito, indicando que ele não é obrigatório. android:required="false".

Observação:caso seu app seja destinado ao Android 5.0 (API de nível 21) ou versões mais recentes e use a permissão ACCESS_COARSE_LOCATION ou ACCESS_FINE_LOCATION, o usuário ainda poderá instalá-lo em um dispositivo de TV, mesmo que ele não tenha uma placa de rede ou um receptor de GPS.

Depois de tornar os recursos de hardware opcionais para o app, é necessário verificar a disponibilidade desses recursos no momento da execução e ajustar o comportamento do app. A próxima seção discute como verificar os recursos de hardware e sugere algumas abordagens para mudar o comportamento do app.

Para mais informações sobre como filtrar e declarar recursos no manifesto, consulte o guia uses-feature.

Verificar se há recursos de hardware

O framework do Android pode informar se os recursos de hardware não estão disponíveis no dispositivo em que o app está sendo executado. Use o método hasSystemFeature(String) para conferir recursos específicos no momento da execução. Esse método usa um único argumento de string que especifica o recurso que você quer verificar.

O exemplo de código a seguir demonstra como detectar a disponibilidade de recursos de hardware no tempo de execução:

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.");
}

Tela touchscreen

Como a maioria das TVs não tem touchscreen, o Android não oferece suporte a essa interação em dispositivos de TV. Além disso, o uso de uma tela touchscreen não é consistente com um ambiente de visualização em que o usuário está sentado a 3 metros de distância da tela. Verifique se os elementos da interface e o texto não exigem ou implicam o uso de uma tela touchscreen.

Para dispositivos de TV, crie seu app para oferecer compatibilidade com a navegação usando um botão direcional em um controle remoto de TV. Para mais informações sobre como oferecer o suporte adequado à navegação usando controles compatíveis com TV, consulte Navegação na TV.

Câmera

Embora uma TV normalmente não tenha câmera, você ainda pode oferecer um app relacionado a fotografia em uma TV. Por exemplo, se você tem um app que tira, exibe e edita fotos, pode desativar a funcionalidade de tirar fotos para TVs e ainda permitir que os usuários vejam e até mesmo editem fotos. Se você decidir permitir que o app relacionado à câmera funcione em uma TV, adicione a seguinte declaração de recurso no manifesto do app:

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

Se você permitir que o app funcione sem uma câmera, adicione um código a ele que detecte se o recurso da câmera está disponível e faça ajustes na operação do app. O exemplo de código a seguir demonstra como detectar a presença de uma câmera:

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

TVs são dispositivos estacionários para ambientes internos e não têm receptores integrados de sistema de posicionamento global (GPS). Se o app usar informações de localização, você ainda poderá permitir que os usuários pesquisem um local ou usem um provedor de localização estática, como um código postal definido durante a configuração do dispositivo de TV.

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);
}

Pausar a reprodução durante o modo de baixo consumo de energia

Alguns dispositivos de TV oferecem suporte a um modo de baixo consumo de energia quando o usuário desliga o dispositivo. Em vez de desligar, o dispositivo desativa a tela e mantém o Android TV em segundo plano. A saída de áudio ainda está ativada nesse modo, então interrompa qualquer conteúdo em reprodução quando o dispositivo estiver no modo de baixo consumo de energia.

Para evitar reproduções durante o modo de baixo consumo de energia, substitua onStop() e interrompa qualquer conteúdo em reprodução:

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();
}

Quando o usuário liga novamente, onStart() é chamado se o app é o ativo em primeiro plano. Para mais informações sobre como iniciar e interromper uma atividade, consulte Ciclo de vida da atividade.