Poziom interfejsu API: 18
Android 4.3 (JELLY_BEAN_MR2
)
to aktualizacja wersji Jelly Bean, która zawiera nowe funkcje dla użytkowników i programistów. Ten dokument zawiera wprowadzenie do najważniejszych
nowych interfejsów API.
Jako deweloper aplikacji jak najszybciej pobierz obraz systemu Android 4.3 i platformę SDK z Menedżera pakietu SDK. Jeśli nie masz urządzenia z Androidem 4.3, na którym możesz przetestować aplikację, użyj obrazu systemu Android 4.3, aby przetestować aplikację na emulatorze Androida. Następnie utwórz aplikacje na platformę Android 4.3, aby zacząć korzystać z najnowszych interfejsów API.
Zaktualizuj docelowy poziom interfejsu API
Aby lepiej zoptymalizować aplikację na urządzeniach z Androidem 4.3:
ustaw targetSdkVersion
na
"18"
, zainstaluj ją w obrazie systemu Android 4.3
przetestować ją, a następnie opublikować aktualizację z tą zmianą.
Z interfejsów API w Androidzie 4.3 możesz korzystać, jednocześnie obsługując starsze wersje, dodając
w kodzie, które sprawdzają poziom interfejsu API systemu przed jego wykonaniem
minSdkVersion
nie obsługuje interfejsów API.
Więcej informacji na temat zachowania zgodności wstecznej można znaleźć w artykule Obsługa różnych
Wersje platformy.
W Bibliotece pomocy Androida są również dostępne różne interfejsy API, które umożliwiają implementację 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 aplikacja na Androida została już przez Ciebie opublikowana, pamiętaj, że zmiany w Androidzie 4.3 mogą na nią wpłynąć.
Jeśli aplikacja używa intencji niejawnych...
Aplikacja może działać nieprawidłowo w środowisku profilu z ograniczonym dostępem.
Użytkownicy korzystający z profilu z ograniczonym dostępem mogą nie mieć dostępu do wszystkich standardowych aplikacji na Androida. Na przykład w profilu z ograniczonym dostępem może być wyłączona przeglądarka internetowa i aplikacja do obsługi aparatu. Twoja aplikacja nie powinna zakładać, że są dostępne inne aplikacje, ponieważ jeśli wywołasz funkcję startActivity()
bez weryfikowania, czy aplikacja jest dostępna do obsługi funkcji Intent
, może się ona zawiesić w profilu z ograniczonym dostępem.
Podczas korzystania z domyślnego zamiaru zawsze należy sprawdzić, czy aplikacja jest dostępna do obsługi zamiaru, wywołując 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 korzysta z kont...
Aplikacja może działać nieprawidłowo w środowisku profilu z ograniczonym dostępem.
Użytkownicy w ograniczonym środowisku profili nie mają domyślnie dostępu do kont użytkowników.
Jeśli Twoja aplikacja zależy od Account
, może się zawieszać lub zachowywać nieoczekiwanie, gdy jest używana na profilu z ograniczonymi uprawnieniami.
Jeśli chcesz całkowicie uniemożliwić profilom z ograniczonym dostępem korzystanie z Twojej aplikacji
aplikacja korzysta z poufnych informacji o koncie, określ atrybut android:requiredAccountType
w pliku manifestu <application>
.
Jeśli chcesz zezwolić profilom z ograniczeniami na dalsze korzystanie z aplikacji, mimo że nie mogą tego zrobić własnych kont, możesz wyłączyć funkcje aplikacji, które wymagają konta lub zezwól profilom z ograniczonym dostępem na dostęp do kont utworzonych przez użytkownika głównego. Więcej informacji znajdziesz w sekcji Obsługa kont na profilu ograniczonym.
Jeśli Twoja aplikacja używa VideoView…
Film może być wyświetlany w mniejszym rozmiarze w Androidzie 4.3.
W poprzednich wersjach Androida widżet VideoView
był nieprawidłowo wyświetlany.
obliczył, że wartość "wrap_content"
dla layout_height
i layout_width
jest taka sama jak "match_parent"
. Jeśli więc użyjesz opcji "wrap_content"
na wysokość lub szerokość, być może uzyskasz wcześniej wybrany układ filmu,
W Androidzie 4.3 i nowszych film może być znacznie rzadziej wyświetlany. Aby rozwiązać ten problem, zastąp "wrap_content"
wartością "match_parent"
i sprawdź, czy film wyświetla się zgodnie z oczekiwaniami w Androidzie 4.3 i starszych wersjach.
Profile z ograniczeniami
Na tabletach z Androidem użytkownicy mogą teraz tworzyć profile z ograniczonymi uprawnieniami na podstawie konta głównego. Gdy użytkownicy tworzą profil z ograniczonym dostępem, mogą włączyć ograniczenia, takie jak aplikacje dostępne na tym profilu. Nowy zestaw interfejsów API w Androidzie 4.3 umożliwia również ustawień ograniczeń dla tworzonych przez siebie aplikacji. Za pomocą nowych interfejsów API możesz na przykład zezwolić użytkownikom na kontrolowanie, jakiego typu treści są dostępne w aplikacji, gdy działa ona w środowisku profilu z ograniczonymi uprawnieniami.
Interfejs użytkownika do zarządzania wprowadzonymi przez Ciebie ograniczeniami jest zarządzany przez aplikację Ustawienia systemu. Aby wyświetlić użytkownikowi ustawienia ograniczeń aplikacji:
musisz zadeklarować ograniczenia stosowane przez Twoją aplikację, tworząc obiekt BroadcastReceiver
, który odbiera intencję ACTION_GET_RESTRICTION_ENTRIES
. System wywołuje ten zamiar, aby zapytać wszystkie aplikacje o dostępne ograniczenia, a następnie tworzy interfejs użytkownika, który pozwala głównemu użytkownikowi zarządzać ograniczeniami dla każdego profilu z ograniczeniami.
W metodzie onReceive()
w Twojej BroadcastReceiver
musisz utworzyć RestrictionEntry
dla każdej restrykcji oferowanej przez aplikację. Każdy element RestrictionEntry
definiuje tytuł i opis ograniczenia oraz jeden z tych typów danych:
TYPE_BOOLEAN
dla ograniczenia, które ma wartość prawda lub fałsz.TYPE_CHOICE
w przypadku ograniczenia, które ma wiele opcji wzajemnie się wykluczających (opcje z opcji z jednego wyboru).TYPE_MULTI_SELECT
w przypadku ograniczenia, które ma więcej niż 1 opcję (opcje w polu wyboru).
Następnie umieszczasz wszystkie obiekty RestrictionEntry
w obiekcie ArrayList
i przekazujesz go do wyniku odbiornika transmisji jako wartość dodatkowego obiektu EXTRA_RESTRICTIONS_LIST
.
System tworzy interfejs pod kątem ograniczeń aplikacji w aplikacji Ustawienia i zapisuje każdy z nich
używając unikalnego klucza podanego przez Ciebie dla każdej jednostki RestrictionEntry
obiektu. Gdy użytkownik otworzy aplikację, możesz zapytać o aktualne ograniczenia przez
Dzwonię pod getApplicationRestrictions()
.
Zwraca to obiekt Bundle
zawierający pary klucz-wartość dla każdej z ograniczeń zdefiniowanych za pomocą obiektów RestrictionEntry
.
Jeśli chcesz wprowadzić bardziej szczegółowe ograniczenia, których nie można obsługiwać za pomocą wartości logicznych, jednowyborowych i wielowyborowych, możesz utworzyć aktywność, w której użytkownik może określić ograniczenia i otworzyć tę aktywność z ustawień ograniczeń. W odbiorniku transmisji uwzględnij dodatkowy parametr EXTRA_RESTRICTIONS_INTENT
w wyniku Bundle
. Ten dodatek musi zawierać parametr Intent
wskazujący klasę Activity
, która ma zostać uruchomiona (użyj metody putParcelable()
, aby przekazać EXTRA_RESTRICTIONS_INTENT
z zamierzeniem).
Gdy główny użytkownik wejdzie do Twojej aktywności, aby ustawić niestandardowe ograniczenia, Twoja aktywność musi zwrócić wynik zawierający wartości ograniczeń w dodatku za pomocą klucza EXTRA_RESTRICTIONS_LIST
lub EXTRA_RESTRICTIONS_BUNDLE
, w zależności od tego, czy określisz 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 profilu z ograniczonym dostępem,
konta nie są domyślnie dostępne z interfejsów API AccountManager
.
Jeśli spróbujesz dodać konto z AccountManager
w profilu z ograniczonymi uprawnieniami, nie uda Ci się tego zrobić. Ze względu na te ograniczenia masz:
3 opcje:
Aby uzyskać dostęp do konta z profilu z ograniczonym dostępem, musisz dodać atrybut android:restrictedAccountType
do tagu <application>:
<application ... android:restrictedAccountType="com.example.account.type" >
Uwaga: włączenie tego atrybutu spowoduje, że Twoje dane dostępu aplikacji do kont głównego użytkownika z profili ograniczonych. Zezwalaj na to tylko wtedy, gdy wyświetlane przez aplikację informacje nie zawierają informacji umożliwiających identyfikację, które są uważane za poufne. Ustawienia systemowe informują głównego użytkownika, że aplikacja przyznaje ograniczone profile do kont, więc użytkownik powinien mieć jasność, że dostęp do konta jest ważny dla działania aplikacji. W miarę możliwości zapewnić głównemu użytkownikowi dostęp do odpowiednich ograniczeń, aby określić poziom dostępu do konta; jest dozwolona w Twojej aplikacji.
Jeśli chcesz używać kont, ale nie są one wymagane do korzystania z podstawowych funkcji aplikacji, możesz sprawdzić dostępność kont i wyłączyć funkcje, gdy nie są dostępne.
Najpierw sprawdź, czy masz już dostępne konto. Jeśli nie, sprawdź, czy można utworzyć nowe konto, wykonując wywołanie getUserRestrictions()
i sprawdzając dodatkowy parametr DISALLOW_MODIFY_ACCOUNTS
w wyniku. Jeśli jest to true
,
musisz wyłączyć te funkcje, które wymagają dostępu do konta.
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 scenariuszu nie deklaruj żadnych nowych atrybutów w pliku manifestu.
Jeśli zależy Ci na tym, aby aplikacja nie była dostępna dla profili z ograniczonymi uprawnieniami, ponieważ zależy ona od poufnych danych osobowych na koncie (a profily z ograniczonymi uprawnieniami obecnie nie mogą dodawać nowych kont), dodaj atrybut android:requiredAccountType
do elementu <application>:
<application ... android:requiredAccountType="com.example.account.type" >
Na przykład aplikacja Gmail używa tego atrybutu do wyłączenia się dla profili ograniczonych, bo osobisty adres e-mail właściciela nie powinien być dostępny w przypadku profili z ograniczonym dostępem.
Komunikacja bezprzewodowa i łączność
Bluetooth Low Energy (Smart ready)
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 pulsoksymetry czy krokomierze.
Bluetooth LE to funkcja sprzętowa, która nie jest dostępna na wszystkich urządzeniach z Androidem, dlatego 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ż interfejsy API klasycznego Bluetootha na Androida, pamiętaj, że korzystanie z interfejsów API Bluetooth LE różni się nieco od tego. Najważniejsze jest to, że istnieje teraz klasa BluetoothManager
, której należy użyć w przypadku niektórych operacji wysokiego poziomu.
takie jak zdobycie BluetoothAdapter
, uzyskanie listy połączonych
urządzeń i sprawdzanie ich stanu. Oto w jaki sposób możesz teraz pobrać
BluetoothAdapter
:
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 funkcję startLeScan()
w obiekcie BluetoothAdapter
, przekazując mu implementację interfejsu BluetoothAdapter.LeScanCallback
. Gdy Bluetooth
adapter wykryje urządzenie peryferyjne Bluetooth LE, Twoja implementacja BluetoothAdapter.LeScanCallback
otrzymuje wywołanie do
Metoda onLeScan()
. Ta metoda zwraca obiekt BluetoothDevice
reprezentujący wykryte urządzenie, wartość RSSI urządzenia oraz tablicę bajtów zawierającą rekord reklamy urządzenia.
Jeśli chcesz skanować w poszukiwaniu tylko określonych typów urządzeń peryferyjnych, możesz zamiast tego wywołać funkcję startLeScan()
i dodać tablicę obiektów UUID
określających usługi GATT obsługiwane przez Twoją aplikację.
Uwaga: za pomocą starszych interfejsów API możesz skanować tylko urządzenia Bluetooth LE lubskanować urządzenia Bluetooth Classic. Nie można skanować jednocześnie urządzeń Bluetooth LE i klasycznych.
Aby połączyć się z urządzeniem peryferyjnym Bluetooth LE, wywołaj metodę connectGatt()
obiektu BluetoothDevice
, przekazując mu implementację interfejsu BluetoothGattCallback
. Twoja implementacja BluetoothGattCallback
otrzymuje wywołania zwrotne dotyczące stanu połączeń z urządzeniem i innych zdarzeń. Jest w okresie: onConnectionStateChange()
wywołanie zwrotne, które można rozpocząć komunikację z urządzeniem, jeśli metoda przekazuje STATE_CONNECTED
jako nowy stan.
Dostęp do funkcji Bluetooth na urządzeniu wymaga też, aby aplikacja poprosiła o pewne uprawnienia użytkownika Bluetooth. Więcej informacji znajdziesz w przewodniku po interfejsie Bluetooth Low Energy API.
Tryb Wi-Fi tylko do skanowania
Android może użyć sieci Wi-Fi, aby określić lokalizację użytkownika, przez skanowanie pobliskich punktów dostępu. Użytkownicy często wyłączają jednak Wi-Fi, aby oszczędzać baterię, co powoduje, że dane o lokalizacji są mniej dokładne. Android obejmuje teraz tryb „tylko skanowanie”, który umożliwia Wi-Fi urządzenia skanowanie punktów dostępu, aby pomóc w ustaleniu lokalizacji bez łączenia się z punktem dostępu, co znacznie zmniejsza zużycie baterii.
Jeśli chcesz poznać lokalizację użytkownika, ale Wi-Fi jest obecnie wyłączone, możesz poprosić użytkownika o włączenie trybu skanowania Wi-Fi, wywołując funkcję startActivity()
z działaniem ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
.
Konfiguracja Wi-Fi
Nowe interfejsy API WifiEnterpriseConfig
umożliwiają usługom przeznaczonym dla firm automatyzację konfiguracji Wi-Fi na urządzeniach zarządzanych.
Szybka odpowiedź na połączenia przychodzące
Od wersji Androida 4.0 funkcja „Szybka odpowiedź” umożliwia użytkownikom odpowiadanie na przychodzące połączenia natychmiastową wiadomością tekstową bez konieczności odbierania połączenia ani odblokowywania urządzenia.
Do tej pory te szybkie wiadomości były zawsze obsługiwane przez domyślną aplikację do obsługi SMS-ów. Teraz każda aplikacja może zadeklarować obsługę tych wiadomości, tworząc Service
z filtrem intencji ACTION_RESPOND_VIA_MESSAGE
.
Gdy użytkownik odpowie na przychodzące połączenie, aplikacja Telefon wysyła intent ACTION_RESPOND_VIA_MESSAGE
z URI opisującym odbiorcę (rozmówcę) oraz dodatkowy parametr EXTRA_TEXT
z wiadomością, którą użytkownik chce wysłać. Gdy usługa otrzymuje intencję, powinna dostarczyć
komunikat i natychmiast się zatrzymuje (aplikacja nie powinna wykazywać aktywności).
Aby otrzymywać te intencje, musisz zadeklarować uprawnienie SEND_RESPOND_VIA_MESSAGE
.
Multimedia
Ulepszenia MediaExtractor i MediaCodec
Android ułatwia teraz tworzenie własnych odtwarzaczy strumieniowego przesyłania danych w standardzie DASH (dynamiczne adaptacyjne strumieniowe przesyłanie danych przez HTTP) zgodnie ze standardem ISO/IEC 23009-1 za pomocą istniejących interfejsów API w MediaCodec
i MediaExtractor
. Platforma, na której są oparte te interfejsy API, została zaktualizowana,
analizowanie fragmentarycznych plików MP4, ale Twoja aplikacja nadal odpowiada za analizę metadanych MPD
i przekazywać poszczególne strumienie do usługi MediaExtractor
.
Jeśli chcesz używać DASH z zaszyfrowanymi treściami, zwróć uwagę, że metoda getSampleCryptoInfo()
zwraca metadane MediaCodec.CryptoInfo
opisujące strukturę każdego zaszyfrowanego multimediów
przykład. Do metody getPsshInfo()
dodano też metodę MediaExtractor
, dzięki której możesz uzyskać dostęp do metadanych PSSH dla multimediów DASH.
Ta metoda zwraca mapę obiektów UUID
na bajty, w której UUID
określa schemat szyfrowania, a bajty to dane specyficzne dla tego schematu.
DRM multimediów
Nowa klasa MediaDrm
zapewnia modułowe rozwiązanie do zarządzania prawami cyfrowymi (DRM) w przypadku treści multimedialnych, oddzielając kwestie DRM od odtwarzania multimediów. Na przykład rozdzielenie interfejsu API umożliwia odtwarzanie treści zaszyfrowanych za pomocą Widevine bez konieczności korzystania z formatu multimediów Widevine. Rozwiązanie DRM obsługuje też standard DASH Common Encryption,
mogą stosować różne schematy DRM w przypadku treści przesyłanych strumieniowo.
Możesz użyć MediaDrm
, aby uzyskać nieprzezroczyste wiadomości z żądaniem klucza i przetworzyć wiadomości z odpowiedzią na żądanie klucza z serwera na potrzeby pozyskiwania i zarządzania licencjami. Twoja aplikacja jest odpowiedzialna za obsługę komunikacji sieciowej z serwerami. Klasa MediaDrm
zapewnia tylko możliwość generowania i przetwarzania wiadomości.
Interfejsy MediaDrm
API są przeznaczone do używania w połączeniu z interfejsami MediaCodec
API wprowadzonymi w Androidzie 4.1 (poziom interfejsu API 16), w tym MediaCodec
do kodowania i dekodowania treści, MediaCrypto
do obsługi zaszyfrowanych treści oraz MediaExtractor
do wyodrębniania i demultipleksowania treści.
Najpierw musisz utworzyć MediaExtractor
i
MediaCodec
obiektów. Otrzymasz wtedy dostęp do schematu DRM
UUID
, zwykle z metadanych zawartych w treści, i używaj ich do tworzenia
wystąpienia obiektu MediaDrm
za pomocą jego konstruktora.
Kodowanie wideo z urządzenia Surface
Android 4.1 (poziom interfejsu API 16) dodał klasę MediaCodec
dla niskiego poziomu
kodowania i dekodowania treści multimedialnych. Do kodowania filmu Android 4.1 wymaga podania przez Ciebie
multimediów z tablicy ByteBuffer
, ale Android 4.3 umożliwia teraz korzystanie z Surface
jako wejścia kodera. Umożliwia to na przykład kodowanie danych wejściowych z istniejącego pliku wideo lub za pomocą klatek wygenerowanych z OpenGL ES.
Aby użyć Surface
jako wejścia do kodera, najpierw wywołaj configure()
dla MediaCodec
.
Następnie zadzwoń pod numer createInputSurface()
, aby uzyskać Surface
, na którym możesz przesyłać strumieniowo swoje multimedia.
Możesz na przykład użyć danego obiektu Surface
jako okna dla kontekstu OpenGL, przekazując go do funkcji eglCreateWindowSurface()
. Następnie podczas renderowania powierzchni wywołaj funkcję eglSwapBuffers()
, aby przekazać ramkę do funkcji MediaCodec
.
Aby rozpocząć kodowanie, wywołaj start()
na urządzeniu MediaCodec
. Gdy skończysz, zadzwoń pod numer signalEndOfInputStream()
aby zakończyć kodowanie i wywołać release()
na
Surface
Muxowanie mediów
Nowa klasa MediaMuxer
umożliwia multipleksowanie między jednym strumieniem audio i jednym strumieniem wideo. Te interfejsy API stanowią odpowiednik MediaExtractor
dodano w Androidzie 4.2 klasę do demultipleksowania (demultipleksowania) multimediów.
Obsługiwane formaty wyjściowe są zdefiniowane w sekcji MediaMuxer.OutputFormat
. Obecnie
Jedynym obsługiwanym formatem wyjściowym jest MP4, a MediaMuxer
obsługuje obecnie
tylko jeden strumień audio lub wideo w danym momencie.
Aplikacja MediaMuxer
jest przeznaczona głównie do działania z usługą MediaCodec
aby przetworzyć wideo w MediaCodec
, a następnie zapisać plik
dane wyjściowe do pliku MP4 za pomocą MediaMuxer
. Możesz też używać MediaMuxer
w połączeniu z MediaExtractor
do edycji multimediów bez konieczności 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 urządzeń zdalnego sterowania, takich jak elementy sterujące dostępne na ekranie blokady. Android 4.3 umożliwia teraz takim kontrolerom wyświetlanie odtwarzania
oraz przyciski i elementy sterujące do przewijania odtwarzania. Jeśli na urządzeniu jest włączony pilot
za pomocą interfejsów API RemoteControlClient
, możesz zezwolić na odtwarzanie
wymaga optymalizacji przez wdrożenie 2 nowych interfejsów.
Najpierw musisz włączyć flagę FLAG_KEY_MEDIA_POSITION_UPDATE
, przekazując ją do
setTransportControlsFlags()
Następnie zaimplementuj te 2 nowe interfejsy:
RemoteControlClient.OnGetPlaybackPositionListener
- Obejmuje to wywołanie zwrotne
onGetPlaybackPosition()
, które dotyczy bieżącej pozycji Twoich multimediów, gdy pilot musi aktualizować postęp w interfejsie użytkownika. 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 zaktualizowaniu odtwarzania z nową pozycją wywołaj
setPlaybackState()
, aby wskazać nowy stan, pozycję i szybkość odtwarzania.
Po zdefiniowaniu tych interfejsów możesz skonfigurować je dla swojego urządzenia RemoteControlClient
, wywołując metodę setOnGetPlaybackPositionListener()
i
setPlaybackPositionUpdateListener()
.
Grafika
Obsługa OpenGL ES 3.0
W Androidzie 4.3 dodaliśmy interfejsy Java i wbudowaną obsługę OpenGL ES 3.0. Główne nowe funkcje OpenGL ES 3.0:
- Zaawansowane efekty wizualne
- Wysokiej jakości kompresja tekstur ETC2/EAC jako standardowa funkcja
- Nowa wersja języka cieniowania GLSL ES z obsługą liczb całkowitych i 32-bitowej liczby zmiennoprzecinkowej.
- Zaawansowane renderowanie tekstur
- Szersza standaryzacja rozmiaru tekstury i formatów bufora renderowania
Interfejs Java dla OpenGL ES 3.0 na Androidzie zawiera dodatek GLES30
.
Jeśli używasz OpenGL ES 3.0, pamiętaj, aby zadeklarować go w pliku manifestu za pomocą elementu <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 funkcję setEGLContextClientVersion()
,
przesyłając wersję 3
.
Więcej informacji o używaniu OpenGL ES, w tym o sprawdzaniu obsługiwanej wersji OpenGL ES na urządzeniu w czasie wykonywania, znajdziesz w przewodniku po interfejsie API OpenGL ES.
Mipmapowanie dla rysunków
Użycie mapy MIP jako źródła bitmapy lub obiektu rysowanego to prosty sposób na uzyskanie obrazu wysokiej jakości i różnych skal obrazu, co może być szczególnie przydatne, jeśli oczekujesz, że obraz będzie skalowany podczas animacji.
Android 4.2 (poziom interfejsu API 17) obsługuje mipmapy w klasie Bitmap
. Android zamienia obrazy mip w Twoim pliku Bitmap
, gdy podasz źródło mipmapy i włączysz opcję setHasMipMap()
. Teraz w Androidzie 4.3 możesz włączyć również mipmapy dla obiektu BitmapDrawable
, przesyłając zasób mipmap
ustawiając atrybut android:mipMap
w pliku zasobów bitmapy lub wywołując hasMipMap()
.
Interfejs
Wyświetlanie nakładek
Nowa klasa ViewOverlay
zapewnia przezroczystą warstwę
View
, do którego można dodawać treści wizualne, który nie ma wpływu
w hierarchii układu. Możesz otrzymać ViewOverlay
na dowolną kwotę View
, dzwoniąc pod numer getOverlay()
. Nakładka ma zawsze taki sam rozmiar i pozycję jak widok hosta (widok, z którego została utworzona). Pozwala to dodawać treści, które pojawiają się przed widokiem hosta, ale nie mogą wykraczać poza jego granice.
Użycie ViewOverlay
jest szczególnie przydatne, gdy chcesz utworzyć animacje, np. przesuwanie widoku poza jego kontener lub przemieszczanie elementów po ekranie bez wpływu na hierarchię widoku. Ponieważ jednak obszarem użytkowym nakładki jest
ograniczony do tego samego obszaru co widok hosta, jeśli chcesz animować widok na zewnątrz
jego położenie w układzie, należy użyć nakładki z widoku nadrzędnego, która zawiera wymagane
granic układu.
Utworzenie nakładki dla widoku widżetu, takiego jak Button
,
może dodać Drawable
obiektów do nakładki, wywołując
add(Drawable)
Jeśli wywołasz getOverlay()
w celu wyświetlenia widoku układu, np. RelativeLayout
, zwracanym obiektem jest ViewGroupOverlay
. Klasa ViewGroupOverlay
jest podklasą klasy ViewOverlay
, która umożliwia też dodawanie obiektów View
przez wywołanie metody add(View)
.
Uwaga: wszystkie elementy rysowalne i widoki, które dodajesz do nakładki, są tylko wizualne. Nie mogą odbierać zdarzeń skupienia ani danych wejściowych.
Na przykład ten kod animuje przesuwanie widoku w prawo, umieszczając go w nakładce widoku nadrzędnego, a następnie wykonując animację 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 widokach zawierających 9 poprawek obrazów tła możesz określić, być wyrównane z sąsiadującymi widokami na podstawie „optycznego” granic obrazu tła, a nie niż „klip” od granic widoku.
Na przykład rysunki 1 i 2 przedstawiają ten sam układ, ale wersja na rysunku 1 używa ograniczeń przycinania (zachowanie domyślne), a wersja na rysunku 2 – ograniczeń optycznych. Obrazy z 9 kawałków użyte na przycisku i w ramce zdjęcia zawierają wypełnienie wokół krawędzi, więc nie są wyrównane względem siebie ani tekstu, gdy używasz ograniczeń klipu.
Uwaga: na zrzucie ekranu na ilustracjach 1 i 2 widoczne jest pole „Pokaż granice układu" Włączono ustawienie programisty. Przy każdym widoku czerwone linie wskazują, granice, niebieskie wskazują granice przycięcia, a różowy – marginesy.

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

