Obsługa sprzętu telewizyjnego

Sprzęt telewizyjny znacznie różni się od innych urządzeń z Androidem. Telewizory nie mają niektórych funkcji sprzętowych dostępnych na innych urządzeniach z Androidem, takich jak ekrany dotykowe, aparaty czy odbiorniki GPS. Telewizory są też całkowicie zależne od dodatkowych urządzeń: aby użytkownicy mogli korzystać z aplikacji TV, muszą używać pilota lub gamepada. (Aby dowiedzieć się więcej o różnych metodach wprowadzania danych, przeczytaj artykuł Zarządzanie kontrolerami telewizora).

Podczas tworzenia aplikacji na telewizor należy dokładnie rozważyć ograniczenia sprzętowe i wymagania dotyczące działania na sprzęcie telewizyjnym. Sprawdź, czy aplikacja działa na telewizorze, i obsługuj nieobsługiwane funkcje sprzętowe.

Sprawdzanie, czy jest urządzenie TV

Jeśli tworzysz aplikację, która działa zarówno na telewizorach, jak i na innych urządzeniach, może być konieczne sprawdzenie, na jakim urządzeniu jest uruchomiona, i odpowiednie dostosowanie jej działania. Jeśli na przykład masz aplikację, którą można uruchomić za pomocą Intent, sprawdź właściwości urządzenia, aby określić, czy uruchomić aktywność przeznaczoną na telewizor czy na telefon.

Zalecanym sposobem sprawdzenia, czy aplikacja działa na telewizorze, jest użycie metody PackageManager.hasSystemFeature, aby sprawdzić, czy urządzenie działa w trybie telewizora. Poniższy przykładowy kod pokazuje, jak sprawdzić, czy aplikacja działa na telewizorze:

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

Obsługa nieobsługiwanych funkcji sprzętowych

W zależności od projektu i funkcji aplikacji możesz obejść problem niedostępności niektórych funkcji sprzętowych. W tej sekcji omawiamy funkcje sprzętowe, które zwykle nie są dostępne na telewizorach, sposoby wykrywania brakujących funkcji sprzętowych oraz sugerowane alternatywy dla tych funkcji.

Nieobsługiwane funkcje sprzętowe telewizora

Telewizory mają inne przeznaczenie niż inne urządzenia, więc nie mają funkcji sprzętowych, które często mają inne urządzenia z Androidem. Z tego powodu system Android nie obsługuje na telewizorach tych funkcji:

Sprzęt Deskryptor funkcji Androida
Ekran dotykowy android.hardware.touchscreen
Emulator ekranu dotykowego android.hardware.faketouch
Połączenia telefoniczne android.hardware.telephony
Aparat android.hardware.camera
Komunikacja Near Field Communication (NFC) android.hardware.nfc
GPS android.hardware.location.gps
Mikrofon android.hardware.microphone
Czujniki android.hardware.sensor
Ekran w orientacji pionowej android.hardware.screen.portrait

Uwaga: niektóre kontrolery telewizyjne mają mikrofon, który nie jest tym samym co opisana tutaj funkcja sprzętowa mikrofonu. Mikrofon kontrolera jest w pełni obsługiwany.

Pełną listę funkcji, podfunkcji i ich deskryptorów znajdziesz w dokumentacji funkcji.

Deklarowanie wymagań sprzętowych dotyczących telewizorów

Aplikacje na Androida mogą deklarować wymagania dotyczące funkcji sprzętowych w pliku manifestu aplikacji, aby nie były instalowane na urządzeniach, które nie obsługują tych funkcji. Jeśli rozszerzasz istniejącą aplikację do użytku na telewizorze, dokładnie sprawdź jej plik manifestu pod kątem deklaracji wymagań sprzętowych, które mogą uniemożliwić jej instalację na telewizorze.

