Interfejsy API Androida 4.3

Poziom API: 18

Android 4.3 (JELLY_BEAN_MR2) to aktualizacja wersji Jelly Bean, która udostępnia nowe funkcje dla użytkowników i deweloperów aplikacji. Ten dokument zawiera wprowadzenie do najbardziej znanych nowych interfejsów API.

Deweloper aplikacji powinien jak najszybciej pobrać obraz systemu Android 4.3 i platformę SDK z Menedżera pakietów SDK. Jeśli nie masz urządzenia z Androidem 4.3, na którym chcesz przetestować aplikację, użyj obrazu systemu Android 4.3, by przetestować aplikację w emulatorze Androida. Następnie skompiluj aplikacje na platformie Androida 4.3, aby zacząć korzystać z najnowszych interfejsów API.

Aktualizowanie docelowego poziomu interfejsu API

Aby lepiej zoptymalizować aplikację pod kątem urządzeń z Androidem 4.3, ustaw targetSdkVersion na "18", zainstaluj ją na obrazie systemu Androida 4.3, przetestuj ją, a następnie opublikuj aktualizację z tą zmianą.

Możesz używać interfejsów API w Androidzie 4.3, a jednocześnie obsługiwać starsze wersje. Aby to zrobić, dodaj do kodu warunki, które przed wykonaniem interfejsów API nieobsługiwanych przez minSdkVersion sprawdzają poziom interfejsu API systemu. Więcej informacji o utrzymywaniu zgodności wstecznej znajdziesz w artykule Obsługa różnych wersji platformy.

W bibliotece pomocy Androida dostępne są różne interfejsy API, które umożliwiają wdrażanie nowych funkcji w starszych wersjach platformy.

Więcej informacji o tym, jak działają poziomy interfejsu API, znajdziesz w artykule Co to jest poziom interfejsu API?.

Ważne zmiany w działaniu

Jeśli masz już opublikowaną aplikację na Androida, pamiętaj, że zmiany w Androidzie 4.3 mogą na nią wpływać.

Jeśli aplikacja używa intencji niejawnych...

Twoja aplikacja może działać nieprawidłowo w środowisku profilu ograniczonego.

Użytkownicy w środowisku o profilu z ograniczonym dostępem mogą nie mieć dostępu do wszystkich standardowych aplikacji na Androida. Na przykład profil z ograniczonym dostępem może mieć wyłączoną przeglądarkę i aplikację aparatu. Aplikacja nie powinna więc sugerować, które aplikacje są dostępne, ponieważ jeśli wywołasz startActivity() bez sprawdzenia, czy aplikacja jest dostępna do obsługi funkcji Intent, może się ona popsuć w profilu z ograniczonym dostępem.

Jeśli korzystasz z intencji niejawnej, zawsze sprawdzaj, czy aplikacja jest dostępna do obsługi intencji, wywołując metodę resolveActivity() lub queryIntentActivities(). Na przykład:

Kotlin

val intent = Intent(Intent.ACTION_SEND)
...
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show()
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
...
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show();
}

Jeśli Twoja aplikacja wymaga kont...

Twoja aplikacja może działać nieprawidłowo w środowisku profilu ograniczonego.

Użytkownicy w środowisku profili z ograniczonym dostępem domyślnie nie mają dostępu do kont użytkowników. Jeśli aplikacja zależy od typu Account, może ulec awarii lub działać w nieoczekiwany sposób po użyciu w profilu z ograniczeniami.

Jeśli chcesz całkowicie uniemożliwić profilom z ograniczonym dostępem korzystanie z Twojej aplikacji, ponieważ działanie aplikacji zależy od poufnych informacji o koncie, podaj atrybut android:requiredAccountType w elemencie <application> pliku manifestu.

Jeśli chcesz, aby profile z ograniczonym dostępem mogły nadal korzystać z Twojej aplikacji, nawet jeśli nie mogą tworzyć własnych kont, możesz wyłączyć funkcje aplikacji, które wymagają konta, lub zezwolić profilom z ograniczonym dostępem na dostęp do kont utworzonych przez głównego użytkownika. Więcej informacji znajdziesz w poniższej sekcji dotyczącej obsługi kont w profilu z ograniczonym dostępem.

Jeśli aplikacja korzysta z funkcji VideoView...

W Androidzie 4.3 Twój film może być mniejszy.

W poprzednich wersjach Androida widżet VideoView nieprawidłowo obliczył wartość "wrap_content" dla właściwości layout_height i layout_width, tak aby była identyczna z wartością "match_parent". Jeśli więc ustawisz właściwość "wrap_content" na potrzeby wysokości lub szerokości, możesz wcześniej uzyskać pożądany układ wideo, co może spowodować zmniejszenie filmu w Androidzie 4.3 i nowszych. Aby rozwiązać ten problem, zastąp "wrap_content" fragmentem "match_parent" i sprawdź, czy film wyświetla się prawidłowo na Androidzie 4.3 i w starszych wersjach.

Profile z ograniczonym dostępem

Na tabletach z Androidem użytkownicy mogą teraz tworzyć profile z ograniczeniami na podstawie głównego użytkownika. Gdy użytkownicy utworzą profil z ograniczonym dostępem, mogą włączyć ograniczenia, np. dotyczące dostępności aplikacji. Nowy zestaw interfejsów API w Androidzie 4.3 pozwala też na tworzenie szczegółowych ustawień ograniczeń dla aplikacji, które tworzysz. Na przykład nowe interfejsy API pozwalają użytkownikom kontrolować, jakie typy treści są dostępne w Twojej aplikacji, gdy działa ona w środowisku profilu z ograniczeniami.

Interfejs umożliwiający użytkownikom kontrolowanie utworzonych przez Ciebie ograniczeń jest zarządzany przez aplikację Ustawienia systemu. Aby wyświetlić użytkownikom ustawienia ograniczeń aplikacji, musisz zadeklarować ograniczenia, które ona zapewnia. W tym celu utwórz BroadcastReceiver, który odbiera intencję ACTION_GET_RESTRICTION_ENTRIES. System wywołuje tę intencję, aby wysyłać zapytania o dostępne ograniczenia do wszystkich aplikacji, a następnie kompilowa interfejs użytkownika tak, aby mógł zarządzać ograniczeniami w przypadku każdego profilu z ograniczeniami.