Rysunek 2. Układ z użyciem granic optycznych.
Aby wyrównać widoki na podstawie ich granic optycznych, w jednym z layoutów nadrzędnych ustaw atrybut android:layoutMode
na "opticalBounds"
. Na przykład:
<LinearLayout android:layoutMode="opticalBounds" ... >

Rysunek 3. Powiększony widok na 9 części przycisku Holo granic optycznych.
Aby wszystko działało, obrazy złożone z dziewięciu poprawek zastosowane do tła widoków muszą określać wyznaczamy granice optyczne za pomocą czerwonych linii wzdłuż dolnej i prawej strony pliku z 9 poprawkami ( widoczne na rysunku 3). Linie czerwone wskazują obszary, które należy odjąć od granice przycięcia, pozostawiając optyczne granice obrazu.
Gdy włączysz granice optyczne dla ViewGroup
w swoim układzie, wszystkie widoki potomne odziedziczą tryb układu granic optycznych, chyba że zastąpisz go dla grupy, ustawiając wartość android:layoutMode
na "clipBounds"
. Wszystkie elementy układu uwzględniają też granice optyczne widoków podrzędnych, dostosowując własne granice na podstawie granic optycznych widoków w nich zawartych. Jednak elementy układu (podklasy klasy ViewGroup
)
obecnie nie obsługuje granic optycznych w przypadku obrazów z dziewięcioma poprawkami zastosowanymi do własnego tła.
Jeśli utworzysz widok niestandardowy, tworząc podklasę View
, ViewGroup
lub dowolnej podklasy, widok odziedziczy te właściwości związane z ograniczeniami optycznymi.
Uwaga: wszystkie widżety obsługiwane przez motyw Holo zostały zaktualizowane o ograniczenia optyczne, w tym Button
, Spinner
,
EditText
i inne. Dzięki temu od razu masz czas, ustawiając
Atrybut android:layoutMode
do "opticalBounds"
, jeśli aplikacja stosuje motyw holograficzny.
(Theme.Holo
, Theme.Holo.Light
itp.).
Aby określić granice optyczne dla własnych obrazów 9-punktowych za pomocą narzędzia Draw 9-patch, przytrzymaj Control, gdy klikając piksele obramowania.
Animacja wartości prostokątów
W nowym formacie RectEvaluator
możesz teraz animować 2 wartości elementu Rect
. Ta nowa klasa to implementacja TypeEvaluator
, którą możesz przekazać do ValueAnimator.setEvaluator()
.
Detektor podłączania i zaznaczania okna
Jeśli wcześniej chciałeś/chciałaś sprawdzać, czy widok został dołączony/odłączony od okna lub czy zmienił się jego punkt skupienia, musiałeś/musiałaś zastąpić klasę View
, aby zaimplementować odpowiednio onAttachedToWindow()
i onDetachedFromWindow()
lub onWindowFocusChanged()
.
Aby teraz otrzymywać zdarzenia attach i detach, możesz zamiast tego zaimplementować ViewTreeObserver.OnWindowAttachListener
i ustawić je w widoku za pomocą addOnWindowAttachListener()
.
Aby otrzymywać zdarzenia skupienia, możesz zaimplementować ViewTreeObserver.OnWindowFocusChangeListener
i ustawić je dla widoku za pomocą
addOnWindowFocusChangeListener()
Obsługa overscanu telewizora
Aby mieć pewność, że aplikacja wypełni cały ekran każdego telewizora, możesz włączyć nadmiarowe skanowanie
układ aplikacji. Tryb nadmiarowego skanowania zależy od flagi FLAG_LAYOUT_IN_OVERSCAN
, którą możesz włączyć, używając motywów platformy takich jak
Theme_DeviceDefault_NoActionBar_Overscan
lub włączając
Styl windowOverscan
w motywie niestandardowym.
Orientacja ekranu
Atrybut screenOrientation
tagu <activity>
obsługuje teraz dodatkowe wartości, aby uwzględnić preferencje użytkownika dotyczące automatycznego obracania:
"userLandscape"
- Działanie takie samo jak w przypadku
"sensorLandscape"
, z tą różnicą, że jeśli użytkownik wyłączy automatyczne obracanie, obraz zostanie zablokowany w normalnej orientacji poziomej i nie będzie się obracać. "userPortrait"
- Działanie takie samo jak w przypadku
"sensorPortrait"
, z tą różnicą, że jeśli użytkownik wyłączy automatyczne obracanie, obraz zostanie zablokowany w normalnej orientacji pionowej i nie będzie się obracać. "fullUser"
- Działanie takie samo jak w przypadku
"fullSensor"
. Umożliwia obracanie w 4 kierunkach, z tym że jeśli użytkownik wyłączy automatyczne obracanie, obraz zostanie zablokowany w preferowanym położeniu.
Dodatkowo możesz teraz zadeklarować "locked"
, aby zablokować orientację aplikacji
w bieżącej orientacji ekranu.
Animacje obrotu
Nowe pole rotationAnimation
w elementach WindowManager
umożliwia wybranie jednej z 3 animacji, której chcesz użyć, gdy system zmieni orientację ekranu. Są to:
Uwaga: te animacje są dostępne tylko wtedy, gdy ustawisz aktywność na „pełnoekranowy”. w tym trybie, który możesz włączać za pomocą motywów takich jak Theme.Holo.NoActionBar.Fullscreen
.
Oto, jak włączyć animację „przejście”:
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
czujnik TYPE_GAME_ROTATION_VECTOR
nie jest oparty na kierunku północnym magnetycznym.
Nowe czujniki TYPE_GYROSCOPE_UNCALIBRATED
i TYPE_MAGNETIC_FIELD_UNCALIBRATED
dostarczają nieprzetworzone dane z czujników bez
do szacowania tendencyjności. Oznacza to, że istniejące czujniki TYPE_GYROSCOPE
i TYPE_MAGNETIC_FIELD
dostarczają dane, które uwzględniają szacowane odchylenie spowodowane dryfowaniem żyroskopu i twardym rdzeniem magnetycznym w urządzeniu. Natomiast nowa wersja „nieskalibrowana” dla różnych wersji tych czujników
nieprzetworzone dane z czujnika i oddzielnie oferują szacowane wartości odchylenia. Te czujniki umożliwiają zastosowanie własnej kalibracji niestandardowej dla danych czujnika poprzez wzbogacenie oszacowanego odchylenia za pomocą danych zewnętrznych.
Odbiornik powiadomień
Do Androida 4.3 dodano nową klasę usługi (NotificationListenerService
), która umożliwia aplikacji otrzymywanie informacji o nowych powiadomieniach publikowanych przez system.
Jeśli Twoja aplikacja uzyskuje obecnie dostęp do powiadomień systemowych za pomocą interfejsów API usługi ułatwień dostępu, zaktualizuj ją, aby używała tych interfejsów API.
dostawca kontaktów
Zapytanie o „kontakty”
Nowe zapytanie dotyczące dostawcy kontaktów, Contactables.CONTENT_URI
, to skuteczny sposób na uzyskanie jednego Cursor
, który zawiera wszystkie adresy e-mail i numery telefonów należące do wszystkich kontaktów pasujących do określonego zapytania.
Zapytanie o różnice kontaktów
Do dostawcy kontaktów dodaliśmy nowe interfejsy API, które pozwalają na efektywne wysyłanie zapytań dotyczących ostatnich zmian w danych kontaktów. Wcześniej aplikacja mogła otrzymywać powiadomienia, gdy coś zmieniło się w danych kontaktów, ale nie wiedziała dokładnie, co się zmieniło. Aby to sprawdzić, musiała pobrać wszystkie kontakty i przeanalizować je.
Aby śledzić zmiany wstawek i aktualizacji, możesz teraz uwzględnić w zaznaczonym elemencie parametr CONTACT_LAST_UPDATED_TIMESTAMP
, aby wysyłać zapytania tylko do tych kontaktów, które uległy zmianie od ostatniego zapytania dotyczącego dostawcy.
Aby śledzić, które kontakty zostały usunięte, nowa tabela ContactsContract.DeletedContacts
zawiera dziennik usuniętych kontaktów (każdy usunięty kontakt jest przechowywany w tej tabeli przez ograniczony czas). Podobnie jak w przypadku parametru CONTACT_LAST_UPDATED_TIMESTAMP
, możesz użyć nowego parametru wyboru CONTACT_DELETED_TIMESTAMP
, aby sprawdzić, które kontakty zostały usunięte od ostatniego zapytania do dostawcy. 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 transmituje teraz działanie CONTACTS_DATABASE_CREATED
, gdy użytkownik
czyści pamięć kontaktów w menu ustawień systemowych, odtwarzając w ten sposób
Baza danych dostawcy kontaktów. Jego zadaniem jest sygnalizowanie aplikacjom, że muszą usunąć cały kontakt
zapisane informacje i wczytać je ponownie za pomocą nowego zapytania.
Przykładowy kod, który korzysta z tych interfejsów API do sprawdzania zmian w kontaktach, znajdziesz w pliku ApiDemos, który jest dostępny w pakiecie Przykłady kodu SDK.
Lokalizacja
Ulepszona obsługa tekstu dwukierunkowego
Poprzednie wersje Androida obsługują języki i układ od prawej do lewej (RTL).
ale czasami nie obsługują tekstu z różnymi kierunkami. Android 4.3 dodaje interfejsy API BidiFormatter
, które pomagają prawidłowo formatować tekst z zawartością w przeciwnym kierunku bez zniekształcania jego części.
Gdy chcesz na przykład utworzyć zdanie ze zmienną ciągu znaków, np. „Czy chodziło Ci o:
15 Bay Street, Laurel, CA?”, zazwyczaj przekazujesz zlokalizowany zasób 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 ustawisz język hebrajski, sformatowany ciąg będzie wyglądał tak:
Tętniąca życiem Ameryka Łacińska, Warszawa, Polska?
To jest błędne, ponieważ liczba „15” powinna znajdować się po lewej stronie „Bay Street”. Rozwiązaniem jest użycie metody BidiFormatter
i jej unicodeWrap()
. Na przykład kod powyżej zmieni się w 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 kierunkowości opartej na pierwszym silnym sygnale, która może się mylić, jeśli pierwszy sygnał kierunkowy dla tekstu nie odpowiada kierunkowi całego tekstu.
W razie potrzeby możesz określić inną heurystykę, przekazując jedną z konstant TextDirectionHeuristic
z TextDirectionHeuristics
do unicodeWrap()
.
Uwaga: te nowe interfejsy API są też dostępne w poprzednich wersjach Androida za pomocą biblioteki obsługi Androida, w tym klasy BidiFormatter
i powiązanych interfejsów API.
Usługi ułatwień dostępu
Obsługa kluczowych zdarzeń
AccessibilityService
może teraz otrzymywać wywołania zwrotne zdarzeń kluczowego wejścia za pomocą metody wywołania zwrotnego onKeyEvent()
. Dzięki temu usługa ułatwień dostępu może obsługiwać dane wejściowe urządzeń takich jak klawiatura i przekształcać je w działania specjalne, które wcześniej były możliwe tylko za pomocą sterowania dotykowego lub przycisków kierunkowych urządzenia.
Zaznacz tekst, a następnie skopiuj/wklej
Interfejs AccessibilityNodeInfo
udostępnia teraz interfejsy API, które umożliwiają AccessibilityService
zaznaczanie, wycinanie, kopiowanie i wklejanie tekstu w węźle.
Aby określić fragment tekstu do wycięcia lub skopiowania, usługa ułatwień dostępu może użyć nowej
działanie, ACTION_SET_SELECTION
, wynik pozytywny
pozycję początkową i końcową zaznaczenia za pomocą funkcji ACTION_ARGUMENT_SELECTION_START_INT
i ACTION_ARGUMENT_SELECTION_END_INT
.
Możesz też zaznaczyć tekst, manipulując kursorem za pomocą istniejącej akcji ACTION_NEXT_AT_MOVEMENT_GRANULARITY
(wcześniej służyła ona tylko do przemieszczania kursora) i dodając argument ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
.
Potem możesz wyciąć lub skopiować treści za pomocą ACTION_CUT
,
ACTION_COPY
, a później wklej w niej przy użyciu
ACTION_PASTE
Uwaga: nowe interfejsy API są również dostępne we wcześniejszych wersjach.
z Androidem dzięki działowi pomocy
Library, w której znajduje się AccessibilityNodeInfoCompat
zajęcia.
Deklarowanie funkcji ułatwień dostępu
Od wersji 4.3 Androida usługa ułatwień dostępu musi deklarować możliwości ułatwień dostępu w pliku metadanych, aby móc korzystać z pewnych funkcji ułatwień dostępu. Jeśli nie można
w pliku metadanych, funkcja nie będzie operacyjna. Aby zadeklarować
funkcji ułatwień dostępu, należy używać atrybutów XML odpowiadających różnym
„capability” stałe w zakresie AccessibilityServiceInfo
zajęcia.
Jeśli na przykład usługa nie żąda możliwości flagRequestFilterKeyEvents
,
nie będzie więc otrzymywać kluczowych zdarzeń.
Testowanie i debugowanie
Automatyczne testowanie interfejsu użytkownika
Nowa klasa UiAutomation
udostępnia interfejsy API, które umożliwiają symulowanie działań użytkownika na potrzeby automatyzacji testów. Korzystając z interfejsów API AccessibilityService
platformy, możesz sprawdzać zawartość ekranu i wstawiać dowolne zdarzenia związane z klawiaturą oraz dotykiem.
Aby uzyskać instancję UiAutomation
, wywołaj funkcję Instrumentation.getUiAutomation()
. Aby to działało, musisz podać opcję -w
w ramach polecenia instrument
podczas uruchamiania InstrumentationTestCase
z adb shell
.
Za pomocą instancji UiAutomation
możesz wykonywać dowolne zdarzenia, aby testować aplikację. Wystarczy, że wywołasz funkcję executeAndWaitForEvent()
, przekazując jej Runnable
do wykonania, okres oczekiwania na wykonanie operacji oraz implementację interfejsu UiAutomation.AccessibilityEventFilter
. W ramach implementacji UiAutomation.AccessibilityEventFilter
otrzymasz wywołanie, które umożliwia filtrowanie interesujących Cię zdarzeń i określanie, czy dany przypadek testowy zakończył się powodzeniem, czy nie.
Aby obserwować wszystkie zdarzenia podczas testu, utwórz implementację funkcji UiAutomation.OnAccessibilityEventListener
i przekaż ją do funkcji setOnAccessibilityEventListener()
.
Za każdym razem, gdy wystąpi zdarzenie, wywoływana jest metoda onAccessibilityEvent()
interfejsu listenera, która otrzymuje obiekt AccessibilityEvent
opisujący to zdarzenie.
Interfejsy API UiAutomation
ujawniają też wiele innych operacji
bardzo niskim, aby zachęcić do rozwoju narzędzi do testowania interfejsu, takich jak uiautomator. Przykład:
UiAutomation
może też:
- Wstrzyknij zdarzenia wejściowe
- Zmienianie orientacji ekranu
- wykonać zrzut ekranu,
Co najważniejsze dla narzędzi do testowania interfejsu użytkownika, interfejsy API UiAutomation
działają w różnych aplikacjach, w przeciwieństwie do interfejsów API Instrumentation
.
Zdarzenia Systrace dla aplikacji
Android 4.3 dodaje klasę Trace
z 2 metodami statycznymi:
beginSection()
i endSection()
,
który umożliwia zdefiniowanie bloków kodu, które mają być uwzględniane w raporcie systrace. Tworząc
fragmentów kodu możliwego do śledzenia w aplikacji, logi systrace dostarczają dużo bardziej szczegółowych informacji
analiza miejsca w aplikacji, gdzie występuje spowolnienie.
Informacje o korzystaniu z narzędzia Systrace znajdziesz w artykule Analiza wyświetlania i skuteczności reklam w systemie Systrace.
Bezpieczeństwo
Kluczowe repozytorium Androida dla kluczy prywatnych aplikacji
W regionie KeyStore
Android oferuje teraz niestandardowego dostawcę zabezpieczeń Java
o nazwie Android Key Store, która pozwala generować i zapisywać klucze prywatne,
może być widoczna i używana tylko przez Twoją aplikację. Aby wczytać magazyn kluczy Android, przekaż
"AndroidKeyStore"
do KeyStore.getInstance()
.
Aby zarządzać prywatnymi poświadczeniami aplikacji w Android Key Store, wygeneruj nowy klucz za pomocą KeyPairGenerator
z użyciem KeyPairGeneratorSpec
. 1.
uzyskać wystąpienie funkcji KeyPairGenerator
, wywołując metodę getInstance()
. Następnie wywołaj funkcję initialize()
, przekazując jej instancję KeyPairGeneratorSpec
, którą możesz uzyskać za pomocą funkcji KeyPairGeneratorSpec.Builder
.
Na koniec zdobądź KeyPair
, dzwoniąc pod numer generateKeyPair()
.
Magazyn danych logowania na sprzęcie
Android obsługuje teraz także pamięć sprzętową urządzenia KeyChain
danych logowania, zwiększając bezpieczeństwo, uniemożliwiając wyodrębnianie kluczy. Oznacza to, że raz
Klucze znajdują się w obsługiwanym sprzętowo magazynie kluczy (Secure Element, TPM lub TrustZone). Mogą być używane
operacji kryptograficznych, ale nie można wyeksportować materiału klucza prywatnego. Nawet jądro systemu operacyjnego
nie może uzyskać dostępu do tego materiału klucza. Nie wszystkie urządzenia z systemem Android obsługują
sprzęt, można sprawdzić w czasie działania, czy dostępna pamięć sprzętowa jest dostępna, wywołując
KeyChain.IsBoundKeyAlgorithm()
Deklaracje w pliku manifestu
Deklarowane wymagane funkcje
W elemencie <uses-feature>
są teraz obsługiwane te wartości, dzięki czemu możesz mieć pewność, że Twoja aplikacja jest instalowana tylko na urządzeniach, które zapewniają funkcje wymagane przez aplikację.
FEATURE_APP_WIDGETS
- Oświadczenie, że Twoja aplikacja udostępnia widżet aplikacji i powinna być instalowana tylko na urządzeniach, które mają ekran główny lub podobną lokalizację, gdzie użytkownicy mogą umieszczać widżety aplikacji.
Przykład:
<uses-feature android:name="android.software.app_widgets" android:required="true" />
FEATURE_HOME_SCREEN
- Oświadczenie, że aplikacja działa jak ekran główny i powinna być instalowana tylko na urządzeniach, które obsługują aplikacje ekranu głównego innych firm.
Przykład:
<uses-feature android:name="android.software.home_screen" android:required="true" />
FEATURE_INPUT_METHODS
- Deklaruje, że Twoja aplikacja udostępnia niestandardową metodę wprowadzania (klawiaturę utworzoną za pomocą
InputMethodService
) i powinna być instalowana tylko na urządzeniach obsługujących metody wprowadzania innych firm. Przykład:<uses-feature android:name="android.software.input_methods" android:required="true" />
FEATURE_BLUETOOTH_LE
- Oświadcza, że aplikacja korzysta z interfejsów Bluetooth Low Energy i powinna być instalowana tylko na urządzeniach, które mogą komunikować się z innymi urządzeniami za pomocą Bluetooth Low Energy.
Przykład:
<uses-feature android:name="android.software.bluetooth_le" android:required="true" />
Uprawnienia użytkowników
W elementach <uses-permission>
są teraz obsługiwane te wartości, które umożliwiają deklarowanie uprawnień wymaganych przez aplikację do uzyskiwania dostępu do określonych interfejsów API.
BIND_NOTIFICATION_LISTENER_SERVICE
- Wymagany do korzystania z nowych interfejsów API
NotificationListenerService
. SEND_RESPOND_VIA_MESSAGE
- Wymagane do odbierania informacji o
ACTION_RESPOND_VIA_MESSAGE
zamierzeniach.
Szczegółowy widok wszystkich zmian interfejsu API w Androidzie 4.3 znajdziesz w Raport o różnicach w interfejsie API.