Jeśli aplikacja wykorzystuje funkcje sprzętowe, takie jak ekran dotykowy czy aparat, które są niedostępne na telewizorze, ale może działać bez tych funkcji, zmodyfikuj plik manifestu aplikacji, aby wskazać, że te funkcje nie są wymagane. Poniższy fragment kodu pliku manifestu pokazuje, jak zadeklarować, że aplikacja nie wymaga funkcji sprzętowych, które są niedostępne na telewizorach, ale używa ich na innych urządzeniach:

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

Uwaga: niektóre funkcje mają funkcje podrzędne, takie jak android.hardware.camera.front, zgodnie z opisem w dokumentacji funkcji. Pamiętaj, aby oznaczyć wszystkie funkcje podrzędne używane w aplikacji jako required="false".

Wszystkie aplikacje przeznaczone do używania na telewizorach muszą deklarować, że funkcja ekranu dotykowego nie jest wymagana, zgodnie z opisem w artykule Pierwsze kroki z aplikacjami TV. Jeśli Twoja aplikacja zwykle korzysta z co najmniej 1 funkcji nieobsługiwanej przez telewizory, zmień ustawienie atrybutu android:required na false w przypadku tych funkcji w pliku manifestu.

Uwaga: jeśli zadeklarujesz funkcję sprzętową jako wymaganą, ustawiając jej wartość na true, uniemożliwi to instalowanie aplikacji na telewizorach i wyświetlanie jej w menu na ekranie głównym Androida TV.

Pamiętaj o uprawnieniach, które wymagają funkcji sprzętowych

Niektóre deklaracje w pliku manifestu uses-permission wskazują na funkcje sprzętowe. Oznacza to, że prośba o niektóre uprawnienia w manifeście aplikacji może uniemożliwić jej instalowanie i używanie na telewizorach. Te często wymagane uprawnienia tworzą domyślne wymaganie dotyczące funkcji sprzętowej:

Uprawnienie Sugerowana funkcja sprzętowa
RECORD_AUDIO android.hardware.microphone
CAMERA android.hardware.camera oraz
android.hardware.camera.autofocus
ACCESS_COARSE_LOCATION

android.hardware.location

android.hardware.location.network (tylko docelowy poziom API 20 lub niższy)

ACCESS_FINE_LOCATION

android.hardware.location

android.hardware.location.gps (tylko docelowy poziom API 20 lub niższy)

ACCESS_WIFI_STATE
CHANGE_WIFI_STATE

android.hardware.wifi

Niektóre telewizory mają tylko połączenie Ethernet.

Pełną listę próśb o uprawnienia, które wymagają funkcji sprzętowej, znajdziesz w uses-feature. Jeśli Twoja aplikacja wymaga jednej z wymienionych wcześniej funkcji, dodaj w pliku manifestu deklarację uses-feature dotyczącą domniemanej funkcji sprzętowej, która wskazuje, że nie jest ona wymagana. android:required="false".

Uwaga: jeśli aplikacja jest kierowana na Androida 5.0 (poziom interfejsu API 21) lub nowszego i używa uprawnienia ACCESS_COARSE_LOCATION lub ACCESS_FINE_LOCATION, użytkownicy mogą ją zainstalować na telewizorze, nawet jeśli nie ma on karty sieciowej ani odbiornika GPS.

Po ustawieniu funkcji sprzętowych jako opcjonalnych dla aplikacji musisz sprawdzać ich dostępność w czasie działania, a następnie dostosowywać działanie aplikacji. W następnej sekcji dowiesz się, jak sprawdzić funkcje sprzętowe, i poznasz kilka sposobów na zmianę działania aplikacji.

Więcej informacji o filtrowaniu i deklarowaniu funkcji w pliku manifestu znajdziesz w przewodniku uses-feature.

Sprawdzanie funkcji sprzętowych

Platforma Androida może poinformować Cię, czy funkcje sprzętowe są niedostępne na urządzeniu, na którym działa aplikacja. Użyj metody hasSystemFeature(String), aby sprawdzić, czy określone funkcje są dostępne w czasie działania. Ta metoda przyjmuje jeden argument w postaci ciągu znaków, który określa funkcję, którą chcesz sprawdzić.

