Gerenciar o hardware da TV

O hardware de TV é substancialmente diferente de outros dispositivos Android. As TVs não incluem alguns dos recursos de hardware encontrados em outros dispositivos Android, como touchscreens, câmeras e receptores de GPS. As TVs também dependem totalmente de dispositivos de hardware secundários: para interagir com apps de TV, os usuários precisam usar um controle remoto ou um gamepad. Para aprender mais sobre vários métodos de entrada, consulte Gerenciar controles de TV.

Ao criar um app para TV, considere cuidadosamente as limitações e os requisitos de hardware para operar em hardware de TV. Verifique se o app está sendo executado em uma TV e processe recursos de hardware não compatíveis.

Verificar se há um dispositivo de TV

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

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 exemplo de código 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, talvez seja possível contornar a indisponibilidade de determinados recursos de hardware. Nesta seção, discutimos 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

As TVs têm uma finalidade diferente de outros dispositivos, por isso não têm recursos de hardware que outros dispositivos Android costumam ter. 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 controles de TV têm um microfone, que não é o mesmo que a descrição de recursos de hardware de microfone descrita aqui. O microfone do controle é totalmente compatível.

Consulte a referência de recursos para ver uma lista completa de recursos, subrecursos e os descritores deles.

Declarar requisitos de hardware para TV

Os apps Android podem declarar requisitos de recursos de hardware no manifesto para garantir que não sejam instalados em dispositivos que não oferecem esses recursos. Se você estiver estendendo um app para uso na TV, revise atentamente o manifesto do app para ver se há declarações de requisitos de hardware que possam impedir a instalação em um dispositivo de TV.

Se o app usa recursos de hardware, como uma tela touch 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 eles não são necessários. O snippet de código de manifesto a seguir demonstra como declarar que seu app não requer recursos de hardware que não estão disponíveis em dispositivos de TV, mas usa esses recursos em dispositivos que não são de TV:

<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 recursos têm subrecursos, como android.hardware.camera.front, conforme descrito na 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 touch não é obrigatório, conforme descrito em Começar a usar apps de TV. Se o app normalmente usa 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 ao definir o valor como true impede que o app seja instalado em dispositivos de TV ou apareça na tela de início do Android TV.

Esteja ciente das permissões que implicam recursos de hardware

Algumas declarações de manifesto uses-permission implicam recursos de hardware. Esse comportamento significa que solicitar algumas permissões no manifesto do app pode impedir que ele seja instalado e usado em dispositivos de TV. As seguintes permissões comumente solicitadas 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 nível desejado da API 20 ou anterior)

ACCESS_FINE_LOCATION

android.hardware.location

android.hardware.location.gps (somente nível desejado da API 20 ou anterior)

ACCESS_WIFI_STATE
CHANGE_WIFI_STATE

android.hardware.wifi

Alguns dispositivos de TV têm apenas uma 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 que indica que ele não é obrigatório. android:required="false".

Observação: se o app for direcionado ao Android 5.0 (nível 21 da API) ou mais recente e usar a permissão ACCESS_COARSE_LOCATION ou ACCESS_FINE_LOCATION, os usuários ainda poderão instalar o app em uma TV, mesmo que ela não tenha uma placa de rede ou um receptor GPS.

Depois de tornar os recursos de hardware opcionais para o app, verifique a disponibilidade deles no momento da execução e ajuste 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 verificar 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 momento da 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

A maioria dos dispositivos de TV não tem telas touchscreen ou recursos de entrada de ponteiro e depende totalmente de controles remotos com botão direcional (D-pad) para navegação. Os apps de TV precisam sempre oferecer suporte a um controle remoto com botão direcional.

Para mais informações sobre como oferecer suporte adequado à navegação usando controles compatíveis com TV, consulte Navegação na TV.

Declarar suporte para toque

Alguns dispositivos de TV são compatíveis com controles remotos de ponteiro e telas touch. Seu app pode oferecer suporte a interações de clique, passagem do cursor e rolagem, como em um dispositivo móvel, para oferecer uma experiência melhor em dispositivos compatíveis.

Se o app permitir o modo de toque, você poderá declarar o suporte ao toque para todo o app ou para atividades individuais adicionando o elemento android.software.leanback.supports_touch <property> definido como true dentro do elemento <application> ou <activity> no AndroidManifest.xml:

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

Observação: em dispositivos que oferecem suporte a um controle remoto de apontamento (como um mouse aéreo ou trackpad), ativar essa opção ativa o modo de cursor e toque em vez de depender da emulação de compatibilidade da plataforma. Uma declaração no nível da atividade substitui a declaração no nível do aplicativo para essa atividade. A omissão dessa propriedade assume como padrão false.

Câmera

Embora uma TV normalmente não tenha uma câmera, você ainda pode fornecer um app relacionado à fotografia em uma TV. Por exemplo, se você tiver um app que tira, mostra e edita fotos, é possível desativar a funcionalidade de tirar fotos para TVs e ainda permitir que os usuários vejam e até editem fotos. Se você decidir ativar o app relacionado à câmera para funcionar em uma TV, adicione a seguinte declaração de recurso ao manifesto do app:

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

Se você permitir que o app seja executado sem uma câmera, adicione um código que detecte se o recurso de 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

As TVs são dispositivos fixos, usados em ambientes internos e não têm receptores de sistema de posicionamento global (GPS) integrados. Se o app usa informações de localização, você ainda pode permitir que os usuários pesquisem um local ou usem um provedor de localização estático, como um código postal configurado 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 = 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);
}

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

Alguns dispositivos de TV são compatíveis com 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 execução em segundo plano. A saída de áudio ainda fica ativada nesse modo. Portanto, interrompa qualquer conteúdo em reprodução quando o dispositivo estiver no modo de baixo consumo.

Para evitar a reprodução durante o modo de baixo consumo, 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 a energia novamente, onStart é chamado se o app estiver ativo em primeiro plano. Para mais informações sobre como iniciar e interromper uma atividade, consulte O ciclo de vida da atividade.