Oprócz nowych funkcji i możliwości Android 8.0 (poziom API 26) obejmuje różne zmiany w działaniu systemu i interfejsu API. Ten dokument Wyróżniamy najważniejsze zmiany, o których należy pamiętać i które warto wziąć pod uwagę. w Twoich aplikacjach.
Większość tych zmian dotyczy wszystkich aplikacji, niezależnie od wersji Android, na który są kierowane. Kilka zmian wpływa jednak tylko na kierowanie na aplikacje Android 8.0 Aby zwiększyć przejrzystość, składa się z 2 sekcji: Zmiany dla wszystkich aplikacji i Zmiany w kierowaniu na aplikacje Android 8.0
Zmiany dotyczące wszystkich aplikacji
Zmiany w działaniu mają zastosowanie do
Limity wykonywania w tle
Jedną ze zmian, jakie wprowadza Android 8.0 (poziom interfejsu API 26) wydłużać czas pracy na baterii, gdy aplikacja w pamięci podręcznej stan, bez aktywnej components, system uruchamia wszystkie blokady wybudzenia ustawione przez aplikację.
Aby poprawić wydajność urządzenia, system ogranicza też zachowanie aplikacji niedziałających na pierwszym planie. Więcej szczegółów:
- Aplikacje działające w tle mają teraz ograniczenia dostęp do usług w tle.
- Aplikacje nie mogą używać plików manifestu do rejestrowania większości komunikatów niejawnych (czyli transmisji, które nie są kierowane bezpośrednio do aplikacji).
Domyślnie te ograniczenia dotyczą tylko aplikacji kierowanych na O. Pamiętaj jednak: użytkownicy mogą włączyć te ograniczenia dla każdej aplikacji z poziomu ekranu Ustawienia, nawet jeśli aplikacja nie jest kierowana na O.
Android 8.0 (poziom interfejsu API 26) zapewnia też te zmiany w konkretnych metodach:
- Metoda
startService()
zgłasza teraz błądIllegalStateException
, jeśli aplikacja kierowanie na Androida 8.0 próbuje użyć tej metody. w sytuacji, gdy tworzenie usług w tle nie jest dozwolone. - Nowa metoda
Context.startForegroundService()
rozpoczyna usługę działającą na pierwszym planie. System zezwala na aplikacje aby dzwonić pod numerContext.startForegroundService()
, nawet gdy aplikacja jest w tle. Aplikacja musi jednak wywołać metodęstartForeground()
tej usługi w ciągu pięciu sekund po utworzeniu usługi.
Więcej informacji: Limity wykonywania w tle.
Ograniczenia lokalizacji w tle na Androidzie
Aby oszczędzać baterię, zadbać o wygodę użytkowników i stan systemu, aplikacje działające w tle otrzymują aktualizacje lokalizacji rzadziej, gdy są używane na urządzeniu z Androidem 8.0. Ta zmiana działania wpływa na wszystkie aplikacje które otrzymują aktualizacje lokalizacji, w tym Usług Google Play.
Te zmiany dotyczą tych interfejsów API:
- Dostawca uśrednionej lokalizacji (FLP)
- Geofencing
- Pomiary GNSS
- Menedżer lokalizacji
- Menedżer Wi-Fi
Aby upewnić się, że aplikacja działa zgodnie z oczekiwaniami, wykonaj te czynności:
- Sprawdź mechanizmy działania aplikacji i upewnij się, że używasz najnowszej lokalizacji API.
- Sprawdź, czy aplikacja działa zgodnie z oczekiwaniami przy każdym użyciu tych kwestii.
- Rozważ użycie Scalona Dostawca lokalizacji (ang. Location Provider, FLP) lub geofencing na potrzeby obsługi przypadków użycia, w których bieżącej lokalizacji użytkownika.
Więcej informacji o tych zmianach znajdziesz w artykule Lokalizacja w tle Limity.
Skróty do aplikacji
Android 8.0 (poziom interfejsu API 26) zawiera te zmiany w skrótach do aplikacji:
- Transmisja nr
com.android.launcher.action.INSTALL_SHORTCUT
nie ma już żadnego wpływu na aplikację, ponieważ jest ona prywatna, domyślnie transmisję. Zamiast tego utwórz skrót do aplikacji za pomocąrequestPinShortcut()
z klasyShortcutManager
. ACTION_CREATE_SHORTCUT
intencja może teraz tworzyć skróty do aplikacji, którymi zarządzasz za pomocąShortcutManager
zajęcia. Ten zamiar może też starsze skróty programu uruchamiającego, które nie współdziałają zShortcutManager
Wcześniej ta intencja mogła tworzyć tylko starsze skróty programu uruchamiającego.- Skróty utworzone za pomocą
requestPinShortcut()
i skrótów utworzonych w aktywności, która obsługujeACTION_CREATE_SHORTCUT
to w pełni funkcjonalne skróty do aplikacji. W związku z tym aplikacje mogą je teraz aktualizować za pomocą metod wShortcutManager
. - Starsze skróty zachowują funkcję z poprzednich wersji Androida, ale musisz ręcznie przekonwertować je na skróty do aplikacji.
Więcej informacji o zmianach w skrótach do aplikacji znajdziesz w Przypinanie skrótów Przewodnik po funkcjach widżetów.
Języki i internacjonalizacja
W Androidzie 7.0 (poziom API 24) wprowadziliśmy koncepcję możliwości
określić domyślny język kategorii, ale niektóre interfejsy API nadal używały parametru
ogólny Locale.getDefault()
bez argumentów, gdy zamiast tego powinni użyć domyślnego języka kategorii DISPLAY
. W Androidzie 8.0 (poziom interfejsu API 26)
następujące metody używają teraz Locale.getDefault(Category.DISPLAY)
zamiast Locale.getDefault()
:
Locale.getDisplayScript(Locale)
również
przywraca wartość Locale.getDefault()
, gdy
Dla parametru Locale
określono wartość displayScript
– argument jest niedostępny.
Dodatkowe zmiany dotyczące języka i internacjonalizacji następujące:
- Dzwonienie pod
Currency.getDisplayName(null)
zwracaNullPointerException
. które pasują do udokumentowanego zachowania. - Analiza nazwy strefy czasowej została zmieniona. Wcześniej,
Urządzenia z Androidem używały wartości zegara systemowego próbkowanej podczas uruchamiania
czas do buforowania nazw stref czasowych używanych do analizy daty
razy. Mogło to negatywnie wpłynąć na analizę, jeśli system
Podczas uruchamiania lub w innych, rzadkich przypadkach zegar był błędny.
Obecnie w typowych przypadkach logika analizy wykorzystuje teraz dane z pola OIOM bieżącej wartości zegara systemowego podczas analizowania nazw stref czasowych. Ten zmiana dostarcza bardziej poprawne wyniki, które mogą się różnić od wcześniejszych Wersje Androida, w których aplikacja używa zajęć takich jak
SimpleDateFormat
- Android 8.0 (poziom interfejsu API 26) aktualizuje wersję ICU do wersji 58.
Okna alertów
Jeśli aplikacja używa SYSTEM_ALERT_WINDOW
uprawnienia i używa jednego z następujących typów okien, aby spróbować wyświetlić
alertów nad innymi aplikacjami i oknami systemowymi:
...te okna są zawsze wyświetlane pod oknami, które korzystają z
Okno TYPE_APPLICATION_OVERLAY
typu. Jeśli aplikacja jest kierowana na Androida 8.0 (poziom interfejsu API 26), korzysta ona z
TYPE_APPLICATION_OVERLAY
typu okna.
Więcej informacji znajdziesz w artykule Typowe typy okien dla okna alertów w sekcji zmian działania aplikacji, na Androida 8.0.
Wpisywanie i nawigacja
Wraz z pojawieniem się aplikacji na Androida na ChromeOS i innych dużych formatów takich jak tablety. Użytkownicy coraz częściej korzystają z nawigacji za pomocą klawiatury. Aplikacje na Androida. W Androidzie 8.0 (poziom interfejsu API 26) zmieniliśmy działanie za pomocą używać klawiatury jako urządzenia wejściowego nawigacji, co zwiększa niezawodność, przewidywalny model nawigacji za pomocą strzałek i tabulatorów.
Wprowadziliśmy następujące zmiany w zaznaczaniu elementów. zachowanie:
-
Jeśli nie zdefiniowano żadnych kolorów stanu zaznaczenia dla
View
obiekt (pierwszy plan lub tło) rysowalna), platforma ustawia teraz domyślny kolor wyróżnieniaView
To wyróżnienie to faliste rysy, które jest na podstawie tematu aktywności.Jeśli nie chcesz, aby obiekt
View
używał tej wartości domyślnej podświetlić, kiedyandroid:defaultFocusHighlightEnabled
dla atrybutufalse
w pliku XML układu zawierającegoView
lub wsiądź wfalse
dosetDefaultFocusHighlightEnabled()
w logice interfejsu aplikacji. - Aby sprawdzić, jak wprowadzanie za pomocą klawiatury wpływa na fokus elementu interfejsu, możesz włączyć Rysunek > Pokaż granice układu. Na Androidzie 8.0, wyświetla się „X” nad elementem, który obecnie ma ostrość.
Poza tym wszystkie elementy paska narzędzi w Androidzie 8.0 są automatycznie klastry nawigacji z klawiaturą, co ułatwia użytkownikom poruszanie się po pasku narzędzi całość.
Aby dowiedzieć się więcej o poprawianiu obsługi nawigacji za pomocą klawiatury w Twojej aplikacji, zapoznaj się z Pomocą techniczną Przewodnik ponawigacji za pomocą klawiatury.
Autouzupełnianie formularzy internetowych
Gdy dzięki Androidowi Autouzupełnianie
Framework zapewnia wbudowaną obsługę autouzupełniania,
następujące metody związane z obiektami WebView
uległy zmianie
w przypadku aplikacji zainstalowanych na urządzeniach z Androidem 8.0 (poziom interfejsu API 26):
WebSettings
-
-
getSaveFormData()
zwraca terazfalse
. Wcześniej ta metoda zwracałatrue
. - Łączę
Nie:
setSaveFormData()
nie ma już żadnego skutku.
-
WebViewDatabase
-
- Łączę
Nie:
clearFormData()
nie ma już żadnego skutku. -
hasFormData()
metoda zwraca terazfalse
. Wcześniej ta metoda zwracałatrue
, gdy formularz zawierał dane.
- Łączę
Nie:
Ułatwienia dostępu
Android 8.0 (poziom interfejsu API 26) zawiera te zmiany w ułatwieniach dostępu:
-
Platforma ułatwień dostępu konwertuje teraz wszystkie gesty dwukrotnego dotknięcia na
ACTION_CLICK
. Ta zmiana sprawia, że TalkBack działa bardziej jak inne usług ułatwień dostępu.Jeśli obiekty
View
w Twojej aplikacji korzystają z dotyku niestandardowego musisz sprawdzić, czy nadal działa z TalkBack. Możesz wystarczy zarejestrować moduł obsługi kliknięć, któryView
których używają obiekty. Jeśli TalkBack nadal nie rozpoznaje gestów wykonywanych na tych urządzeniachView
obiekty, zastąpperformAccessibilityAction()
- Usługi ułatwień dostępu są już znane
ClickableSpan
wystąpienia w Twojej aplikacjiTextView
obiektów.
Aby dowiedzieć się więcej o ułatwieniach dostępu w aplikacji, zobacz Ułatwienia dostępu.
Sieć i połączenia HTTP(S)
Android 8.0 (poziom interfejsu API 26) obejmuje te zmiany w działaniu połączenia sieciowe i połączenia HTTP(S):
- Żądania OPTIONS bez treści mają atrybut
Content-Length: 0
nagłówek. Wcześniej nie miały nagłówkaContent-Length
. - HttpURLConnection normalizuje adresy URL zawierające puste ścieżki przez dodanie
ukośnik za nazwą hosta lub urzędu. Na przykład:
konwertuje
http://example.com
nahttp://example.com/
- Niestandardowy selektor serwera proxy ustawiony przez ProxySelector.setDefault() kieruje reklamy tylko na adres (schemat, host i port) żądanego adresu URL. Dlatego wybór serwera proxy może być oparty tylko na tych wartościach. Adres URL przekazywane do niestandardowego selektora serwera proxy nie zawiera żądanych adresów URL ścieżki, parametrów zapytania czy fragmentów.
- Identyfikatory URI nie mogą zawierać pustych etykiet.
Wcześniej platforma obsługiwała obejście polegające na akceptowanie pustych etykiet w nazwy hostów, co jest niedozwolone w przypadku identyfikatorów URI. To obejście było przeznaczone dla zgodność ze starszymi wersjami libcore. Deweloperzy używający interfejsu API nieprawidłowo zobaczy komunikat ADB: „Identyfikator URI example.com ma puste etykiety w nazwa hosta. Ten format ma nieprawidłowy format i nie zostanie zaakceptowany w przyszłości na Androidzie wydania”. Android 8.0 usuwa to obejście, system zwraca wartość null w przypadku nieprawidłowych identyfikatorów URI.
- Implementacja HttpsURLConnection w Androidzie 8.0 nie obsługuje niezabezpieczonej wersji protokołu TLS/SSL.
- Obsługa tunelowania połączeń HTTP(S) zmieniła się w ten sposób:
- Podczas tunelowania połączenia HTTPS przez połączenie system prawidłowo umieszcza numer portu (:443) w wierszu Host podczas wysyłania. te informacje na serwer pośredni. Wcześniej, jest wyświetlany tylko w wierszu CONNECT.
- System nie wysyła już klientów użytkownika i autoryzacji serwera proxy
z żądania tunelowanego do serwera proxy.
System nie wysyła już na stronę przeprowadzono tunelowanie Http(s)URLConnection na serwerze proxy podczas konfigurowania przez tunel. Zamiast tego system generuje nagłówek autoryzacji proxy, i wysyła ją do serwera proxy, gdy ten serwer Kod HTTP 407 w odpowiedzi na początkowe żądanie.
System przestanie też kopiować nagłówek klienta użytkownika. z żądania tunelowanego do żądania serwera proxy, które konfiguruje przez tunel. Zamiast tego biblioteka generuje dla niej nagłówek klienta użytkownika, użytkownika.
send(java.net.DatagramPacket)
zwraca wyjątek SocketException, jeśli wcześniej wykonana metoda Connect() niepowodzenie.- DatagramSocket.connect() ustawia pendingSocketException, jeśli błąd wewnętrzny. Przed Androidem 8.0 kolejna funkcja recv() wywołał błąd SocketException, mimo że wywołanie send() powiodło się. Aby zachować spójność, oba wywołania zgłaszają teraz wyjątek SocketException.
- InetAddress.isReachable() próbuje wykonać ICMP, zanim przełączy się na protokół TCP Echo
protokołu.
- Niektóre hosty blokujące port 7 (TCP Echo), takie jak google.com, mogą mogą być teraz osiągalne, jeśli zaakceptują protokół ICMP Echo.
- W przypadku naprawdę niedostępnych hostów ta zmiana oznacza 2-krotnie ile czasu zostało do ponowienia połączenia.
Bluetooth
Android 8.0 (poziom interfejsu API 26) wprowadza te zmiany w długości
dane używane przez funkcję ScanRecord.getBytes()
pobiera:
- Metoda
getBytes()
nie przyjmuje żadnych założeń liczba otrzymanych bajtów. Nie należy więc stosować żadnych minimalnej lub maksymalnej liczby zwracanych bajtów. Zamiast tego powinni ocenić długość tablicy wynikowej. - Urządzenia zgodne z Bluetooth 5 mogą zwracać dane dłuższe niż wcześniejsze maksimum wynoszące ok. 60 bajtów.
- Jeśli urządzenie zdalne nie dostarcza odpowiedzi na skanowanie – mniej niż 60 bajtów które mogą zostać zwrócone.
Sprawne łączenie
Android 8.0 (poziom interfejsu API 26) wprowadza wiele ulepszeń w ustawieniach Wi-Fi, aby ułatwić wybór Wybierz sieć Wi-Fi, która zapewni użytkownikom najlepsze wrażenia. Konkretne zmiany to m.in.:
- Większa stabilność i niezawodność.
- Bardziej intuicyjny interfejs użytkownika.
- Jedno, skonsolidowane menu Ustawienia Wi-Fi.
- Na zgodnych urządzeniach automatyczna aktywacja Wi-Fi w przypadku zapisanej sieci wysokiej jakości jest w pobliżu.
Bezpieczeństwo
Android 8.0 obejmuje te funkcje zabezpieczeń zmiany:
- Platforma nie obsługuje już protokołu SSLv3.
- Podczas nawiązywania połączenia HTTPS z serwerem, które nieprawidłowo
implementuje negocjacje wersji protokołu TLS,
HttpsURLConnection
nie próbuje już obejść tego problemu na korzystanie z wcześniejszych wersji protokołu TLS i ponawianie ponownych prób. - Android 8.0 (poziom interfejsu API 26) stosuje bezpieczne przetwarzanie (SECCOMP) filtr do wszystkich aplikacji. Lista dozwolonych wywołań Syscall jest ograniczona do tych narażone na kontakt bionikowy. Chociaż dostępnych jest kilka innych wywołań Syscall dla zgodności wstecznej odradzamy ich używanie.
- Obiekty
WebView
Twojej aplikacji są teraz uruchamiane w trybie wieloprocesowym i trybu uzyskiwania zgody. Treści internetowe są przetwarzane w ramach osobnego, osobnego procesu o procesie aplikacji zwiększającym bezpieczeństwo. -
Nie możesz już zakładać, że pliki APK znajdują się w katalogach, których nazwy kończą się
-1 lub -2. Aplikacje, które powinny używać
sourceDir
, aby uzyskać z katalogu i nie bezpośrednio polegać na formacie katalogu. - Informacje o ulepszeniach zabezpieczeń związanych z korzystaniem z reklam natywnych Więcej informacji znajdziesz w artykule na temat bibliotek natywnych.
Oprócz tego w Androidzie 8.0 (poziom interfejsu API 26) wprowadzamy następujące zmiany związane z instalowaniem nieznane aplikacje z nieznanych źródeł:
- Wartość ustawienia starszego typu
INSTALL_NON_MARKET_APPS
to teraz zawsze 1. Aby określić, czy nieznane źródło może instalować aplikacje za pomocą instalatora pakietu, należy zamiast tego użyć wartości zwracanejcanRequestPackageInstalls()
- Jeśli spróbujesz zmienić wartość parametru
INSTALL_NON_MARKET_APPS
korzysta z:setSecureSetting()
,UnsupportedOperationException
rzucona. Aby uniemożliwić użytkownikom instalowanie nieznanych aplikacji przy użyciu nieznanych aplikacji , zamiast tego zastosuj metodę UżytkownikDISALLOW_INSTALL_UNKNOWN_SOURCES
. -
Profile zarządzane utworzone na urządzeniach z Androidem 8.0 (poziom interfejsu API 26) automatycznie otrzymują
Użytkownik
DISALLOW_INSTALL_UNKNOWN_SOURCES
ograniczenie włączone. Istniejące profile zarządzane na urządzeniach, które: uaktualniony do Androida 8.0, UżytkownikDISALLOW_INSTALL_UNKNOWN_SOURCES
jest włączone automatycznie, o ile właściciel profilu nie wyraźnie to ograniczenie zostało wyłączone (przed uaktualnieniem) przez ustawienieINSTALL_NON_MARKET_APPS
do 1.
Dodatkowe informacje o instalowaniu nieznanych aplikacji znajdziesz w Nieznana aplikacja Przewodnik po uprawnieniach instalacji.
Dodatkowe wskazówki na temat zwiększania bezpieczeństwa aplikacji znajdziesz tutaj: Bezpieczeństwo dla deweloperów aplikacji na Androida
Prywatność
Android 8.0 (poziom interfejsu API 26) powoduje, że następujące funkcje związane z ochroną prywatności zmian na platformie.
- Platforma obsługuje teraz identyfikatory w inny sposób.
-
W przypadku aplikacji, które zostały zainstalowane przed aktualizacją OTA do wersji
Android 8.0 (poziom API 26)
(poziom interfejsu API 26), wartość
Pole
ANDROID_ID
pozostaje bez zmian chyba że odinstalujesz aplikację, a potem zainstalujesz ponownie po aktualizacji OTA. Aby zachować wartości w po zakończeniu aktualizacji OTA, programiści mogą powiązać starą i nową wartość za pomocą Kopia zapasowa pary klucz/wartość. - W przypadku aplikacji zainstalowanych na urządzeniach z Androidem 8.0 wartość
ANDROID_ID
ma teraz zakres na klucz podpisywania aplikacji i na użytkownika. Wartość AdresANDROID_ID
jest unikalny dla każdej kombinacji klucza podpisywania aplikacji, użytkownika i urządzenia. W rezultacie na tym samym urządzeniu mogą działać aplikacje z różnymi kluczami podpisywania nie zobaczą już takiego samego identyfikatora Androida (nawet dla tego samego użytkownika). - Wartość
ANDROID_ID
nie zmienia się podczas odinstalowywania ani ponownego instalowania pakietu, o ile klucz podpisywania jest taki sam (a aplikacja nie została zainstalowana przed aktualizacją OTA (wersja Androida 8.0). - Wartość
ANDROID_ID
nie zmienia się, nawet jeśli aktualizacja systemu spowoduje zmianę klucza podpisywania pakietu. - na urządzeniach wysyłanych z użyciem Usług Google Play i identyfikatora wyświetlania reklam.
musisz użyć
Identyfikator wyświetlania reklam. Prosty, standardowy system
do zarabiania na aplikacjach,
Identyfikator wyświetlania reklam to unikalny, możliwy do zresetowania przez użytkownika identyfikator wyświetlania reklam. Jest on dostępny
przez Usługi Google Play.
Urządzenia innych producentów powinny kontynuować aby dostarczyć
ANDROID_ID
.
-
W przypadku aplikacji, które zostały zainstalowane przed aktualizacją OTA do wersji
Android 8.0 (poziom API 26)
(poziom interfejsu API 26), wartość
Pole
- Zapytanie o właściwość systemową
net.hostname
zwraca wartość null wynik.
Logowanie niewykrytych wyjątków
Jeśli aplikacja zainstaluje Thread.UncaughtExceptionHandler
, który robi to
nie możesz połączyć się z domyślnym numerem Thread.UncaughtExceptionHandler
,
system
nie powoduje zamknięcia aplikacji w przypadku wystąpienia nieobsłużonego wyjątku. Od
w Androidzie 8.0 (poziom interfejsu API 26), system rejestruje zapis stosu wyjątków w tej
sytuacja; we wcześniejszych wersjach platformy system nie musiałby mieć
zarejestrowano zapis stosu wyjątków.
Zalecamy niestandardowy atrybut Thread.UncaughtExceptionHandler
zawsze wyzwalają metodę
domyślny moduł obsługi, na aplikacje stosujące się do tej rekomendacji nie mają wpływu
zmiany w Androidzie 8.0.
zmiana podpisu za pomocą funkcji findViewById()
Wszystkie instancje metody findViewById()
zwracają teraz
<T extends View> T
zamiast View
. Ta zmiana
ma takie konsekwencje:
- Może to spowodować, że istniejący kod będzie mieć niejednoznaczny typ zwrotu,
na przykład, jeśli jest zarówno
someMethod(View)
, jak isomeMethod(TextView)
, który przenosi wynik wywołania dofindViewById()
- Jeśli używany jest język źródłowy Java 8, wymaga to jawnego rzutu na
View
, gdy typ zwrotu nie jest ograniczony (na przykładassertNotNull(findViewById(...)).someViewMethod())
- Zastąpienia nieostatecznych metod
findViewById()
(dla (np.Activity.findViewById()
) będą potrzebować zwrotu Zaktualizowano typ.
Zmiana statystyk użytkowania dostawcy kontaktów
W poprzednich wersjach Androida komponent Dostawca kontaktów
pozwala programistom uzyskać dane o korzystaniu dla każdego kontaktu. Te dane o korzystaniu
ujawnia informacje o każdym adresie e-mail i powiązanym numerze telefonu;
z kontaktem, w tym liczbę prób nawiązania z nim kontaktu
i kiedy po raz ostatni skontaktowano się z danym kontaktem. Aplikacje, które proszą o oznaczenie
READ_CONTACTS
uprawnienia do odczytu tych danych.
Aplikacje mogą odczytać te dane, jeśli o to poprosisz
READ_CONTACTS
uprawnienia. W Androidzie 8.0 (poziom interfejsu API 26) i nowszych zapytania o dane o korzystaniu są zwracane
wartości przybliżone, a nie dokładne. System Android utrzymuje
wartości wewnętrznie, tak więc ta zmiana nie będzie miała wpływu
API autouzupełniania.
Ta zmiana działania wpływa na te parametry zapytania:
Obsługa odbioru
AbstractCollection.removeAll()
i AbstractCollection.retainAll()
teraz zawsze zwraca NullPointerException
; poprzednia wersja
Element NullPointerException
nie został odrzucony, gdy kolekcja została
puste. Ta zmiana sprawia, że zachowanie jest zgodne z dokumentacją.
Android Enterprise
Android 8.0 (poziom interfejsu API 26) zmienia działania niektórych interfejsów API i funkcji aplikacji firmowych, w tym kontrolerów zasad (DPC). Wprowadzone zmiany:
- Nowe zachowania ułatwiające aplikacjom obsługę profili służbowych na w pełni zarządzanych urządzeniach.
- Zmiany dotyczące obsługi aktualizacji systemu, weryfikacji aplikacji oraz uwierzytelniania zwiększyć integralność urządzenia i systemu.
- Ulepszenia obsługi administracyjnej, powiadomień, Ekran ostatnich danych i zawsze włączona sieć VPN.
Aby poznać wszystkie zmiany wprowadzone w Androidzie 8.0 (poziom interfejsu API 26) i dowiedzieć się, jak mogą ma wpływ na Twoją aplikację, przeczytaj Android w firmach
Aplikacje kierowane na Androida 8.0
Te zmiany w działaniu dotyczą wyłącznie aplikacji, na które są kierowane
Android 8.0 (poziom interfejsu API 26) lub nowszy. aplikacje kompatybilne z Androidem 8.0,
lub ustaw targetSdkVersion
na Androida 8.0 lub nowszego
ich aplikacje do prawidłowej obsługi tych zachowań (w stosownych przypadkach).
Okna alertów
Aplikacje używające uprawnienia SYSTEM_ALERT_WINDOW
uprawnienia nie mogą już używać następujących typów okien do wyświetlania okien alertów
nad innymi aplikacjami i oknami systemowymi:
Aplikacje muszą używać nowego typu okna o nazwie
TYPE_APPLICATION_OVERLAY
Jeśli korzystasz z metody
Okno TYPE_APPLICATION_OVERLAY
wpisz w celu wyświetlenia okien alertów dotyczących aplikacji, zachowaj te cechy
o nowym typie okna:
- Okna alertów aplikacji są zawsze widoczne w kluczowych oknach systemowych, takich jak takie jak pasek stanu czy edytory IME.
- System może przenosić okna lub zmieniać ich rozmiar
TYPE_APPLICATION_OVERLAY
typu okna. - W obszarze powiadomień można wybrać ustawienia blokowania
wyświetlania przez aplikację okien z alertami wyświetlanych przy użyciu
TYPE_APPLICATION_OVERLAY
typu okna.
Powiadomienia o zmianach treści
W Androidzie 8.0 (poziom interfejsu API 26) zmienia się sposób
ContentResolver.notifyChange()
i registerContentObserver(Uri, boolean, ContentObserver)
w aplikacjach kierowanych na Androida 8.0.
Te interfejsy API wymagają teraz prawidłowego atrybutu ContentProvider
jest zdefiniowany dla urzędu we wszystkich identyfikatorach URI. Zdefiniowanie prawidłowego ContentProvider
z odpowiednimi uprawnieniami spowoduje
pomagają chronić aplikację przed zmianami treści
przez złośliwe aplikacje i zapobiegać
przed wyciekiem potencjalnie prywatnych danych do szkodliwych aplikacji.
Wyświetl fokus
Klikalne obiekty View
mogą teraz zaznaczać również
wartość domyślną. Jeśli chcesz, aby obiekt View
mógł być klikalny, ale nie
ustaw
Atrybut android:focusable
do false
w układzie
Plik XML zawierający View
lub przekaż w false
do setFocusable()
w interfejsie aplikacji
logikę logiczną.
Dopasowywanie klienta użytkownika w funkcji wykrywania przeglądarki
Android 8.0 (poziom interfejsu API 26) i nowsze zawierają
ciąg identyfikatora kompilacji OPR
. Niektóre dopasowania do wzorca mogą
powoduje, że logika wykrywania przeglądarki błędnie identyfikuje przeglądarkę inną niż Opera jako Opera.
Przykładem dopasowania do wzorca może być:
if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}
Aby uniknąć problemów wynikających z takiej nieprawidłowej identyfikacji, użyj ciągu innego niż
OPR
jako dopasowanie do wzorca w przeglądarce Opera.
Bezpieczeństwo
Te zmiany wpływają na bezpieczeństwo w Androidzie 8.0 (poziom interfejsu API 26):
- Jeśli konfiguracja zabezpieczeń sieci aplikacji
opcje
obsługi ruchu nieszyfrowanego,
Obiekty
WebView
nie mają dostępu do stron internetowych przez HTTP. Każdy ObiektWebView
musi używać protokołu HTTPS. - Ustawienie systemowe Zezwalaj na nieznane źródła zostało usunięte. w uprawnienie Instalowanie nieznanych aplikacji umożliwia zarządzanie nieznanymi instalacjami aplikacji z nieznanych źródeł. Więcej informacji o tym nowym uprawnieniu: Nieznana aplikacja Przewodnik po uprawnieniach instalacji.
Dodatkowe wskazówki na temat zwiększania bezpieczeństwa aplikacji znajdziesz tutaj: Bezpieczeństwo dla deweloperów aplikacji na Androida
Dostęp do konta i wykrywalność
W Androidzie 8.0 (poziom interfejsu API 26) aplikacje nie mają już dostępu
z kontami użytkowników, chyba że podmiot uwierzytelniający jest właścicielem kont lub
użytkownik udziela takiego dostępu.
GET_ACCOUNTS
uprawnienie
już nie wystarcza. Aby aplikacja mogła mieć dostęp do konta,
możesz użyć funkcji AccountManager.newChooseAccountIntent()
lub aplikacji uwierzytelniającej
. Po uzyskaniu dostępu do kont aplikacja może zadzwonić
AccountManager.getAccounts()
aby uzyskać do nich dostęp.
Wycofywanie Androida 8.0
LOGIN_ACCOUNTS_CHANGED_ACTION
aplikacji;
powinni zamiast tego użyć
addOnAccountsUpdatedListener()
aby otrzymywać informacje o kontach w trakcie działania.
Informacje na temat nowych interfejsów API i metod dodanych do dostępu do konta oraz wykrywalność, patrz Dostęp do konta i wykrywalność.
Prywatność
Poniższe zmiany wpływają na prywatność w Androidzie 8.0 (poziom interfejsu API 26).
-
Właściwości systemowe
net.dns1
,net.dns2
,net.dns3
inet.dns4
nie są już jest to zmiana, która zwiększa prywatność na platformie. -
Aby uzyskać informacje o sieci, takie jak serwery DNS, aplikacje z
ACCESS_NETWORK_STATE
może zarejestrowaćNetworkRequest
lubNetworkCallback
obiekt. Te klasy są dostępne w Androidzie 5.0 (poziom interfejsu API 21) i nowszych. -
Plik Build.SERIAL został wycofany.
Aplikacje, które muszą znać numer seryjny sprzętu, powinny
nowej metody
Build.getSerial()
, która wymaga parametruREAD_PHONE_STATE
uprawnienia. -
Interfejs API
LauncherApps
nie zezwala już na profil służbowy aby uzyskać informacje o profilu głównym. Gdy użytkownik jest w pracy profil, interfejs APILauncherApps
działa tak, jakby żadna aplikacja są zainstalowane w innych profilach w tej samej grupie profili. Tak jak wcześniej, próby uzyskania dostępu do niepowiązanych profili powodują wyjątek SecurityExceptions.
Uprawnienia
Przed Androidem 8.0 (poziom interfejsu API 26) jeśli aplikacja prosiła o uprawnienia w czasie działania aplikacji i przyznano odpowiednie uprawnienia, aplikacji otrzymały pozostałe uprawnienia należące do tego samego grupy uprawnień i zarejestrowanych w pliku manifestu.
W aplikacjach kierowanych na Androida 8.0 poprawiono. Aplikacja otrzymuje tylko te uprawnienia, które ma bezpośrednio poproszono o dostęp. Jeśli jednak użytkownik przyzna aplikacji uprawnienia, kolejne prośby o uprawnienia w tej grupie przyznanych automatycznie.
Załóżmy na przykład, że aplikacja zawiera zarówno READ_EXTERNAL_STORAGE
, jak i
WRITE_EXTERNAL_STORAGE
w pliku manifestu.
Aplikacja prosi o READ_EXTERNAL_STORAGE
i
przyznanych przez użytkownika. Jeśli aplikacja jest kierowana na interfejs API na poziomie 25 lub niższym, system też
przyznaje WRITE_EXTERNAL_STORAGE
w tym samym
ponieważ należy do tej samej grupy uprawnień STORAGE
oraz jest
zarejestrowanych w pliku manifestu. Jeśli aplikacja jest kierowana na Androida 8.0 (poziom interfejsu API 26), system przyznaje
w tym momencie tylko READ_EXTERNAL_STORAGE
;
jeśli jednak aplikacja zażąda później WRITE_EXTERNAL_STORAGE
, system natychmiast
przyznaje to uprawnienie bez pytania użytkownika o zgodę.
Multimedia
- Platforma może osiągnąć
automatyczne wyciszanie tła,
o samej treści. W tym przypadku, gdy inna aplikacja żąda koncentracji na
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
, aplikacja zmniejsza głośność, ale zwykle nie otrzymujeonAudioFocusChange()
oddzwanianie i nie utratą ostrości audio. Dostępne są nowe interfejsy API, które mogą zastąpić to zachowanie w przypadku które wymagają wstrzymywania zamiast ukrywania się. - Gdy użytkownik odbierze połączenie telefoniczne, aktywne strumienie multimediów zostaną wyciszone na czas .
- Wszystkie interfejsy API związane z dźwiękiem powinny używać protokołu
AudioAttributes
a nie typów strumieni audio. Nadal używaj typów strumieni audio wyłącznie do sterowania głośnością. Inne sposoby wykorzystania typów strumieni nadal działają (np. argumentstreamType
w wycofanymAudioTrack
), ale system rejestruje to jako błąd. - W przypadku korzystania z narzędzia
AudioTrack
, jeśli aplikacja żąda odpowiednio dużego bufora audio, jeśli będzie ona dostępna, spróbuje użyć danych wyjściowych z głębokiego bufora. - W Androidzie 8.0 (poziom interfejsu API 26) obsługa zdarzeń związanych z przyciskami multimediów wygląda inaczej:
- Obsługa przycisków multimediów w działaniu interfejsu użytkownika nie uległo zmianie: działania na pierwszym planie nadal mają priorytet podczas obsługi zdarzeń związanych z przyciskiem multimedialnym.
- Jeśli działanie na pierwszym planie nie obsługuje zdarzenia przycisku multimediów, system kieruje to zdarzenie. w aplikacji, która ostatnio odtwarzała dźwięk lokalnie. Stan aktywności, flagi i odtwarzanie stan sesji multimedialnej nie jest brany pod uwagę przy określaniu, która aplikacja otrzymuje multimedia zdarzenia przycisków.
- Jeśli sesja multimediów w aplikacji została opublikowana,
system wysyła zdarzenie przycisku multimediów do sekcji
MediaButtonReceiver
, jeśli ją ma. - W każdym innym przypadku system odrzuca zdarzenie związane z przyciskiem multimediów.
Biblioteki natywne
W aplikacjach kierowanych na Androida 8.0 (poziom interfejsu API 26) biblioteki natywne nie mogą być dłużej wczytywane, jeśli zawierają segmenty wczytywania, które są zarówno dostępne do zapisu, . Z powodu tej zmiany niektóre aplikacje mogą przestać działać, jeśli: biblioteki natywne z nieprawidłowymi segmentami wczytywania. To jest zabezpieczeń.
Więcej informacji można znaleźć w sekcji Segmenty możliwe do zapisu i wykonywalne.
Zmiany tagu łączącego są powiązane z poziomem interfejsu API, na który kierowana jest aplikacja. Jeśli to zmiana tagu łączącego docelowym poziomie interfejsu API, aplikacja nie może wczytać biblioteki. Jeśli kierujesz reklamy poziom interfejsu API niższy niż poziom interfejsu API, na którym następuje zmiana tagu łączącego; logcat wyświetla ostrzeżenie.
Obsługa odbioru
W Androidzie 8.0 (poziom API 26):
Metoda Collections.sort()
została wdrożona
od List.sort()
. Na odwrót
dotyczyło Androida 7.x (poziomy interfejsu API 24 i 25):
Domyślna implementacja interfejsu List.sort()
pod tytułem Collections.sort()
.
Ta zmiana zezwala na: Collections.sort()
aby korzystać ze zoptymalizowanej kategorii List.sort()
z implementacjami z tymi ograniczeniami:
Implementacje klucza
List.sort()
nie może wywoływać funkcjiCollections.sort()
, ponieważ spowodowałoby to przepełnienie stosu z powodu nieskończonej rekurencji. Jeśli chcesz, aby ustawienia domyślne w implementacjiList
, nie zastępujsort()
Jeśli klasa nadrzędna nieprawidłowo zaimplementuje funkcję
sort()
, to jest to zwykle wystarczy zastąpić wartośćList.sort()
dzięki implementacji opartej naList.toArray()
,Arrays.sort()
iListIterator.set()
. Na przykład:@Override public void sort(Comparator<? super E> c) { Object[] elements = toArray(); Arrays.sort(elements, c); ListIterator<E> iterator = (ListIterator<Object>) listIterator(); for (Object element : elements) { iterator.next(); iterator.set((E) element); } }
W większości przypadków możesz też zastąpić
List.sort()
z która deleguje różne ustawienia domyślne implementacji w zależności od poziomu interfejsu API. Na przykład:@Override public void sort(Comparator<? super E> comparator) { if (Build.VERSION.SDK_INT <= 25) { Collections.sort(this); } else { super.sort(comparator); } }
Jeśli korzystasz z drugiej strony tylko dlatego, że chcesz mieć
sort()
dostępnej na wszystkich poziomach interfejsu API, warto nadać jej unikalną nazwę, na przykładsortCompat()
, zamiast zastępowaniasort()
-
Collections.sort()
jest teraz liczone jako modyfikacji strukturalnej Wyświetl listę implementacji, które wywołująsort()
. Na przykład w wersjach z platformy sprzed Androida 8.0 (poziom interfejsu API 26)ArrayList
i dzwonię podsort()
w trakcie iteracji rzuciłbyConcurrentModificationException
czy sortowanie zostało wykonane, dzwoniąc pod numerList.sort()
.Collections.sort()
nie zgłosił wyjątku.Ta zmiana sprawi, że zachowanie platformy będzie bardziej spójne: daje teraz
ConcurrentModificationException
.
Sposób ładowania klas
Android 8.0 (poziom interfejsu API 26) sprawdza, czy moduły ładowania klas nie
narusza założenia dotyczące środowiska wykonawczego przy wczytywaniu nowych klas. Te weryfikacje są
jest wykonywana niezależnie od tego, czy klasa jest odwołuje się do języka Java (z
forName()
),
Kod bajtowy Dalvik lub JNI. Platforma nie przechwytuje bezpośrednich wywołań z Javy do
metody loadClass()
, która też nie jest sprawdzana.
wyniki takich rozmów. Takie zachowanie nie powinno wpływać na prawidłowe zachowanie
z programów ładujących klas.
Platforma sprawdza, czy deskryptor klasy zwracany przez program wczytujący klasy
pasuje do oczekiwanego deskryptora. Jeśli zwrócony deskryptor nie pasuje,
platforma zgłasza błąd NoClassDefFoundError
i zapisuje w
z wyjątkiem precyzyjnego komunikatu informującego o rozbieżności.
Platforma sprawdza też, czy deskryptory żądanych klas są prawidłowe. Ten
wykrywa wywołania JNI, które pośrednio ładują klasy, takie jak GetFieldID()
,
przekazywania nieprawidłowych deskryptorów do tych klas. np. pole z podpisem
Nie można znaleźć java/lang/String
, ponieważ podpis jest nieprawidłowy.
powinna być Ljava/lang/String;
.
Różni się od wywołania JNI do FindClass()
gdzie java/lang/String
jest prawidłową pełną nazwą.
Android 8.0 (poziom interfejsu API 26) nie obsługuje definiowania klas przez wiele modułów ładowania klas
za pomocą tego samego obiektu DexFile. Jeśli spróbujesz to zrobić, środowisko wykonawcze Androida zgłasza błąd
InternalError
z komunikatem „Próbuję zarejestrować plik .dex <filename>
z wieloma programami wczytującymi klasy”.
Interfejs DexFile API został wycofany, ale zdecydowanie zalecamy korzystanie z
jednym z programów uruchamiających klasy platformy, w tym PathClassLoader
lub
BaseDexClassLoader
.
Uwaga: możesz utworzyć wiele modułów ładowania klas, które odwołują się do
ten sam kontener plików APK lub JAR z systemu plików. Zazwyczaj nie zawsze
spowoduje duże obciążenie pamięci. Jeśli pliki DEX w kontenerze są przechowywane zamiast
skompresowane, platforma może wykonać na nich operację mmap
, a nie
ich bezpośrednie wyodrębnianie. Jeśli jednak platforma musi wyodrębnić plik DEX z kontenera,
odwoływanie się do pliku DEX może zużywać dużo pamięci.
W Androidzie wszystkie moduły ładowania klas są uważane za zdolne do równoległego wczytywania. Gdy wiele wątków próbuje wczytać tę samą klasę z tą samą klasą program uruchamiający, wygrywa pierwszy wątek, który ukończy operację, a wynik jest używany do w innych wątkach. Dzieje się tak niezależnie od tego, czy program wczytujący klasy zwrócił tę samą klasę, zwrócił inną klasę lub zgłosił wyjątek. Platforma dyskretnie ignoruje takie wyjątki.
Uwaga: w wersjach platformy niż w Androidzie 8.0 (poziom interfejsu API 26), naruszenie tych założeń może spowodować zdefiniowanie tej samej klasa wiele razy, uszkodzenie stosu z powodu pomylenia klas i inne niepożądane skutki.