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 são também completamente dependentes de dispositivos de hardware secundários. Para que os usuários interajam com apps de TV, é preciso usar um controle remoto ou um controlador de jogo. Ao criar um app para TV, é preciso considerar cuidadosamente as limitações e as exigências de hardware para a operação em hardwares de TV.

Esta lição mostra como verificar se seu app está sendo executado em uma TV e como lidar com recursos de hardware incompatíveis. Para saber mais sobre vários métodos de entrada, consulte Como gerenciar controladores de TV.

Verificar se há um dispositivo de TV

Se você está criando um app que opere tanto em dispositivos de TV quanto em outros dispositivos, pode ser necessário verificar em que tipo de dispositivo seu app está sendo executado e ajustar a operação. Por exemplo, se você tem um app que pode ser iniciado por um Intent, seu aplicativo precisa verificar as propriedades do dispositivo para determinar se ele precisa iniciar uma atividade voltada à TV ou a um smartphone.

O modo recomendado para determinar se seu app está sendo executado em um dispositivo de TV é usar o método UiModeManager.getCurrentModeType() para verificar se o dispositivo está sendo executado no modo de televisão. A amostra de código a seguir mostra como conferir se o app está sendo executado em um dispositivo de TV:

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

Lidar com recursos de hardware incompatíveis

Dependendo do projeto e da funcionalidade do app, você pode ignorar determinados recursos de hardware indisponíveis. Esta seção discute que recursos de hardware não estão normalmente disponíveis para TV, como detectar recursos de hardware ausentes e sugere alternativas para usar esses recursos.

Recursos de hardware de TV incompatíveis

TVs têm uma funcionalidade diferente de outros dispositivos e, por isso, não têm recursos de hardware que outros dispositivos Android frequentemente têm. Por essa razão, o sistema Android não oferece compatibilidade com os 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 [1] android.hardware.microphone
Sensores android.hardware.sensor
Tela na orientação retrato android.hardware.screen.portrait

[1] 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.

Declaração dos requisitos de hardware para TV

Apps Android podem declarar requisitos de recursos de hardware no manifesto do app para garantir que eles não sejam instalados em dispositivos que não ofereçam esses recursos. Se estiver estendendo um app existente para uso em TVs, revise cuidadosamente o manifesto do app para detectar qualquer declaração de requisito de hardware que possa evitar que o app seja instalado em um dispositivo de TV.

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

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

Observação: alguns dos recursos têm subrecursos como android.hardware.camera.front, conforme descrito em Referência de recursos. Não deixe de marcar como required="false" qualquer subrecurso que também foi usado no app.

Todos os apps previstos para uso em dispositivos de TV precisam declarar que o recurso de touchscreen não é necessário, como descrito em Introdução a apps para TV. Se o app usa normalmente um ou mais recursos dentre os listados acima, altere a configuração do atributo android:required desses recursos para false no manifesto.

Cuidado: a declaração de um recurso de hardware como exigido definindo o valor para true evita que o app seja instalado em dispositivos de TV ou que apareça na tela inicial do Android TV.

Após decidir tornar os recursos de hardware opcionais para o app, é preciso confirmar a disponibilidade desses recursos no tempo de execução e ajustar o comportamento do app. A seção seguinte discute como verificar os recursos de hardware e sugere algumas abordagens para mudar o comportamento do seu app.

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

Declaração de permissões que implicam recursos de hardware

Algumas declarações uses-permission do manifesto implicam recursos de hardware. Esse comportamento significa que a solicitação de permissões no manifesto do app pode impedir que o app seja instalado e usado em dispositivos de TV. As seguintes permissões normalmente solicitadas criam uma exigência implícita 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 (apenas API de nível 20 ou anterior)

ACCESS_FINE_LOCATION

android.hardware.location

android.hardware.location.gps (apenas API de nível 20 ou anterior)

Para uma lista completa de solicitações de permissão que implicam uma exigência de recurso de hardware, consulte o guia uses-feature. Se o app exigir um dos recursos listados acima, inclua uma declaração uses-feature no manifesto para o recurso de hardware implicado que indique que ele não é obrigatório (android:required="false").

Observação: se seu app for destinado ao Android 5.0 (API de nível 21) ou posterior e usar a permissão ACCESS_COARSE_LOCATION ou ACCESS_FINE_LOCATION, os usuários ainda poderão instalá-lo em um dispositivo de TV, mesmo que a TV não tenha uma placa de rede ou um receptor de GPS.

Verificar se há recursos de hardware

A estrutura de trabalho 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 tempo de execução. Esse método usa um argumento de string único 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 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.");
    }
    

Touchscreen

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

Em dispositivos de TV, você precisa projetar o app para trabalhar com esse modelo de interação oferecendo compatibilidade com a navegação por um teclado direcional (D-pad) em um controle remoto de TV. Para mais informações sobre como oferecer a compatibilidade adequada à navegação usando controles compatíveis com TV, consulte Criação de navegação na TV.

Câmera

Apesar de uma TV normalmente não ter uma câmera, você pode oferecer um app relacionado a fotografia em um dispositivo de TV. Por exemplo, se você tem um app que tira, exibe e edita fotos, pode desativar essa funcionalidade de tirar fotos para TVs, mas ainda permitir que os usuários visualizem e até mesmo editem fotografias. Se decidir permitir que o app relacionado a câmeras funcione em uma TV, adicione a seguinte declaração de recurso ao manifesto:

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

Se você ativar o app para funcionar sem uma câmera, adicione código para detectar se o recurso de câmera está disponível e faça ajustes à operação do seu app. O exemplo de código a seguir demonstra como detectar a presença de uma câmera:

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

TVs são dispositivos estacionários para interiores e não têm um receptor de sistema de posicionamento global (GPS) integrado. Se o app usa informações de localização, você pode permitir que usuários pesquisem um local ou usem um provedor de localização estática, como um CEP definido durante a configuração do dispositivo.

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

Pausar reprodução no modo de baixo consumo de energia

Alguns dispositivos de TV oferecem 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 funcionando em segundo plano. Nesse modo, a saída de áudio permanece ativada, então seu app precisa interromper qualquer conteúdo em reprodução quando o dispositivo entra 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();
    }
    

Se seu app for o app ativo em primeiro plano quando o dispositivo for ligado novamente, onStart() será chamado. Para mais informações sobre como iniciar e interromper uma atividade, consulte Ciclo de vida da atividade.