Oprócz nowych funkcji i możliwości Android 7.0 wprowadza różne zmiany w działaniu systemu i interfejsu API. W tym dokumencie omawiamy niektóre kluczowe zmiany, które należy wziąć pod uwagę w swoich aplikacjach.
Jeśli opublikowałeś(-aś) już aplikację na Androida, pamiętaj, że te zmiany w systemie mogą na nią wpłynąć.
Bateria i pamięć
Android 7.0 zawiera zmiany zachowania systemu, które mają na celu wydłużenie czasu pracy baterii urządzenia i zmniejszenie wykorzystania pamięci RAM. Te zmiany mogą wpłynąć na dostęp aplikacji do zasobów systemowych oraz na sposób jej interakcji z innymi aplikacjami za pośrednictwem określonych intencji niejawnych.
Uśpienie
Wprowadzona w Androidzie 6.0 (poziom interfejsu API 23) funkcja Doze wydłuża czas pracy na baterii poprzez odkładanie na później działań procesora i działalności sieci, gdy urządzenie jest odłączone od zasilania, nieruchome i ma wyłączony ekran. Android 7.0 wprowadza dalsze udoskonalenia funkcji Doze, stosując podzbiór ograniczeń procesora i sieci, gdy urządzenie jest odłączone od zasilania, ma wyłączony ekran, ale niekoniecznie jest nieruchome, np. gdy telefon jest w kieszeni użytkownika.
Gdy urządzenie jest zasilane z baterii, a jego ekran był przez pewien czas wyłączony, urządzenie przejdzie w tryb uśpienia i zastosuje pierwszy podzbiór ograniczeń: wyłącza dostęp aplikacji do sieci oraz opóźnia zadania i synchronizacje. Jeśli po wejściu w tryb Doze urządzenie przez pewien czas pozostaje nieruchome, system stosuje pozostałe ograniczenia Doze do PowerManager.WakeLock
, AlarmManager
alarmów, GPS-a i skanowania sieci Wi-Fi. Niezależnie od tego, czy stosowane są niektóre czy wszystkie ograniczenia uśpienia, system wybudza urządzenie na krótkie okresy konserwacji, podczas których aplikacje mają dostęp do sieci i mogą wykonywać wszelkie odroczone zadania/synchronizacje.
Pamiętaj, że aktywowanie ekranu lub podłączenie urządzenia powoduje wyjście z Doze i zniesienie tych ograniczeń przetwarzania. Dodatkowe zachowanie nie ma wpływu na rekomendacje i najlepsze rozwiązania dotyczące dostosowywania aplikacji do wcześniejszej wersji Doze, która została wprowadzona w Androidzie 6.0 (poziom interfejsu API 23). Więcej informacji znajdziesz w artykule Optymalizacja pod kątem Doze i trybu wstrzymania aplikacji. Nadal musisz przestrzegać tych zaleceń, na przykład używać Komunikacji w chmurze Firebase (FCM) do wysyłania i odbierania wiadomości, a także zacząć planować aktualizacje, aby uwzględnić dodatkowe zachowanie Doze.
Projekt Svelte: optymalizacje w tle
Android 7.0 usuwa 3 domyślne transmisje, aby zoptymalizować wykorzystanie pamięci i zużycie energii. Ta zmiana jest konieczna, ponieważ transmisje niejawne często uruchamiają aplikacje, które zarejestrowały się jako odbiorcy w tle. Usunięcie tych transmisji może znacznie poprawić wydajność urządzenia i wygodę użytkowników.
Urządzenia mobilne często zmieniają połączenia, na przykład przełączając się z Wi-Fi na mobilną transmisję danych. Obecnie aplikacje mogą monitorować zmiany w łączności, rejestrując w pliku manifestu odbiornik niejawną transmisję CONNECTIVITY_ACTION
. Wiele aplikacji rejestruje się, by odbierać tę transmisję, dlatego jeden przełącznik sieci może wywołać je wszystkie jednocześnie.
Podobnie w poprzednich wersjach Androida aplikacje mogły rejestrować się do odbioru niejawnych transmisji ACTION_NEW_PICTURE
i ACTION_NEW_VIDEO
z innych aplikacji, takich jak Aparat. Gdy użytkownik zrobi zdjęcie za pomocą aplikacji Aparat, te aplikacje zostaną uruchomione, aby przetworzyć transmisję.
Aby rozwiązać te problemy, Android 7.0 wprowadza następujące optymalizacje:
- Aplikacje kierowane na Androida 7.0 (poziom interfejsu API 24) lub nowszego nie otrzymują transmisji
CONNECTIVITY_ACTION
, jeśli w manifeście deklarują odbiornik transmisji. Aplikacje nadal będą otrzymywać transmisjeCONNECTIVITY_ACTION
, jeśliBroadcastReceiver
zostanie zarejestrowany wContext.registerReceiver()
i jego kontekst nadal będzie prawidłowy. - System nie wysyła już transmisji
ACTION_NEW_PICTURE
aniACTION_NEW_VIDEO
. Ta optymalizacja dotyczy wszystkich aplikacji, a nie tylko tych kierowanych na Androida 7.0.
Jeśli Twoja aplikacja korzysta z któregokolwiek z tych intencjonalnych, jak najszybciej usuń ich zależności, aby móc prawidłowo kierować ją na urządzenia z Androidem 7.0.
Platforma Android oferuje kilka rozwiązań, które ograniczają potrzebę korzystania z tych domyślnych transmisji. Na przykład interfejs API JobScheduler
zapewnia solidny mechanizm do planowania operacji sieciowych, gdy spełnione są określone warunki, takie jak połączenie z nielimitowaną siecią. Możesz nawet używać JobScheduler
, aby reagować na zmiany w dostawcach treści.
Więcej informacji o optymalizacji w tle w Androidzie 7.0 (poziom interfejsu API 24) i o tym, jak dostosować aplikację, znajdziesz w artykule Optymalizacja działania w tle.
Zmiany uprawnień
Android 7.0 zawiera zmiany w uprawnieniach, które mogą mieć wpływ na Twoją aplikację.
Zmiany uprawnień systemu plików
Aby zwiększyć bezpieczeństwo plików prywatnych, katalog prywatny aplikacji kierowanych na Androida 7.0 lub nowszego ma dostęp ograniczony (0700
). To ustawienie zapobiega wyciekowi metadanych plików prywatnych, takich jak ich rozmiar lub istnienie. Ta zmiana uprawnień ma kilka efektów ubocznych:
-
Właściciel pliku nie powinien już zmniejszać uprawnień dotyczących plików prywatnych, a próba dodania ich za pomocą
MODE_WORLD_READABLE
lubMODE_WORLD_WRITEABLE
spowoduje wywołanieSecurityException
.Uwaga: to ograniczenie nie jest jeszcze w pełni egzekwowane. Aplikacje mogą nadal modyfikować uprawnienia do katalogu prywatnego przy użyciu natywnych interfejsów API lub interfejsu API
File
. Zdecydowanie odradzamy jednak zniesienie uprawnień do katalogu prywatnego. -
Przekazywanie identyfikatorów URI
file://
poza domenę pakietu może spowodować, że odbiorca otrzyma ścieżkę, do której nie będzie miał dostępu. W związku z tym próby przekazania aktywatora identyfikatora URIfile://
dla aktywatoraFileUriExposedException
. Zalecane jest udostępnianie treści pliku prywatnego za pomocą funkcjiFileProvider
. -
Użytkownicy
DownloadManager
nie mogą już udostępniać prywatnie plików przechowywanych na dysku współdzielonym według nazwy pliku. Starsze aplikacje mogą mieć niedostępną ścieżkę podczas próby uzyskania dostępu doCOLUMN_LOCAL_FILENAME
. Aplikacje kierowane na Androida 7.0 lub nowszego wywołująSecurityException
, gdy próbują uzyskać dostęp doCOLUMN_LOCAL_FILENAME
. Starsze aplikacje, które ustawiają lokalizację pobierania na publiczną za pomocąDownloadManager.Request.setDestinationInExternalFilesDir()
lubDownloadManager.Request.setDestinationInExternalPublicDir()
mogą nadal uzyskiwać dostęp do ścieżki wCOLUMN_LOCAL_FILENAME
. Nie zalecamy jednak używania tej metody. Preferowanym sposobem uzyskiwania dostępu do pliku udostępnianego przezDownloadManager
jest użycieContentResolver.openFileDescriptor()
.
Udostępnianie plików między aplikacjami
W przypadku aplikacji kierowanych na Androida 7.0 platforma Androida egzekwuje zasady interfejsu API StrictMode
, które zabraniają ujawniania identyfikatorów URI file://
poza aplikacją. Jeśli intencje zawierająca identyfikator URI pliku opuszcza aplikację, aplikacja nie działa z wyjątkiem FileUriExposedException
.
Aby udostępniać pliki między aplikacjami, wyślij identyfikator URI content://
i przyznaj tymczasowe uprawnienia dostępu do tego identyfikatora. Najprostszym sposobem na przyznanie tego uprawnienia jest użycie klasy FileProvider
. Więcej informacji o uprawnieniach i udostępnianiu plików znajdziesz w artykule Udostępnianie plików.
Udoskonalone ułatwienia dostępu
Android 7.0 zawiera zmiany mające na celu poprawę użyteczności platformy dla użytkowników ze słabym lub osłabionym wzrokiem. Zmiany te nie powinny wymagać wprowadzenia zmian w kodzie aplikacji, ale warto sprawdzić te funkcje i przetestować je w aplikacji, aby ocenić ich wpływ na wrażenia użytkowników.
Powiększenie ekranu
Android 7.0 umożliwia użytkownikom ustawianie rozmiaru wyświetlacza, który powiększa lub pomniejsza wszystkie elementy na ekranie, zwiększając w ten sposób ułatwienia dostępu dla osób niedowidzących. Użytkownicy nie mogą powiększać ekranu o minimalną szerokość sw320dp, czyli szerokość tabletu Nexus 4, typowej średniej wielkości telefonu.
Gdy gęstość urządzenia się zmienia, system powiadamia uruchomione aplikacje w następujące sposoby:
- Jeśli aplikacja jest kierowana na interfejs API na poziomie 23 lub niższym, system automatycznie zatrzymuje wszystkie jej procesy w tle. Oznacza to, że jeśli użytkownik przełączy się z tej aplikacji na ekran Ustawienia i zmieni ustawienie Rozmiar wyświetlacza, system zamknie aplikację w taki sam sposób, jak w sytuacji niskiej ilości pamięci. Jeśli aplikacja ma jakieś procesy na pierwszym planie, system powiadamia je o zmianie konfiguracji w sposób opisany w artykule Obsługa zmian w czasie wykonywania, tak jakby zmieniła się orientacja urządzenia.
- Jeśli aplikacja jest kierowana na Androida 7.0, wszystkie jej procesy (na pierwszym planie i w tle) są powiadamiane o zmianie konfiguracji zgodnie z opisem w sekcji Obsługa zmian w środowisku wykonawczym.
Większość aplikacji nie musi wprowadzać żadnych zmian, aby obsługiwać tę funkcję, o ile są zgodne ze sprawdzonymi metodami dotyczącymi Androida. Sprawdź te elementy:
- Przetestuj aplikację na urządzeniu o szerokości ekranu
sw320dp
, aby upewnić się, że działa wystarczająco dobrze. - Gdy konfiguracja urządzenia ulegnie zmianie, zaktualizuj wszystkie informacje w pamięci podręcznej zależne od gęstości, takie jak zapisane w pamięci podręcznej bitmapy lub zasoby wczytane z sieci. Sprawdź, czy konfiguracja uległa zmianie, gdy aplikacja wznowi działanie po przerwie.
Uwaga: jeśli dane zależne od konfiguracji są przechowywane w pamięci podręcznej, warto uwzględnić odpowiednie metadane, takie jak odpowiedni rozmiar ekranu lub gęstość pikseli. Zapisanie tych metadanych pozwala zdecydować, czy po zmianie konfiguracji trzeba odświeżyć dane w pamięci podręcznej.
- Unikaj podawania wymiarów w pikselach, ponieważ nie skalują się one do gęstości ekranu. Zamiast tego podaj wymiary w pikselach niezależnych od gęstości (
dp
).
Ustawienia dla niedowidzących w Kreatorze konfiguracji
Android 7.0 zawiera ustawienia dotyczące wzroku na ekranie powitalnym, na którym użytkownicy mogą skonfigurować te ustawienia ułatwień dostępu na nowym urządzeniu: gestyk powiększania, rozmiar czcionki, rozmiar wyświetlacza i TalkBack. Ta zmiana zwiększa widoczność błędów związanych z różnymi ustawieniami ekranu. Aby ocenić wpływ tej funkcji, przetestuj swoje aplikacje z włączonymi tymi ustawieniami. Odpowiednie ustawienia znajdziesz w sekcji Ustawienia > Ułatwienia dostępu.
Aplikacje NDK łączące się z bibliotekami platformy
Począwszy od Androida 7.0 system uniemożliwia aplikacjom dynamiczne łączenie się z bibliotekami innymi niż NDK, co może powodować awarie aplikacji. Ta zmiana zachowania ma na celu zapewnienie spójnego korzystania z aplikacji na różnych platformach i urządzeniach. Nawet jeśli Twój kod nie łączy się z bibliotekami prywatnymi, możliwe, że to zewnętrzna biblioteka statyczna w Twojej aplikacji. Dlatego wszyscy deweloperzy powinni się upewnić, że ich aplikacje nie ulegają awarii na urządzeniach z Androidem 7.0. Jeśli Twoja aplikacja używa kodu natywnego, powinna korzystać tylko z publicznych interfejsów NDK.
Aplikacja może próbować uzyskać dostęp do interfejsów API prywatnej platformy na 3 sposoby:
- Twoja aplikacja ma bezpośredni dostęp do prywatnych bibliotek platformy. Zaktualizuj aplikację, aby zawierała własną kopię tych bibliotek, lub użyj publicznych interfejsów API NDK.
- Twoja aplikacja korzysta z biblioteki innej firmy, która uzyskuje dostęp do prywatnych bibliotek platformy. Nawet jeśli masz pewność, że Twoja aplikacja nie ma bezpośredniego dostępu do bibliotek prywatnych, nadal musisz ją przetestować w tym scenariuszu.
- Aplikacja odwołuje się do biblioteki, która nie jest zawarta w pliku APK. Może się tak zdarzyć, jeśli spróbujesz użyć własnej kopii OpenSSL, ale zapomnisz ją umieścić w pliku APK aplikacji. Aplikacja może działać normalnie na platformach Androida obejmujących
libcrypto.so
. Może się jednak zdarzyć, że aplikacja ulegnie awarii w nowszych wersjach Androida, które nie zawierają tej biblioteki (na przykład na Androidzie 6.0 i nowszych). Aby to naprawić, upewnij się, że wszystkie biblioteki inne niż NDK są pogrupowane w pliku APK.
Aplikacje nie powinny używać bibliotek natywnych, które nie są zawarte w NDK, ponieważ mogą się zmieniać lub być usuwane w różnych wersjach Androida. Przykładem takiej zmiany jest przejście z OpenSSL na BoringSSL. Poza tym ze względu na to, że nie ma wymagań dotyczących zgodności dla bibliotek platformy nieuwzględnionych w NDK, różne urządzenia mogą oferować różne poziomy zgodności.
Aby ograniczyć wpływ tego ograniczenia na już opublikowane aplikacje, zestaw bibliotek, które są często używane, takich jak libandroid_runtime.so
, libcutils.so
, libcrypto.so
i libssl.so
, jest tymczasowo dostępny w Androidzie 7.0 (poziom API 24) w przypadku aplikacji kierowanych na poziom API 23 lub niższy. Jeśli aplikacja wczyta jedną z tych bibliotek, logcat wygeneruje ostrzeżenie, a na urządzeniu docelowym pojawi się powiadomienie. Jeśli zobaczysz te ostrzeżenia, zaktualizuj aplikację, aby zawierała własną kopię tych bibliotek lub używała tylko publicznych interfejsów API NDK. Przyszłe wersje platformy Android mogą całkowicie ograniczyć korzystanie z bibliotek prywatnych i spowodować awarię aplikacji.
Wszystkie aplikacje generują błąd czasu wykonywania, gdy wywołują interfejs API, który nie jest publiczny ani tymczasowo dostępny. Skutkiem jest to, że
System.loadLibrary
i dlopen(3)
zwracają
NULL
, co może spowodować awarię aplikacji. Sprawdź kod aplikacji, aby usunąć odwołania do prywatnych interfejsów API platformy, i gruntownie przetestuj aplikacje na urządzeniu lub w emulatorze z Androidem 7.0 (poziom interfejsu API 24). Jeśli nie masz pewności, czy Twoja aplikacja używa bibliotek prywatnych, możesz sprawdzić logcat, aby zidentyfikować błąd środowiska wykonawczego.
W tabeli poniżej opisujemy, jakie zachowanie aplikacji możesz zaobserwować w zależności od wykorzystania w niej prywatnych bibliotek natywnych i docelowego poziomu interfejsu API (android:targetSdkVersion
).
Biblioteki | Docelowy poziom interfejsu API | Dostęp w czasie wykonywania za pomocą linkera dynamicznego | Działanie Androida 7.0 (poziom interfejsu API 24) | Przyszłe zachowanie platformy Android |
---|---|---|---|---|
NDK Public | Dowolny | Ułatwienia dostępu | Działa zgodnie z oczekiwaniami | Działa zgodnie z oczekiwaniami |
Prywatne (tymczasowo dostępne biblioteki prywatne) | 23 lub mniej | Tymczasowo dostępne | Działa zgodnie z oczekiwaniami, ale pojawia się ostrzeżenie w logcat. | Błąd środowiska wykonawczego |
Prywatne (tymczasowo dostępne prywatne biblioteki) | 24 lub więcej | Z ograniczonym dostępem | Błąd środowiska wykonawczego | Błąd środowiska wykonawczego |
Prywatny (inne) | Dowolny | Z ograniczonym dostępem | Błąd środowiska wykonawczego | Błąd środowiska wykonawczego |
Sprawdź, czy Twoja aplikacja korzysta z bibliotek prywatnych
Aby ułatwić wykrywanie problemów z wczytywaniem bibliotek prywatnych, logcat może wygenerować ostrzeżenie lub błąd środowiska wykonawczego. Jeśli na przykład Twoja aplikacja jest kierowana na poziom interfejsu API 23 lub niższego i próbuje uzyskać dostęp do prywatnej biblioteki na urządzeniu z Androidem 7.0, może wyświetlić się ostrzeżenie podobne do tego:
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so" ("/system/lib/libandroid_runtime.so") needed or dlopened by "/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible for the namespace "classloader-namespace" - the access is temporarily granted as a workaround for http://b/26394120
Te ostrzeżenia logcat informują, która biblioteka próbuje uzyskać dostęp do interfejsu API prywatnej platformy, ale nie spowoduje awarii aplikacji. Jeśli aplikacja jest kierowana na interfejs API na poziomie 24 lub wyższym, logcat generuje ten błąd czasu wykonywania, a aplikacja może się zawiesić:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so" ("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace" at java.lang.Runtime.loadLibrary0(Runtime.java:977) at java.lang.System.loadLibrary(System.java:1602)
Możesz też zobaczyć te dane wyjściowe logcat, jeśli Twoja aplikacja korzysta z bibliotek innych firm, które dynamicznie łączą się z prywatnymi interfejsami API platformy. Narzędzie readelf w Androidzie 7.0DK umożliwia wygenerowanie listy wszystkich dynamicznie powiązanych bibliotek współdzielonych danego pliku .so
. Aby to zrobić, uruchom to polecenie:
aarch64-linux-android-readelf -dW libMyLibrary.so
Zaktualizuj aplikację
Oto kilka czynności, które możesz wykonać, aby naprawić tego typu błędy i upewnić się, że aplikacja nie ulegnie awarii podczas przyszłych aktualizacji platformy:
- Jeśli Twoja aplikacja korzysta z prywatnych bibliotek platformy, zaktualizuj ją, aby zawierała własną kopię tych bibliotek, lub użyj publicznych interfejsów NDK API.
- Jeśli Twoja aplikacja korzysta z biblioteki innej firmy, która ma dostęp do symboli prywatnych, skontaktuj się z jej autorem, aby ją zaktualizować.
- Upewnij się, że wszystkie biblioteki inne niż NDK są spakowane w pliku APK.
- Użyj standardowych funkcji JNI zamiast
getJavaVM
igetJNIEnv
zlibandroid_runtime.so
:AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or JavaVM::AttachCurrentThread from <jni.h>.
- Zamiast prywatnego symbolu
property_get
zlibcutils.so
użyj symbolu__system_property_get
. Aby to zrobić, użyj właściwości__system_property_get
z tymi elementami:#include <sys/system_properties.h>
Uwaga: dostępność i zawartość właściwości systemowych nie są testowane w CTS. Lepszym rozwiązaniem jest całkowite unikanie stosowania tych właściwości.
- Użyj lokalnej wersji symbolu
SSL_ctrl
z poziomulibcrypto.so
. Na przykład w pliku.so
musisz utworzyć statyczny link do bibliotekilibcyrpto.a
lub dołączyć dynamicznie połączoną wersję bibliotekilibcrypto.so
z BoringSSL/OpenSSL i zapakować ją w pliku APK.
Android for Work
Android 7.0 zawiera zmiany w aplikacji na Androida dla firm, w tym zmiany w instalacji certyfikatów, resetowaniu hasła, zarządzaniu dodatkowym użytkownikiem i dostępie do identyfikatorów urządzenia. Jeśli tworzysz aplikacje dla środowisk Android for Work, sprawdź te zmiany i odpowiednio zmodyfikuj aplikację.
- Musisz zainstalować delegowany instalator certyfikatów, zanim DPC będzie mógł go ustawić. W przypadku aplikacji do zarządzania profilem i aplikacji właściciela urządzenia kierowanych na Androida 7.0 (poziom interfejsu API 24) przed wywołaniem przez kontrolera zasad dotyczących urządzeń (DPC) należy zainstalować delegowany instalator certyfikatu.
DevicePolicyManager.setCertInstallerPackage()
Jeśli instalator nie jest jeszcze zainstalowany, systemIllegalArgumentException
. - Ograniczenia resetowania hasła dla administratorów urządzeń dotyczą teraz również właścicieli profili. Administratorzy urządzeń nie mogą już używać opcji
DevicePolicyManager.resetPassword()
, aby usunąć hasła lub zmienić te, które są już ustawione. Administratorzy urządzeń nadal mogą ustawić hasło, ale tylko wtedy, gdy na urządzeniu nie ma hasła, kodu PIN ani wzoru. - Właściciele urządzeń i profili mogą zarządzać kontami nawet wtedy, gdy są ustawione ograniczenia. Właściciele urządzeń i właściciele profili mogą wywoływać interfejsy Account Management API, nawet jeśli obowiązują ograniczenia dotyczące użytkowników
DISALLOW_MODIFY_ACCOUNTS
. - Właściciele urządzeń mogą łatwiej zarządzać dodatkowymi użytkownikami. Gdy urządzenie działa w trybie właściciela urządzenia, ograniczenie
DISALLOW_ADD_USER
jest automatycznie ustawiane. Zapobiega to tworzeniu przez użytkowników niezarządzanych kont dodatkowych. Ponadto metodyCreateUser()
icreateAndInitializeUser()
są wycofane; zastępuje je nowa metodaDevicePolicyManager.createAndManageUser()
. - Właściciele urządzeń mają dostęp do ich identyfikatorów. Właściciel urządzenia może uzyskać dostęp do adresu MAC karty Wi-Fi urządzenia za pomocą
DevicePolicyManager.getWifiMacAddress()
. Jeśli sieć Wi-Fi nie została nigdy włączona na urządzeniu, ta metoda zwraca wartośćnull
. - Ustawienie Tryb pracy kontroluje dostęp do aplikacji służbowych. Gdy tryb pracy jest wyłączony, program uruchamiający system sygnalizuje, że aplikacje służbowe są niedostępne, wyświetlając je w szarym kolorze. Ponowne włączenie trybu pracy przywróci normalne działanie.
- Podczas instalowania pliku PKCS #12 zawierającego łańcuch certyfikatów klienta i odpowiadający mu klucz prywatny z poziomu interfejsu ustawień certyfikat CA w łańcuchu nie jest już instalowany w magazynie z zaufanymi poświadczeniami. Nie ma to wpływu na wynik funkcji
KeyChain.getCertificateChain()
, gdy aplikacje próbują później pobrać łańcuch certyfikatów klienta. W razie potrzeby certyfikat CA należy zainstalować w magazynie zaufanych danych logowania za pomocą interfejsu ustawień, oddzielnie, w formacie DER z rozszerzeniem pliku .crt lub .cer. - Od Androida 7.0 rejestracja i przechowywanie odcisków palców są zarządzane na poziomie użytkownika. Jeśli klient zasad urządzenia (DPC) właściciela profilu jest przeznaczony dla poziomu interfejsu API 23 (lub niższego) na urządzeniu z Androidem 7.0 (poziom interfejsu API 24), użytkownik nadal może ustawić odcisk palca na urządzeniu, ale aplikacje służbowe nie będą mieć dostępu do odcisku palca. Jeśli DPC jest kierowany na poziom interfejsu API 24 lub nowszy, użytkownik może ustawić odcisk palca specjalnie dla profilu służbowego, klikając Ustawienia > Bezpieczeństwo > Bezpieczeństwo profilu służbowego.
- Nowy stan szyfrowania
ENCRYPTION_STATUS_ACTIVE_PER_USER
jest zwracany przezDevicePolicyManager.getStorageEncryptionStatus()
, aby wskazać, że szyfrowanie jest aktywne, a klucz szyfrowania jest powiązany z użytkownikiem. Nowy stan jest zwracany tylko wtedy, gdy DPC jest kierowany na interfejs API na poziomie 24 lub wyższym. W przypadku aplikacji kierowanych na starsze poziomy interfejsu API zwracany jest kluczENCRYPTION_STATUS_ACTIVE
, nawet jeśli klucz szyfrowania jest specyficzny dla użytkownika lub profilu. - W Androidzie 7.0 kilka metod, które normalnie wpływają na całe urządzenie, działa inaczej, gdy na urządzeniu jest zainstalowany profil służbowy z osobnym testem zabezpieczającym. Te metody dotyczą tylko profilu służbowego, a nie całego urządzenia. (Pełna lista takich metod znajduje się w dokumentacji
DevicePolicyManager.getParentProfileInstance()
). Na przykład:DevicePolicyManager.lockNow()
blokuje tylko profil służbowy, zamiast blokować całe urządzenie. W przypadku każdej z tych metod możesz uzyskać stare zachowanie, wywołując metodę w nadrzędnim wystąpieniu klasyDevicePolicyManager
; możesz uzyskać ten nadrzędny element, wywołując metodęDevicePolicyManager.getParentProfileInstance()
. Jeśli na przykład wywołasz metodęlockNow()
instancji nadrzędnej, całe urządzenie zostaje zablokowane.
Przechowywanie adnotacji
W Androidzie 7.0 naprawiliśmy błąd, który powodował ignorowanie widoczności adnotacji. Ten problem umożliwiał środowisku uruchomieniowemu dostęp do adnotacji, do których nie powinno mieć dostępu. Te adnotacje obejmowały:
VISIBILITY_BUILD
: ma być widoczny tylko w czasie kompilacji.VISIBILITY_SYSTEM
: ma być widoczny w czasie wykonywania, ale tylko dla systemu podstawowego.
Jeśli Twoja aplikacja korzysta z tego zachowania, dodaj zasady przechowywania do adnotacji, które muszą być dostępne w czasie wykonywania. Możesz to zrobić za pomocą @Retention(RetentionPolicy.RUNTIME)
.
Zmiany domyślnej konfiguracji TLS/SSL
Android 7.0 wprowadza następujące zmiany w domyślnej konfiguracji TLS/SSL używanej przez aplikacje do obsługi HTTPS i innego ruchu TLS/SSL:
- Zestawy szyfrów RC4 są teraz wyłączone.
- Zestawy szyfrów CHACHA20-POLY1305 są teraz włączone.
Wyłączenie domyślnie mechanizmu szyfrowania RC4 może powodować przerwy w połączeniach HTTPS lub TLS/SSL, gdy serwer nie negocjuje nowoczesnych zestawów szyfrów. Preferowaną rozwiązaniem jest ulepszenie konfiguracji serwera, aby uzyskać dostęp do silniejszych i bardziej nowoczesnych zestawów szyfrów i protokołów. W idealnej sytuacji należy włączyć TLS 1.2 i AES-GCM oraz preferować i włączać zestawy szyfrów oparte na szyfrowaniu z zachowaniem tajemnicy (ECDHE).
Możesz też zmodyfikować aplikację, aby używała niestandardowego SSLSocketFactory
do komunikacji z serwerem. Fabryka powinna być zaprojektowana tak, aby tworzyć instancje SSLSocket
, w których oprócz domyślnych zestawów szyfrów włączone są niektóre z zestawów szyfrów wymaganych przez serwer.
Uwaga: te zmiany nie dotyczą usługi WebView
.
Aplikacje kierowane na Androida 7.0
Te zmiany zachowania dotyczą wyłącznie aplikacji kierowanych na Androida 7.0 (poziom interfejsu API 24) lub nowszego. Aplikacje skompilowane pod kątem Androida 7.0 lub z ustawieniami targetSdkVersion
Androida 7.0 lub nowszego muszą zostać zmodyfikowane, aby prawidłowo obsługiwać te zachowania (w odpowiednich przypadkach).
Zmiany w serializacji
W Androidzie 7.0 (poziom interfejsu API 24) naprawiliśmy błąd w obliczaniu domyślnej wartości serialVersionUID, przez co nie była ona zgodna ze specyfikacją.
Klasy, które implementują interfejs Serializable
i nie określają wyraźnego pola serialVersionUID
, mogą mieć zmieniony domyślny identyfikator serialVersionUID, co spowoduje wyjątek podczas próby deserializacji instancji klasy, które zostały zaserializowane w wcześniejszej wersji lub za pomocą aplikacji kierowanej na wcześniejszą wersję. Komunikat o błędzie będzie wyglądał mniej więcej tak:
local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567
Rozwiązanie tych problemów wymaga dodania pola serialVersionUID
do każdej klasy, której dotyczy problem, z wartością stream classdesc
serialVersionUID
z komunikatu o błędzie (w tym przypadku 1234
). Ta zmiana jest zgodna ze wszystkimi zaleceniami dotyczącymi tworzenia kodu serializacji i działa we wszystkich wersjach Androida.
Naprawiony błąd dotyczył obecności statycznych metod inicjalizujących, np. <clinit>
. Zgodnie ze specyfikacją obecność lub brak metody stałego inicjalizowania w klasie wpłynie na domyślną wartość serialVersionUID obliczoną dla tej klasy.
Przed naprawieniem błędu obliczenia sprawdzały też, czy superklasa zawiera statyczny inicjalizator, jeśli klasa nie miała takiego.
Zmiana ta nie ma wpływu na aplikacje kierowane na interfejs API na poziomie 23 lub niższym, klasach zawierających pole serialVersionUID
ani klas zawierających metodę inicjowania statycznego.
Inne ważne informacje
- Gdy aplikacja działa na Androidzie 7.0, ale jest kierowana na niższy poziom interfejsu API, a użytkownik zmieni rozmiar wyświetlacza, proces aplikacji zostanie zatrzymany. Aplikacja musi być w stanie prawidłowo obsłużyć ten scenariusz. W przeciwnym razie aplikacja ulegnie awarii, gdy użytkownik przywróci ją z listy Ostatnie.
Przetestuj aplikację, aby upewnić się, że nie będzie ona tak działać. Możesz to zrobić, wywołując identyczne awarie, gdy ręcznie zabijasz aplikację za pomocą DDMS.
Aplikacje kierowane na Androida 7.0 (poziom interfejsu API 24) lub nowszego nie są automatycznie usuwane po zmianie gęstości, ale nadal mogą słabo reagować na zmiany w konfiguracji.
- Aplikacje na Androidzie 7.0 powinny płynnie obsługiwać zmiany konfiguracji i nie powinny ulegać awarii przy kolejnych uruchomieniach. Aby sprawdzić działanie aplikacji, zmień rozmiar czcionki (Ustawienia > Wyświetlacz > Rozmiar czcionki), a następnie przywróć aplikację z Ostatnich.
-
Z powodu błędu w poprzednich wersjach Androida system nie oznaczał zapisu do gniazda TCP na wątku głównym jako naruszenia trybu rygorystycznego. Ten błąd został naprawiony w Androidzie 7.0.
Aplikacje, które wykazują takie zachowanie,
android.os.NetworkOnMainThreadException
. Ogólnie wykonywanie operacji sieciowych w wątku głównym nie jest dobrym pomysłem, ponieważ wiąże się to z dużym opóźnieniem, które powoduje błędy ANR i zacinanie. -
Rodzina metod
Debug.startMethodTracing()
domyślnie przechowuje dane wyjściowe w katalogu pakietu w wspólnej pamięci masowej, a nie na najwyższym poziomie karty SD. Oznacza to, że aplikacje nie muszą już prosić o uprawnienieWRITE_EXTERNAL_STORAGE
, aby korzystać z tych interfejsów API. -
Wiele interfejsów API platform zaczęło sprawdzać, czy w ramach transakcji
Binder
nie są wysyłane duże ładunki. System zamiast milcząco rejestrować te ładunki lub pomijać je, zwraca teraz błądTransactionTooLargeExceptions
jakoRuntimeExceptions
. Typowym przykładem jest przechowywanie zbyt wielu danych wActivity.onSaveInstanceState()
, co powoduje, żeActivityThread.StopInfo
zgłasza błądRuntimeException
, gdy aplikacja jest kierowana na Androida 7.0. -
Jeśli aplikacja publikuje zadania
Runnable
w usługachView
, a usługaView
nie jest przypisana do okna, system umieszcza zadanieRunnable
w kolejce z zadaniemView
. ZadanieRunnable
nie jest wykonywane, dopóki usługaView
nie zostanie przypisana do okna. Dzięki temu rozwiązano te błędy: -
Jeśli aplikacja na Androidzie 7.0 z uprawnieniami
DELETE_PACKAGES
próbuje usunąć pakiet, ale został on zainstalowany przez inną aplikację, system wymaga potwierdzenia użytkownika. W takim przypadku aplikacje powinny oczekiwać wartościSTATUS_PENDING_USER_ACTION
jako stanu zwracanego, gdy wywołują funkcjęPackageInstaller.uninstall()
. - Dostawca JCA o nazwie Crypto został wycofany, ponieważ jego jedyny algorytm, SHA1PRNG, jest słaby pod względem kryptograficznym. Aplikacje nie mogą już używać funkcji SHA1PRNG do (niebezpiecznego) wyprowadzania kluczy, ponieważ dostawca tej funkcji nie jest już dostępny. Więcej informacji znajdziesz w poście na blogu Usługa bezpieczeństwa „Crypto” nie jest już obsługiwana na Androidzie N.