W metodzie onReceive() BroadcastReceiver musisz utworzyć RestrictionEntry dla każdego ograniczenia nakładanego przez aplikację. Każdy element RestrictionEntry ma tytuł, opis i jeden z tych typów danych:

  • TYPE_BOOLEAN w przypadku ograniczenia, które ma wartość prawda lub fałsz.
  • TYPE_CHOICE w przypadku ograniczenia zawierającego wiele wzajemnie wykluczających się opcji (opcje).
  • TYPE_MULTI_SELECT w przypadku ograniczenia zawierającego wiele opcji, które nie wzajemnie się wykluczają (opcje pól wyboru).

Następnie umieszczasz wszystkie obiekty RestrictionEntry w obiekcie ArrayList i umieszczasz je w wyniku odbiornika jako wartość nadmiarowego EXTRA_RESTRICTIONS_LIST.

System tworzy interfejs z ograniczeniami aplikacji w aplikacji Ustawienia i zapisuje je za pomocą unikalnego klucza podanego dla każdego obiektu RestrictionEntry. Gdy użytkownik otworzy aplikację, możesz przesłać zapytanie o obecne ograniczenia, wywołując getApplicationRestrictions(). Zwraca ono Bundle zawierające pary klucz-wartość dla każdego ograniczenia zdefiniowanego w obiektach RestrictionEntry.

Jeśli chcesz podać bardziej szczegółowe ograniczenia, których nie można obsługiwać przy użyciu wartości logicznych, jednokrotnego wyboru ani wartości wielokrotnego wyboru, możesz utworzyć działanie, w którym użytkownik będzie mógł określić ograniczenia i umożliwić im uruchomienie danej aktywności z poziomu ustawień ograniczeń. W odbiorniku transmisji dodaj do wyniku Bundle dodatek EXTRA_RESTRICTIONS_INTENT. Ten dodatek musi określać klasę Intent wskazującą klasę Activity do uruchomienia (użyj metody putParcelable(), aby przekazać intencję EXTRA_RESTRICTIONS_INTENT). Gdy główny użytkownik przejdzie do działania, aby ustawić ograniczenia niestandardowe, musi ona zwrócić wynik zawierający wartości ograniczeń dodatkowo za pomocą klucza EXTRA_RESTRICTIONS_LIST lub EXTRA_RESTRICTIONS_BUNDLE w zależności od tego, czy wskażesz obiekty RestrictionEntry czy pary klucz-wartość.

Obsługa kont w profilu z ograniczonym dostępem