Poniższy przykładowy kod pokazuje, jak wykryć dostępność funkcji sprzętowych w czasie działania:

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

Ekran dotykowy

Większość telewizorów nie ma ekranów dotykowych ani funkcji wprowadzania danych za pomocą wskaźnika i do nawigacji wykorzystuje wyłącznie piloty z padem kierunkowym. Aplikacje TV muszą zawsze obsługiwać pilota z padem kierunkowym.

Więcej informacji o prawidłowej obsłudze nawigacji za pomocą elementów sterujących dostosowanych do telewizorów znajdziesz w artykule Nawigacja na telewizorze.

Deklarowanie obsługi dotykowej

Niektóre telewizory obsługują piloty ze wskaźnikiem i ekrany dotykowe. Aplikacja może obsługiwać interakcje polegające na klikaniu, najechaniu kursorem i przewijaniu, podobnie jak na urządzeniu mobilnym, aby zapewnić lepsze wrażenia na urządzeniach, które je obsługują.

Jeśli aplikacja obsługuje tryb dotykowy, możesz zadeklarować obsługę dotyku dla całej aplikacji lub poszczególnych aktywności, dodając element android.software.leanback.supports_touch <property> ustawiony na true wewnątrz elementu <application> lub <activity> w pliku AndroidManifest.xml:

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

Uwaga: na urządzeniach, które obsługują pilota ze wskaźnikiem (np. mysz powietrzną lub trackpad), włączenie tej opcji powoduje włączenie trybu kursora i dotyku zamiast polegania na emulacji zgodności platformy. Deklaracja na poziomie aktywności zastępuje deklarację na poziomie aplikacji dla tej aktywności. Jeśli pominiesz tę właściwość, domyślnie zostanie użyta wartość false.

Aparat

Chociaż telewizor zwykle nie ma aparatu, nadal możesz udostępniać na nim aplikację związaną z fotografią. Jeśli na przykład masz aplikację, która robi, wyświetla i edytuje zdjęcia, możesz wyłączyć funkcję robienia zdjęć na telewizorach, ale nadal umożliwiać użytkownikom wyświetlanie, a nawet edytowanie zdjęć. Jeśli zdecydujesz się włączyć obsługę aplikacji związanej z aparatem na telewizorze, dodaj do pliku manifestu aplikacji tę deklarację funkcji:

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

Jeśli umożliwisz działanie aplikacji bez aparatu, dodaj do niej kod, który wykrywa, czy funkcja aparatu jest dostępna, i odpowiednio dostosowuje działanie aplikacji. Poniższy przykładowy kod pokazuje, jak wykryć obecność aparatu:

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

Telewizory to urządzenia stacjonarne, które są używane w pomieszczeniach i nie mają wbudowanych odbiorników globalnego systemu pozycjonowania (GPS). Jeśli aplikacja korzysta z informacji o lokalizacji, możesz nadal zezwalać użytkownikom na wyszukiwanie lokalizacji lub używać statycznego dostawcy lokalizacji, np. kodu pocztowego skonfigurowanego podczas konfiguracji telewizora.

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

Wstrzymywanie odtwarzania w trybie oszczędzania energii

Niektóre telewizory obsługują tryb oszczędzania baterii, gdy użytkownik wyłączy urządzenie. Zamiast wyłączać się, urządzenie wyłącza wyświetlacz i utrzymuje działanie Androida TV w tle. W tym trybie wyjście audio jest nadal włączone, więc zatrzymaj odtwarzanie wszystkich treści, gdy urządzenie jest w trybie oszczędzania baterii.

Aby uniknąć odtwarzania w trybie oszczędzania baterii, zastąp onStop i zatrzymaj odtwarzanie wszystkich treści:

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

Gdy użytkownik ponownie włączy zasilanie, wywoływana jest metoda onStart, jeśli Twoja aplikacja jest aktywną aplikacją na pierwszym planie. Więcej informacji o rozpoczynaniu i zatrzymywaniu aktywności znajdziesz w artykule Cykl życia aktywności.