Wszystkie konta dodane do użytkownika głównego są dostępne w przypadku profilu z ograniczonym dostępem, ale domyślnie konta nie są dostępne przez interfejsy API AccountManager. Jeśli spróbujesz dodać konto AccountManager w profilu z ograniczeniami, zakończy się niepowodzeniem. Z powodu tych ograniczeń masz do wyboru 3 opcje:

  • Zezwól na dostęp do kont właściciela z poziomu profilu ograniczonego.

    Aby uzyskać dostęp do konta z profilu ograniczonego, musisz dodać atrybut android:restrictedAccountType do tagu <application>:

    <application ...
        android:restrictedAccountType="com.example.account.type" >
    

    Uwaga: włączenie tego atrybutu daje aplikacji dostęp do kont głównego użytkownika z profili ograniczonych. Należy więc zezwolić na to tylko wtedy, gdy informacje wyświetlane przez aplikację nie zawierają informacji umożliwiających identyfikację osób, które są uznawane za poufne. Ustawienia systemowe poinformują głównego użytkownika o tym, że Twoja aplikacja udostępnia swoim kontom profile z ograniczonym dostępem, dlatego dla użytkownika powinno być jasne, że dostęp do konta jest ważny dla działania aplikacji. W miarę możliwości należy też zapewnić głównemu użytkownikowi odpowiednie ograniczenia, które określają dozwolony poziom dostępu aplikacji do konta.

  • Jeśli nie możesz zmodyfikować kont, wyłącz niektóre funkcje.

    Jeśli chcesz korzystać z kont, ale nie potrzebujesz ich do realizowania swoich głównych funkcji, możesz sprawdzić dostępność kont i wyłączyć funkcje, gdy nie są dostępne. Najpierw sprawdź, czy już masz takie konto. Jeśli nie, zapytaj, czy można utworzyć nowe konto, wywołując funkcję getUserRestrictions(), i sprawdź dodatkowo informację o DISALLOW_MODIFY_ACCOUNTS w wyniku. Jeśli jest to true, wyłącz wszelkie funkcje aplikacji, które wymagają dostępu do kont. Na przykład:

    Kotlin

    val um = context.getSystemService(Context.USER_SERVICE) as UserManager
    val restrictions: Bundle = um.userRestrictions
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }
    

    Java

    UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    Bundle restrictions = um.getUserRestrictions();
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }
    

    Uwaga: w tym przypadku nie należy deklarować nowych atrybutów w pliku manifestu.

  • Wyłącz aplikację, gdy nie możesz uzyskać dostępu do kont prywatnych.

    Jeśli jednak Twoim zdaniem aplikacja nie ma być dostępna dla profili z ograniczonym dostępem, ponieważ jest uzależniona od poufnych danych osobowych na koncie (oraz ze względu na to, że profile z ograniczeniami nie mogą obecnie dodawać nowych kont), dodaj atrybut android:requiredAccountType do tagu <application>:

    <application ...
        android:requiredAccountType="com.example.account.type" >
    

    Na przykład aplikacja Gmail używa tego atrybutu do wyłączania się w profilach z ograniczeniami, ponieważ osobisty adres e-mail właściciela nie powinien być dostępny w profilach z ograniczonym dostępem.

  • Łączność bezprzewodowa

    Bluetooth Low Energy (technologia Smart)

    Android obsługuje teraz Bluetooth Low Energy (LE) z nowymi interfejsami API w android.bluetooth. Dzięki nowym interfejsom API możesz tworzyć aplikacje na Androida, które komunikują się z urządzeniami peryferyjnymi Bluetooth Low Energy, takimi jak pulsometr czy krokomierze.

    Bluetooth LE to funkcja sprzętowa, która nie jest dostępna na wszystkich urządzeniach z Androidem, więc w pliku manifestu musisz zadeklarować element <uses-feature> dla "android.hardware.bluetooth_le":

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
    

    Jeśli znasz już klasyczne interfejsy API Bluetooth na Androida, zwróć uwagę na pewne różnice w korzystaniu z interfejsów API Bluetooth LE. Przede wszystkim jest teraz klasa BluetoothManager, której należy używać do wykonywania niektórych działań ogólnych, takich jak pozyskiwanie BluetoothAdapter, pobieranie listy połączonych urządzeń i sprawdzanie stanu urządzenia. Na przykład aby pobrać BluetoothAdapter w ten sposób:

    Kotlin

    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothAdapter = bluetoothManager.adapter
    

    Java

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();
    

    Aby wykryć urządzenia peryferyjne Bluetooth LE, wywołaj metodę startLeScan() w BluetoothAdapter i przekaż jej implementację interfejsu BluetoothAdapter.LeScanCallback. Gdy przejściówka Bluetooth wykryje urządzenie peryferyjne Bluetooth LE, Twoja implementacja BluetoothAdapter.LeScanCallback otrzyma wywołanie metody onLeScan(). Ta metoda udostępnia obiekt BluetoothDevice reprezentujący wykryte urządzenie, wartość RSSI dla urządzenia oraz tablicę bajtów zawierającą rekord reklam urządzenia.

    Jeśli chcesz skanować w poszukiwaniu tylko określonych typów urządzeń peryferyjnych, możesz zamiast tego wywołać startLeScan() i dołączyć tablicę obiektów UUID, które określają usługi GATT obsługiwane przez Twoją aplikację.

    Uwaga: możesz skanować tylko w poszukiwaniu urządzeń Bluetooth LE lub w poszukiwaniu klasycznych urządzeń Bluetooth przy użyciu poprzednich interfejsów API. Nie można jednocześnie skanować w poszukiwaniu urządzeń LE i Classic.

    Aby połączyć się z urządzeniem peryferyjnym Bluetooth LE, wywołaj connectGatt() na odpowiednim obiekcie BluetoothDevice i przekaż mu implementację BluetoothGattCallback. Twoja implementacja BluetoothGattCallback otrzymuje wywołania zwrotne dotyczące stanu połączenia z urządzeniem i innych zdarzeń. To w trakcie wywołania zwrotnego onConnectionStateChange() możesz rozpocząć komunikację z urządzeniem, jeśli metoda przekaże STATE_CONNECTED jako nowy stan.

    Aby uzyskać dostęp do funkcji Bluetooth na urządzeniu, aplikacja musi też prosić o określone uprawnienia użytkownika Bluetooth. Więcej informacji znajdziesz w przewodniku po interfejsie API Bluetooth Low Energy.

    Tryb tylko skanowania Wi-Fi

    Podczas próby rozpoznania lokalizacji użytkownika Android może użyć Wi-Fi, aby uzyskać pomoc przez skanowanie pobliskich punktów dostępu. Jednak użytkownicy często wyłączają Wi-Fi, aby oszczędzać baterię, przez co dane o lokalizacji są mniej dokładne. Android oferuje teraz tryb „tylko skanowanie”, który pozwala sieci Wi-Fi na skanowanie punktów dostępu. Dzięki temu można ustalić lokalizację bez łączenia się z punktem dostępu, co znacznie zmniejsza wykorzystanie baterii.

    Jeśli chcesz uzyskać lokalizację użytkownika, gdy Wi-Fi jest obecnie wyłączone, możesz poprosić użytkownika o włączenie trybu skanowania Wi-Fi, wywołując startActivity() i wykonując ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE.

    Konfiguracja Wi-Fi

    Nowe interfejsy API WifiEnterpriseConfig pozwalają usługom dla firm zautomatyzować konfigurację Wi-Fi na urządzeniach zarządzanych.

    Szybka odpowiedź na połączenia przychodzące

    Od Androida 4.0 dostępna jest funkcja „Szybka odpowiedź”, która pozwala odpowiadać na połączenia przychodzące natychmiastowo SMS-ami, bez potrzeby odbierania połączenia czy odblokowywania urządzenia. Do tej pory te krótkie wiadomości były zawsze obsługiwane przez domyślną aplikację do obsługi wiadomości. Teraz każda aplikacja może zadeklarować swoją zdolność do obsługi tych wiadomości, tworząc Service z filtrem intencji dla ACTION_RESPOND_VIA_MESSAGE.

    Gdy użytkownik odpowie szybką odpowiedzią na połączenie przychodzące, aplikacja Telefon wysyła intencję ACTION_RESPOND_VIA_MESSAGE z identyfikatorem URI opisującym odbiorcę (rozmówcę) i dodatkowo EXTRA_TEXT z wiadomością, którą użytkownik chce wysłać. Gdy usługa otrzyma intencję, powinna przekazać komunikat i natychmiast się zatrzymać (aplikacja nie powinna pokazywać aktywności).

    Aby otrzymać tę intencję, musisz zadeklarować uprawnienie SEND_RESPOND_VIA_MESSAGE.

    Multimedia

    Ulepszenia MediaExtractor i MediaCodec

    Android ułatwia teraz pisanie własnych odtwarzaczy z możliwością dynamicznego przesyłania strumieniowego przez HTTP (DASH) zgodnie ze standardem ISO/IEC 23009-1 przy użyciu istniejących interfejsów API w MediaCodec i MediaExtractor. Platforma stanowiąca podstawę tych interfejsów API została zaktualizowana, aby umożliwić analizowanie pofragmentowanych plików MP4, ale Twoja aplikacja nadal odpowiada za analizowanie metadanych MPD i przekazywanie poszczególnych strumieni do MediaExtractor.

    Jeśli chcesz używać DASH w przypadku zaszyfrowanych treści, zwróć uwagę na to, że metoda getSampleCryptoInfo() zwraca metadane MediaCodec.CryptoInfo opisujące strukturę każdej zaszyfrowanej próbki multimediów. Do usługi MediaExtractor została też dodana metoda getPsshInfo(), która umożliwia dostęp do metadanych PSSH dotyczących multimediów DASH. Ta metoda zwraca mapowanie obiektów UUID na bajty, gdzie UUID określa schemat kryptograficzny, a bajty to dane właściwe dla tego schematu.

    DRM multimediów

    Nowa klasa MediaDrm to modułowe rozwiązanie do zarządzania prawami cyfrowymi (DRM) do treści multimedialnych, dzięki czemu oddziela on problemy z zabezpieczeniami DRM od odtwarzania multimediów. Na przykład rozdzielenie interfejsów API umożliwia odtwarzanie treści zaszyfrowanych za pomocą Widevine bez konieczności używania formatu multimediów Widevine. To rozwiązanie DRM obsługuje też standard DASH Common Encryption, więc można używać różnych schematów DRM w przypadku strumieniowanych treści.

    MediaDrm umożliwia uzyskiwanie nieprzezroczystych komunikatów z żądaniem klucza i przetwarzanie wiadomości z odpowiedzią z serwera na potrzeby pozyskiwania i udostępniania licencji. Twoja aplikacja odpowiada za obsługę komunikacji sieciowej z serwerami. Klasa MediaDrm umożliwia tylko generowanie i przetwarzanie wiadomości.

    Interfejsy API MediaDrm powinny być używane w połączeniu z interfejsami API MediaCodec, które zostały wprowadzone w Androidzie 4.1 (poziom API 16), w tym z interfejsami MediaCodec do kodowania i dekodowania treści, MediaCrypto do obsługi zaszyfrowanych treści i MediaExtractor do wyodrębniania i demuksowania treści.

    Najpierw musisz utworzyć obiekty MediaExtractor i MediaCodec. Następnie możesz uzyskać dostęp do schematu DRM (UUID), zwykle z poziomu metadanych w treści, i użyć go do utworzenia instancji obiektu MediaDrm za pomocą jego konstruktora.

    Kodowanie wideo z platformy

    Do Androida 4.1 (poziom interfejsu API 16) dodano klasę MediaCodec do niskopoziomowego kodowania i dekodowania treści multimedialnych. Podczas kodowania filmów Android 4.1 wymagał dostarczenia multimediów w tablicy ByteBuffer, natomiast Android 4.3 pozwala teraz na użycie Surface jako danych wejściowych kodera. Pozwala to na przykład zakodować dane wejściowe z istniejącego pliku wideo lub użyć klatek wygenerowanych przez OpenGL ES.

    Aby użyć elementu Surface jako danych wejściowych kodera, najpierw wywołaj configure() dla MediaCodec. Następnie zadzwoń pod numer createInputSurface(), aby otrzymać urządzenie Surface, na którym możesz przesyłać multimedia.

    Możesz na przykład użyć podanego Surface jako okna dla kontekstu OpenGL, przekazując go do interfejsu eglCreateWindowSurface(). Następnie podczas renderowania powierzchni wywołaj eglSwapBuffers(), aby przekazać klatkę do elementu MediaCodec.

    Aby rozpocząć kodowanie, wywołaj start() na urządzeniu MediaCodec. Gdy skończysz, wywołaj signalEndOfInputStream(), aby zakończyć kodowanie, i wywołaj metodę release() na Surface.

    Powielanie multimediów

    Nowa klasa MediaMuxer umożliwia multipleksowanie między 1 strumieniem audio i 1 strumieniem wideo. Te interfejsy API służą jako odpowiedniki klasy MediaExtractor dodanej w Androidzie 4.2 na potrzeby demultipleksowania multimediów.

    Obsługiwane formaty wyjściowe są zdefiniowane w polu MediaMuxer.OutputFormat. Obecnie jedynym obsługiwanym formatem wyjściowym jest MP4, a MediaMuxer obsługuje tylko 1 strumień audio lub 1 strumień wideo naraz.

    Komponent MediaMuxer został opracowany głównie z myślą o współpracy z MediaCodec, więc można przetwarzać filmy za pomocą MediaCodec, a następnie zapisywać dane wyjściowe w pliku MP4 za pomocą MediaMuxer. Możesz też używać MediaMuxer w połączeniu z MediaExtractor, aby edytować multimedia bez konieczności ich kodowania ani dekodowania.

    Postęp odtwarzania i przewijanie dla RemoteControlClient

    W Androidzie 4.0 (poziom interfejsu API 14) dodano RemoteControlClient, aby umożliwić sterowanie odtwarzaniem multimediów z klientów zdalnych, np. elementy sterujące dostępne na ekranie blokady. Android 4.3 umożliwia teraz takim kontrolerom wyświetlanie pozycji odtwarzania i elementów sterujących do przeglądania odtwarzania. Jeśli do aplikacji multimedialnej masz włączone interfejsy API RemoteControlClient, możesz zezwolić na przeglądanie treści przy odtwarzaniu, implementując dwa nowe interfejsy.

    Najpierw musisz włączyć flagę FLAG_KEY_MEDIA_POSITION_UPDATE, przekazując ją do setTransportControlsFlags().

    Następnie zaimplementuj dwa nowe interfejsy:

    RemoteControlClient.OnGetPlaybackPositionListener
    Obejmuje to wywołanie zwrotne onGetPlaybackPosition(), które żąda bieżącej pozycji multimediów, gdy pilot musi zaktualizować postęp w swoim interfejsie.
    RemoteControlClient.OnPlaybackPositionUpdateListener
    Obejmuje to wywołanie zwrotne onPlaybackPositionUpdate(), które informuje aplikację o nowym kodzie czasu multimediów, gdy użytkownik przewija odtwarzanie za pomocą interfejsu pilota.

    Po zmianie pozycji odtwarzania na nową pozycję wywołaj funkcję setPlaybackState(), aby wskazać nowy stan, pozycję i szybkość odtwarzania.

    Po zdefiniowaniu tych interfejsów możesz ustawić je dla interfejsu RemoteControlClient, wywołując odpowiednio metodę setOnGetPlaybackPositionListener() i setPlaybackPositionUpdateListener().

    Grafika

    Obsługa OpenGL ES 3.0

    Android 4.3 dodaje interfejsy Java i wbudowaną obsługę OpenGL ES 3.0. Najważniejsze nowe funkcje dostępne w OpenGL ES 3.0 to:

    • Przyspieszenie rozwoju zaawansowanych efektów wizualnych
    • Wysoka jakość kompresji tekstur ETC2/EAC jako funkcja standardowa
    • Nowa wersja języka cieniowania GLSL ES z obsługą liczb całkowitych i 32-bitowych zmiennoprzecinkowych.
    • Zaawansowane renderowanie tekstur
    • Szersza standaryzacja rozmiaru tekstur i formatów bufora renderowania

    Interfejs Java dla OpenGL ES 3.0 na Androidzie jest dostarczany z GLES30. Jeśli korzystasz z platformy OpenGL ES 3.0, zadeklaruj to w pliku manifestu za pomocą tagu <uses-feature> i atrybutu android:glEsVersion. Na przykład:

    <manifest>
        <uses-feature android:glEsVersion="0x00030000" />
        ...
    </manifest>
    

    Pamiętaj, aby określić kontekst OpenGL ES, wywołując setEGLContextClientVersion(), przekazując 3 jako wersję.

    Więcej informacji o korzystaniu z OpenGL ES, w tym o sprawdzaniu obsługiwanej wersji OpenGL ES w czasie działania urządzenia, znajdziesz w przewodniku po interfejsie API OpenGL ES.

    Mipmappowanie elementów graficznych

    Użycie mipmapy jako źródła bitmapy lub elementu z elementami rysunkowymi to prosty sposób na zapewnienie wysokiej jakości obrazu i różnych skal obrazów, co może być szczególnie przydatne, jeśli spodziewasz się, że obraz będzie skalowany podczas animacji.

    Android 4.2 (poziom interfejsu API 17) dodał obsługę map mipmap w klasie Bitmap – Android zamienia obrazy mip w Bitmap, jeśli podasz źródło mipmap i włączysz funkcję setHasMipMap(). Teraz w Androidzie 4.3 można włączyć mapy mipmaps także dla obiektu BitmapDrawable, udostępniając zasób mipmap i ustawiając atrybut android:mipMap w pliku zasobów bitmapy lub wywołując hasMipMap().

    Interfejs

    Wyświetl nakładki

    Nowa klasa ViewOverlay tworzy przezroczystą warstwę na elemencie View, do której można dodawać treści wizualne. Nie ma ona wpływu na hierarchię układu. Aby uzyskać ViewOverlay dla dowolnego elementu View, zadzwoń pod numer getOverlay(). Nakładka zawsze ma taki sam rozmiar i położenie jak widok hosta (widok, z którego została utworzona), dzięki czemu można dodawać treści widoczne przed widokiem hosta, ale które nie mogą wykraczać poza zakres tego widoku hosta.

    Użycie właściwości ViewOverlay jest szczególnie przydatne, gdy chcesz tworzyć animacje, np. wysuwać widok poza kontener lub przesuwać elementy po ekranie bez wpływu na hierarchię widoków. Ponieważ jednak użytkowy obszar nakładki jest ograniczony do tego samego obszaru co widok hosta, jeśli chcesz animować widok, który wykracza poza swoją pozycję w układzie, musisz użyć nakładki z widoku nadrzędnego, który ma wyznaczone granice układu.

    Podczas tworzenia nakładki dla widoku widżetu, np. Button, możesz dodać do nakładki obiekty Drawable, wywołując add(Drawable). Jeśli wywołasz getOverlay() w przypadku widoku układu, takiego jak RelativeLayout, zwrócony obiekt to ViewGroupOverlay. Klasa ViewGroupOverlay jest podklasą klasy ViewOverlay, która także umożliwia dodawanie obiektów View przez wywołanie add(View).

    Uwaga: wszystkie elementy, które można rysować i widoki, które dodajesz do nakładki, mają charakter wyłącznie wizualny. Nie mogą odbierać zdarzeń skupienia ani wprowadzania danych.

    Na przykład poniższy kod animuje widok przesuwany w prawo przez umieszczenie go w nakładce widoku nadrzędnego, a następnie wykonanie w nim animacji przesunięcia:

    Kotlin

    val view: View? = findViewById(R.id.view_to_remove)
    val container: ViewGroup? = view?.parent as ViewGroup
    
    container?.apply {
        overlay.add(view)
        ObjectAnimator.ofFloat(view, "translationX", right.toFloat())
                .start()
    }
    

    Java

    View view = findViewById(R.id.view_to_remove);
    ViewGroup container = (ViewGroup) view.getParent();
    container.getOverlay().add(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
    anim.start();
    

    Układ granic optycznych

    W przypadku widoków zawierających 9 poprawek obrazu tła możesz teraz określić, że powinny być one wyrównane z sąsiadującymi widokami na podstawie „optycznych” granic obrazu tła, a nie granic obrazu tła.

    Na przykład rysunki 1 i 2 przedstawiają ten sam układ, ale w wersji na ilustracji 1 obowiązują granice klipu (działanie domyślne), a na ilustracji 2 – granice optyczne. Obrazy z dziewięcioma elementami używanymi w przypadku przycisku i ramki na zdjęcia zawierają dopełnienie wokół krawędzi, dlatego nie będą one wyrównane względem siebie ani tekstu podczas korzystania z granic klipu.

    Uwaga: na zrzucie ekranu na rysunkach 1 i 2 włączone jest ustawienie programisty „Pokaż granice układu”. Czerwone linie oznaczają granice optyczne, niebieskie linie – granice klipu, a różowe – marginesy.

    Rysunek 1. Układ z użyciem granic klipu (domyślnie).

    Rysunek 2. Układ z wykorzystaniem granic optycznych.

    Aby wyrównać widoki na podstawie ich granic optycznych, ustaw wartość atrybutu android:layoutMode na "opticalBounds" w jednym z układów nadrzędnych. Na przykład:

    <LinearLayout android:layoutMode="opticalBounds" ... >
    

    Rysunek 3. Powiększony widok dziewięciopunktowego przycisku Holo z zakresami optycznymi.

    Aby tak się stało, obrazy dziewięciu punktów zastosowane do tła widoków muszą określać granice optyczne za pomocą czerwonych linii wzdłuż dolnej i prawej strony pliku z dziewięcioma poprawkami (jak pokazano na ilustracji 3). Czerwone linie wskazują obszar, który powinien zostać odjęty od granic klipu, pozostawiając w ten sposób optyczne granice obrazu.

    Gdy włączysz progi optyczne dla elementu ViewGroup w układzie, wszystkie widoki podrzędne będą dziedziczyć tryb układu granic optycznych, chyba że zastąpisz go dla grupy, ustawiając android:layoutMode na "clipBounds". Wszystkie elementy układu również uwzględniają optyczne granice widoków danych dziecka, dostosowując własne granice na podstawie optycznych granic znajdujących się w nich widoków. Jednak elementy układu (podklasy ViewGroup) obecnie nie obsługują granic optycznych dla obrazów z dziewięcioma poprawkami zastosowanymi na własnym tle.

    Jeśli utworzysz widok niestandardowy przez podklasyfikację View, ViewGroup lub ich dowolnej podklasy, widok odziedziczy te optyczne powiązania.

    Uwaga: wszystkie widżety obsługiwane przez motyw Holo zostały zaktualizowane o granice optyczne, między innymi Button, Spinner i EditText. Jeśli Twoja aplikacja stosuje motyw Holo (Theme.Holo, Theme.Holo.Light itp.), ustaw wartość atrybutu android:layoutMode na "opticalBounds", aby od razu odnieść korzyści.

    Aby określić progi optyczne dla własnych dziewięciu punktów na zdjęciach za pomocą narzędzia Rysuj 9-patch, klikaj przyciski obramowania, przytrzymując klawisz Ctrl.

    Animacja wartości prostokątnych

    Dzięki nowej funkcji RectEvaluator możesz teraz animować pomiędzy 2 wartościami parametru Rect. Ta nowa klasa to implementacja TypeEvaluator, którą możesz przekazać do zajęć ValueAnimator.setEvaluator().

    Dołączaj okna i ustawiaj ostrość

    Wcześniej, aby nasłuchiwać, kiedy widok został dołączony lub odłączony od okna lub gdy jego zaznaczenie uległo zmianie, trzeba było zastąpić klasę View, aby zaimplementować odpowiednio onAttachedToWindow() i onDetachedFromWindow() lub onWindowFocusChanged().

    Aby odbierać zdarzenia dołączania i odłączania, możesz zamiast tego zaimplementować ViewTreeObserver.OnWindowAttachListener i ustawić go w widoku danych za pomocą addOnWindowAttachListener(). Aby otrzymywać zdarzenia skupienia, możesz wdrożyć funkcję ViewTreeObserver.OnWindowFocusChangeListener i ustawić ją w widoku danych za pomocą addOnWindowFocusChangeListener().

    Obsługa nadmiarowego skanowania sygnału telewizyjnego

    Aby mieć pewność, że aplikacja wypełnia cały ekran każdego telewizora, możesz włączyć nadmiarowość obrazu w układzie aplikacji. Tryb nadmiarowego skanowania jest określany za pomocą flagi FLAG_LAYOUT_IN_OVERSCAN, którą można włączyć za pomocą motywów platformy, takich jak Theme_DeviceDefault_NoActionBar_Overscan, lub stylu windowOverscan w motywie niestandardowym.

    Orientacja ekranu

    Atrybut screenOrientation w tagu <activity> obsługuje teraz dodatkowe wartości zgodne z preferencją użytkownika dotyczącą automatycznej rotacji:

    "userLandscape"
    Działa tak samo jak "sensorLandscape", chyba że użytkownik wyłączy autoobracanie, zablokuje się w normalnej orientacji poziomej i nie odwraca.
    "userPortrait"
    Działa tak samo jak "sensorPortrait", ale jeśli użytkownik wyłączy autoobracanie, obraz zostanie zablokowany w normalnej orientacji pionowej i nie będzie odwracany.
    "fullUser"
    Działa tak samo jak "fullSensor" i umożliwia obrót we wszystkich 4 kierunkach, chyba że użytkownik wyłączy autoobracanie, ekran zostanie zablokowany w preferowanej orientacji użytkownika.

    Oprócz tego możesz też zadeklarować, że "locked" blokuje orientację ekranu w aplikacji.

    Animacje obrotu

    Nowe pole rotationAnimation w WindowManager umożliwia wybór jednej z 3 animacji, które mają być używane, gdy system zmieni orientację ekranu. Te 3 animacje to:

    Uwaga: te animacje są dostępne tylko wtedy, gdy dla aktywności ustawisz tryb pełnoekranowy, który można włączyć przy użyciu motywów, takich jak Theme.Holo.NoActionBar.Fullscreen.

    Animację „przenikanie” można włączyć na przykład w ten sposób:

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val params: WindowManager.LayoutParams = window.attributes
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE
        window.attributes = params
        ...
    }
    

    Java

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        getWindow().setAttributes(params);
        ...
    }
    

    Dane wejściowe użytkownika

    Nowe typy czujników

    Nowy czujnik TYPE_GAME_ROTATION_VECTOR umożliwia wykrywanie obrotów urządzenia bez obaw o zakłócenia magnetyczne. W przeciwieństwie do czujnika TYPE_ROTATION_VECTOR wskazówka TYPE_GAME_ROTATION_VECTOR nie jest kierowana na północ magnetyczną.

    Nowe czujniki TYPE_GYROSCOPE_UNCALIBRATED i TYPE_MAGNETIC_FIELD_UNCALIBRATED dostarczają nieprzetworzone dane z czujnika bez uwzględniania szacowanego odchylenia. Oznacza to, że istniejące czujniki TYPE_GYROSCOPE i TYPE_MAGNETIC_FIELD dostarczają dane z czujników, które uwzględniają szacowane odchylenie pochodzące odpowiednio z dryfu żyroskopu i twardego żelaza. Nowe „nieskalibrowane” wersje tych czujników dostarczają natomiast nieprzetworzone dane z czujników i osobno przedstawiają szacowane wartości odchylenia. Czujniki te umożliwiają Ci własną, niestandardową kalibrację danych z czujników przez wzmacnianie szacowanego odchylenia za pomocą danych zewnętrznych.

    Odbiornik powiadomień

    Android 4.3 dodaje nową klasę usługi NotificationListenerService, która umożliwia aplikacji otrzymywanie informacji o nowych powiadomieniach publikowanych przez system.

    Jeśli Twoja aplikacja korzysta obecnie z interfejsów API usługi ułatwień dostępu do uzyskiwania dostępu do powiadomień systemowych, zaktualizuj ją tak, aby używała tych interfejsów API.

    dostawca kontaktów

    Zapytanie o „kontakty”

    Nowe zapytanie dotyczące dostawcy kontaktów (Contactables.CONTENT_URI) pozwala skutecznie uzyskać dane Cursor zawierające wszystkie adresy e-mail i numery telefonów należące do wszystkich kontaktów pasujących do podanego zapytania.

    Zapytanie o delta kontaktów

    Do dostawcy kontaktów dodano nowe interfejsy API, które umożliwiają sprawne wykonywanie zapytań dotyczących ostatnich zmian w danych kontaktów. Wcześniej aplikacja mogła otrzymywać powiadomienia o zmianach w danych kontaktów, ale nie wiadomo było, co dokładnie się zmieniło. Aby wykryć zmiany, konieczne było pobranie wszystkich kontaktów, a następnie ich przejrzenie.

    Aby śledzić zmiany dotyczące wstawek i aktualizacji, możesz teraz uwzględnić w wyborze parametr CONTACT_LAST_UPDATED_TIMESTAMP, aby wysyłać zapytania tylko o kontakty, które zmieniły się od czasu ostatniego zapytania o dostawcę.

    Aby śledzić usunięte kontakty, nowa tabela ContactsContract.DeletedContacts zawiera dziennik usuniętych kontaktów (ale przez ograniczony czas każdy usunięty kontakt jest przechowywany w tej tabeli). Podobnie jak w przypadku CONTACT_LAST_UPDATED_TIMESTAMP możesz użyć nowego parametru wyboru (CONTACT_DELETED_TIMESTAMP), aby sprawdzić, które kontakty zostały usunięte od czasu ostatniego zapytania o dostawcę. Tabela zawiera też stałą DAYS_KEPT_MILLISECONDS, która określa liczbę dni (w milisekundach), przez które dziennik ma być przechowywany.

    Dodatkowo dostawca kontaktów rozpowszechnia teraz działanie CONTACTS_DATABASE_CREATED, gdy użytkownik wyczyści pamięć kontaktów w menu ustawień systemu, co skutecznie odtworzy bazę danych dostawcy kontaktów. Ma na celu sygnalizowanie aplikacjom, że muszą usunąć wszystkie zapisane informacje kontaktowe i załadować je ponownie za pomocą nowego zapytania.

    Przykładowy kod korzystający z tych interfejsów API do sprawdzania zmian w kontaktach znajdziesz w przykładzie interfejsu API, który znajdziesz w pobranym pliku SDK Sample.

    Tłumaczenie

    Ulepszona obsługa tekstu dwukierunkowego

    Poprzednie wersje Androida obsługują języki i układy tekstu od prawej do lewej, ale czasem nie obsługują poprawnie tekstu w różnych kierunkach. Dlatego w Androidzie 4.3 do Androida 4.3 dodane są interfejsy API BidiFormatter, które ułatwiają prawidłowe formatowanie tekstu z treściami w odwrotnym kierunku bez zniekształcania żadnych jego elementów.

    Jeśli na przykład chcesz utworzyć zdanie ze zmienną w postaci ciągu znaków, np. „Czy chodziło Ci o 15 Bay Street, Laurel, CA?”, zwykle przekazujesz zasób zlokalizowanego ciągu znaków i zmienną do String.format():

    Kotlin

    val suggestion = String.format(resources.getString(R.string.did_you_mean), address)
    

    Java

    Resources res = getResources();
    String suggestion = String.format(res.getString(R.string.did_you_mean), address);
    

    Jeśli jednak język to hebrajski, sformatowany ciąg znaków będzie wyglądać tak:

    PLACEHOLDER PLACEHOLDER 電כויlar ל 15 Bay Street, Laurel, Kalifornia?

    To nie jest dobra odpowiedź, ponieważ cyfra „15” powinna być na lewo od „Bay Street”. Rozwiązaniem jest użycie metody BidiFormatter i jej metody unicodeWrap(). Na przykład powyższy kod stanie się taki:

    Kotlin

    val bidiFormatter = BidiFormatter.getInstance()
    val suggestion = String.format(
            resources.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address)
    )
    

    Java

    Resources res = getResources();
    BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    String suggestion = String.format(res.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address));
    

    Domyślnie unicodeWrap() używa heurystyki szacowania pierwszej wartości kierunkowej, która może powodować błędy, jeśli pierwszy sygnał kierunku tekstu nie odzwierciedla właściwego kierunku dla całej treści. Jeśli to konieczne, możesz określić inną metodę heurystyczną, przekazując jedną ze stałych TextDirectionHeuristic z parametru TextDirectionHeuristics do unicodeWrap().

    Uwaga: te nowe interfejsy API są też dostępne dla poprzednich wersji Androida za pomocą biblioteki pomocy Androida wraz z klasą BidiFormatter i powiązanymi interfejsami API.

    Usługi ułatwień dostępu

    Obsługa kluczowych zdarzeń

    AccessibilityService może teraz za pomocą metody onKeyEvent() odbierać wywołanie zwrotne dla kluczowych zdarzeń wejściowych. Dzięki temu usługa ułatwień dostępu może obsługiwać wprowadzanie danych z urządzeń wejściowych obsługujących klawisze, takich jak klawiatura, i przekładać te zdarzenia na działania specjalne, które wcześniej były możliwe tylko przy użyciu dotyku lub pada kierunkowego urządzenia.

    Zaznaczanie tekstu i kopiowanie/wklejanie

    AccessibilityNodeInfo udostępnia teraz interfejsy API, które pozwalają AccessibilityService na wybieranie, wycinanie, kopiowanie i wklejanie tekstu w węźle.

    Aby określić wybór tekstu do wycięcia lub skopiowania, usługa ułatwień dostępu może użyć nowego działania (ACTION_SET_SELECTION), przekazując wraz z nim pozycję początkową i końcową zaznaczenia za pomocą elementów ACTION_ARGUMENT_SELECTION_START_INT i ACTION_ARGUMENT_SELECTION_END_INT. Tekst możesz też zaznaczyć, zmieniając pozycję kursora za pomocą dotychczasowej czynności ACTION_NEXT_AT_MOVEMENT_GRANULARITY (wcześniej tylko w celu przesuwania kursora) i dodając argument ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN.

    Następnie możesz wyciąć lub skopiować tekst za pomocą ACTION_CUT, ACTION_COPY, a później wkleić za pomocą ACTION_PASTE.

    Uwaga: te nowe interfejsy API są też dostępne dla poprzednich wersji Androida za pomocą biblioteki pomocy Androida z klasą AccessibilityNodeInfoCompat.

    Deklarowanie ułatwień dostępu

    Począwszy od Androida 4.3, usługa ułatwień dostępu musi zadeklarować funkcje ułatwień dostępu w swoim pliku metadanych, aby można było używać określonych ułatwień dostępu. Jeśli plik metadanych nie wymaga takiej możliwości, funkcja nie będzie działać. Aby zadeklarować ułatwienia dostępu w swojej usłudze, musisz użyć atrybutów XML, które odpowiadają różnym stałym „możliwości” w klasie AccessibilityServiceInfo.

    Jeśli na przykład usługa nie żąda możliwości flagRequestFilterKeyEvents, nie otrzyma kluczowych zdarzeń.

    Testowanie i debugowanie

    Automatyczne testowanie interfejsu

    Nowa klasa UiAutomation udostępnia interfejsy API umożliwiające symulowanie działań użytkowników na potrzeby automatyzacji testów. Dzięki interfejsom API AccessibilityService na platformie interfejsy API UiAutomation umożliwiają sprawdzanie zawartości ekranu i wstrzykiwanie dowolnych zdarzeń dotyku i klawiatury.

    Aby pobrać wystąpienie typu UiAutomation, wywołaj Instrumentation.getUiAutomation(). Aby to zadziałało, musisz podać opcję -w w poleceniu instrument podczas uruchamiania InstrumentationTestCase z adb shell.

    W instancji UiAutomation możesz uruchamiać dowolne zdarzenia do przetestowania, wywołując metodę executeAndWaitForEvent(), przekazując jej żądanie Runnable, czas oczekiwania na operację i implementację interfejsu UiAutomation.AccessibilityEventFilter. W ramach implementacji UiAutomation.AccessibilityEventFilter otrzymasz wywołanie umożliwiające filtrowanie interesujących Cię zdarzeń i określenie powodzenia lub niepowodzenia danego przypadku testowego.

    Aby obserwować wszystkie zdarzenia podczas testu, utwórz implementację UiAutomation.OnAccessibilityEventListener i przekaż ją do interfejsu setOnAccessibilityEventListener(). Za każdym razem, gdy wystąpi zdarzenie, interfejs detektora otrzymuje wywołanie onAccessibilityEvent() i otrzymuje obiekt AccessibilityEvent, który opisuje zdarzenie.

    Interfejsy UiAutomation API udostępniają wiele innych operacji na bardzo niskim poziomie, aby zachęcić do opracowania narzędzi testowych UI, takich jak uiautomator. UiAutomation może też na przykład:

    • Wstrzyknij zdarzenia wejściowe
    • Zmień orientację ekranu
    • wykonać zrzut ekranu,

    Co najważniejsze w przypadku narzędzi do testowania interfejsu użytkownika interfejsy API UiAutomation działają poza granice aplikacji, w przeciwieństwie do tych w Instrumentation.

    Zdarzenia Systrace w aplikacjach

    Android 4.3 dodaje klasę Trace z 2 metodami statycznymi: beginSection() i endSection(), które umożliwiają definiowanie bloków kodu, które mają być dołączane do raportu systrace. Tworząc w aplikacji sekcje kodu możliwego do śledzenia, logi systrace dostarczają znacznie bardziej szczegółowej analizy miejsc, w których następuje spowolnienie w aplikacji.

    Więcej informacji o korzystaniu z narzędzia Systrace znajdziesz w artykule Analizowanie wyświetlania i skuteczności w Systrace.

    Zabezpieczenia

    Magazyn kluczy Android na potrzeby kluczy prywatnych aplikacji

    Android oferuje teraz w usłudze KeyStore niestandardowy dostawca zabezpieczeń Java o nazwie Android Key Store. Umożliwia on generowanie i zapisywanie kluczy prywatnych, które mogą być widoczne i używane tylko przez Twoją aplikację. Aby wczytać magazyn kluczy Android, przekaż polecenie "AndroidKeyStore" na adres KeyStore.getInstance().

    Aby zarządzać prywatnymi danymi logowania do aplikacji w magazynie kluczy Android, wygeneruj nowy klucz za pomocą funkcji KeyPairGenerator i KeyPairGeneratorSpec. Najpierw pobierz instancję KeyPairGenerator, wywołując getInstance(). Następnie wywołaj polecenie initialize(), przekazując mu wystąpienie KeyPairGeneratorSpec, które możesz uzyskać, używając polecenia KeyPairGeneratorSpec.Builder. Wreszcie możesz odebrać KeyPair, dzwoniąc pod numer generateKeyPair().

    Magazyn danych logowania do sprzętu

    Android obsługuje teraz także sprzętowe przechowywanie danych logowania w KeyChain, co zwiększa bezpieczeństwo, ponieważ uniemożliwia wyodrębnianie kluczy. Oznacza to, że jeśli klucze znajdują się w sprzętowym magazynie kluczy (Secure Element, TPM lub TrustZone), można ich używać do operacji kryptograficznych, ale nie można eksportować materiału klucza prywatnego. Nawet jądro systemu operacyjnego nie ma dostępu do tego materiału klucza. Chociaż nie wszystkie urządzenia z Androidem obsługują pamięć masową, możesz w czasie działania sprawdzić, czy pamięć sterowana sprzętowo jest dostępna, wywołując stronę KeyChain.IsBoundKeyAlgorithm().

    Deklaracje w pliku manifestu

    Wymagane funkcje, które można zadeklarować

    Poniższe wartości są teraz obsługiwane w elemencie <uses-feature>, dzięki czemu możesz mieć pewność, że aplikacja będzie instalowana tylko na urządzeniach, które obsługują funkcje, których potrzebuje.

    FEATURE_APP_WIDGETS
    Deklaruje, że aplikacja zawiera widżet aplikacji i powinna być zainstalowana tylko na urządzeniach z ekranem głównym lub w podobnym miejscu, w którym użytkownicy mogą umieszczać widżety aplikacji. Przykład:
    <uses-feature android:name="android.software.app_widgets" android:required="true" />
    
    FEATURE_HOME_SCREEN
    Deklaruje, że aplikacja działa jako zamiennik ekranu głównego i powinna być instalowana tylko na urządzeniach, które obsługują aplikacje na ekranie głównym innych firm. Przykład:
    <uses-feature android:name="android.software.home_screen" android:required="true" />
    
    FEATURE_INPUT_METHODS
    Deklaruje, że aplikacja udostępnia niestandardową metodę wprowadzania (klawiaturę wbudowaną w InputMethodService) i powinna być zainstalowana wyłącznie na urządzeniach, które obsługują metody wprowadzania innych firm. Przykład:
    <uses-feature android:name="android.software.input_methods" android:required="true" />
    
    FEATURE_BLUETOOTH_LE
    Deklaruje, że aplikacja korzysta z interfejsów API Bluetooth Low Energy i powinna być instalowana tylko na urządzeniach, które mogą komunikować się z innymi urządzeniami przez Bluetooth Low Energy. Przykład:
    <uses-feature android:name="android.software.bluetooth_le" android:required="true" />
    

    Uprawnienia użytkownika

    Poniższe wartości są teraz obsługiwane w <uses-permission> w celu zadeklarowania uprawnień wymaganych przez aplikację do uzyskania dostępu do określonych interfejsów API.

    BIND_NOTIFICATION_LISTENER_SERVICE
    Wymagane do korzystania z nowych interfejsów API NotificationListenerService.
    SEND_RESPOND_VIA_MESSAGE
    Wymagane do uzyskania intencji ACTION_RESPOND_VIA_MESSAGE.

    Szczegółowy widok wszystkich zmian w interfejsach API w Androidzie 4.3 znajdziesz w raporcie Różnice w interfejsie API.