Podobnie jak w poprzednich wersjach, Android 15 zawiera zmiany w działaniu, które mogą mieć do aplikacji. Opisane poniżej zmiany w działaniu dotyczą tylko aplikacji, które: na Androida 15 lub nowszego. Jeśli aplikacja jest kierowana na Androida 15 lub nowszego, należy zmodyfikować aplikację, aby obsługiwała te zachowania. mają zastosowanie.
Zapoznaj się też z listą zmian w działaniu, które mają wpływ na wszystkie aplikacje
z Androidem 15 niezależnie od tego, jaki masz targetSdkVersion
w aplikacji.
Główna funkcja
Android 15 zmienia lub rozszerza różne podstawowe funkcje systemu Android.
Zmiany w usługach na pierwszym planie
Wprowadzamy te zmiany w usługach działających na pierwszym planie w Androidzie 15.
- Zachowanie limitu czasu oczekiwania usługi działającej na pierwszym planie w ramach synchronizacji danych
- Nowy typ usługi na pierwszym planie do przetwarzania multimediów
- Ograniczenia dotyczące
BOOT_COMPLETED
odbiorników uruchamiających usługi na pierwszym planie - Ograniczenia uruchamiania usług na pierwszym planie, gdy aplikacja ma uprawnienie
SYSTEM_ALERT_WINDOW
Zachowanie limitu czasu oczekiwania usługi działającej na pierwszym planie w ramach synchronizacji danych
Android 15 wprowadza nowy limit czasu oczekiwania w dataSync
w przypadku kierowania na aplikacje
Android 15 (poziom interfejsu API 35) lub nowszy. Odnosi się to również do nowych funkcji
Typ usługi na pierwszym planie: mediaProcessing
.
System pozwala na działanie usług aplikacji dataSync
przez łącznie 6 godzin
w ciągu 24 godzin, po czym system wywołuje metodę
Metoda Service.onTimeout(int, int)
(wprowadzona w Androidzie)
15) W tej chwili usługa ma kilka sekund na nawiązanie połączenia
Service.stopSelf()
W przypadku wywołania funkcji Service.onTimeout()
makro
usługa nie jest już uznawana za usługę na pierwszym planie. Jeśli usługa nie
wywoła Service.stopSelf()
, system zgłosi wyjątek wewnętrzny.
jest rejestrowany w Logcat z następującym komunikatem:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"
Aby uniknąć problemów związanych ze zmianą działania, możesz wykonać co najmniej jedną z :
- Pozwól usłudze wdrożyć nową metodę
Service.onTimeout(int, int)
. Gdy Twoja aplikacja otrzyma wywołanie zwrotne, wywołajstopSelf()
w za kilka sekund. (Jeśli nie zatrzymasz aplikacji od razu, system wygeneruje komunikat niepowodzenie). - Upewnij się, że usługi
dataSync
w Twojej aplikacji nie działają przez więcej niż 6 godzin w dowolnym okresie 24 godzin (chyba że użytkownik wejdzie w interakcję z aplikacją, resetowanie minutnika). - Uruchamiaj tylko usługi na pierwszym planie (
dataSync
) w wyniku bezpośredniego działania użytkownika interakcja; ponieważ aplikacja działa na pierwszym planie w momencie uruchomienia usługi, możesz korzystać z usługi przez pełne 6 godzin od momentu, gdy aplikacja działała w tle. - Zamiast usługi na pierwszym planie
dataSync
użyj alternative API.
Jeśli usługi na pierwszym planie w Twojej aplikacji (dataSync
) działały przez 6 godzin w ciągu ostatnich 6 godzin
24, nie możesz uruchomić innej usługi na pierwszym planie dataSync
, chyba że użytkownik
przeniosła aplikację na pierwszy plan (co powoduje zresetowanie licznika). Jeśli spróbujesz
uruchomienia innej usługi na pierwszym planie dataSync
, system zgłasza
ForegroundServiceStartNotAllowedException
.
z komunikatem o błędzie, np. „Limit czasu dla usługi na pierwszym planie został już wyczerpany
wpisz dataSync”.
Testowanie
Aby przetestować działanie aplikacji, możesz włączyć czasy oczekiwania na synchronizację danych, nawet jeśli aplikacja
nie jest kierowana na Androida 15 (o ile aplikacja działa na Androidzie 15),
urządzenia). Aby włączyć limity czasu, uruchom to polecenie adb
:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
Możesz też dostosować ten czas, aby łatwiej sprawdzić,
działa po osiągnięciu limitu. Aby ustawić nowy limit czasu, uruchom
to polecenie adb
:
adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds
Nowy typ usługi na pierwszym planie przetwarzania multimediów
W Androidzie 15 wprowadziliśmy nowy typ usługi na pierwszym planie: mediaProcessing
. Ten
jest odpowiedni do operacji takich jak transkodowanie plików multimedialnych. Dla:
np. aplikacja do multimediów może pobrać plik audio i przekonwertować go
przed odtworzeniem materiału w innym formacie. Możesz użyć elementu mediaProcessing
na pierwszym planie
by zapewnić ciągłość konwersji nawet wtedy, gdy aplikacja jest
w tle.
System zezwala na działanie usług aplikacji mediaProcessing
przez łącznie 6
godz. w okresie 24-godzinnym, po czym system wywołuje metodę
Metoda Service.onTimeout(int, int)
(wprowadzona w Androidzie)
15) W tej chwili usługa ma kilka sekund na nawiązanie połączenia
Service.stopSelf()
Jeśli usługa nie
wywoła Service.stopSelf()
, system zgłosi wyjątek wewnętrzny.
jest rejestrowany w Logcat z następującym komunikatem:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"
Aby uniknąć wyjątku, wykonaj jedną z tych czynności:
- Pozwól usłudze wdrożyć nową metodę
Service.onTimeout(int, int)
. Gdy Twoja aplikacja otrzyma wywołanie zwrotne, wywołajstopSelf()
w za kilka sekund. (Jeśli nie zatrzymasz aplikacji od razu, system wygeneruje komunikat niepowodzenie). - Upewnij się, że usługi
mediaProcessing
w Twojej aplikacji nie działają dłużej niż łącznie 6 godzin w dowolnym okresie 24 godzin (chyba że użytkownik wejdzie w interakcję z aplikacją, resetowanie minutnika). - Uruchamiaj tylko usługi na pierwszym planie (
mediaProcessing
) w wyniku bezpośredniego działania użytkownika interakcja; ponieważ aplikacja działa na pierwszym planie w momencie uruchomienia usługi, możesz korzystać z usługi przez pełne 6 godzin od momentu, gdy aplikacja działała w tle. - Zamiast usługi na pierwszym planie
mediaProcessing
użyj alternatywnej metody API, na przykład WorkManager.
Jeśli usługi na pierwszym planie typu mediaProcessing
w Twojej aplikacji były uruchomione przez 6 godzin w
ostatnich 24, nie możesz uruchomić innej usługi na pierwszym planie mediaProcessing
, chyba że
użytkownik przeniósł aplikację na pierwszy plan (co powoduje zresetowanie licznika). Jeśli
próbuje uruchomić inną usługę na pierwszym planie mediaProcessing
, system zgłasza
ForegroundServiceStartNotAllowedException
.
z komunikatem o błędzie, np. „Limit czasu dla usługi na pierwszym planie został już wyczerpany
type MediaProcessing”.
Więcej informacji o typie usługi mediaProcessing
znajdziesz w artykule Zmiany w
Typy usług działających na pierwszym planie w Androidzie 15: przetwarzanie multimediów.
Testowanie
Aby przetestować działanie aplikacji, możesz włączyć limity czasu przetwarzania multimediów, nawet jeśli
aplikacja nie jest kierowana na Androida 15 (o ile działa na
na urządzeniu z Androidem 15). Aby włączyć limity czasu, uruchom to polecenie adb
:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
Możesz też dostosować ten czas, aby łatwiej sprawdzić,
działa po osiągnięciu limitu. Aby ustawić nowy limit czasu, uruchom
to polecenie adb
:
adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds
Ograniczenia dotyczące BOOT_COMPLETED
odbiorników uruchamiających usługi na pierwszym planie
Wprowadziliśmy nowe ograniczenia dotyczące odbiorników BOOT_COMPLETED
usług działających na pierwszym planie. Odbiorcy BOOT_COMPLETED
nie mogą uruchamiać modułu
te typy usług na pierwszym planie:
dataSync
camera
mediaPlayback
phoneCall
mediaProjection
microphone
(to ograniczenie obowiązuje w przypadkumicrophone
od Androida 14)
Jeśli odbiornik BOOT_COMPLETED
próbuje uruchomić którykolwiek z tych typów działania na pierwszym planie
usług, system wywołuje ForegroundServiceStartNotAllowedException
.
Testowanie
Aby przetestować działanie aplikacji, możesz włączyć te nowe ograniczenia, nawet jeśli aplikacja nie jest kierowana na Androida 15 (o ile jest ona uruchomiona na urządzeniu z Androidem 15). Uruchom to polecenie adb
:
adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name
Aby wysłać komunikat typu BOOT_COMPLETED
bez ponownego uruchamiania urządzenia:
uruchom to polecenie adb
:
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name
Ograniczenia dotyczące uruchamiania usług na pierwszym planie, gdy aplikacja ma uprawnienie SYSTEM_ALERT_WINDOW
Wcześniej, jeśli jakaś aplikacja miała uprawnienie SYSTEM_ALERT_WINDOW
, można było ją uruchomić.
z usługi na pierwszym planie, nawet jeśli aplikacja działała obecnie w tle (jak
omawiane w artykule wykluczenia z ograniczeń uruchamiania w tle).
Jeśli aplikacja jest kierowana na Androida 15, wykluczenie jest teraz bardziej precyzyjne. Aplikacja wymaga teraz
mieć uprawnienia SYSTEM_ALERT_WINDOW
oraz także mieć widoczną nakładkę
okno. Oznacza to, że aplikacja musi najpierw uruchomić
Okno TYPE_APPLICATION_OVERLAY
i okno
musi być widoczna przed uruchomieniem usługi na pierwszym planie.
Jeśli aplikacja próbuje uruchomić usługę działającej na pierwszym planie w tle bez
spełnia te nowe wymagania (i nie jest objęty żadnym innym wyjątkiem),
system zgłasza ForegroundServiceStartNotAllowedException
.
Jeśli Twoja aplikacja deklaruje uprawnienia SYSTEM_ALERT_WINDOW
i uruchamia usługi na pierwszym planie w tle, może to mieć wpływ
. Jeśli Twoja aplikacja otrzymuje ForegroundServiceStartNotAllowedException
, sprawdź,
kolejność działania aplikacji i upewnij się, że ma ona już aktywną
przed próbą uruchomienia usługi na pierwszym planie z poziomu
w tle. Możesz sprawdzić, czy okno nakładki jest obecnie widoczne
, dzwoniąc pod numer View.getWindowVisibility()
, lub
może zastąpić wartość View.onWindowVisibilityChanged()
aby otrzymywać powiadomienia o zmianach widoczności.
Testowanie
Aby przetestować działanie aplikacji, możesz włączyć nowe ograniczenia, nawet jeśli
aplikacja nie jest kierowana na Androida 15 (o ile działa na Androidzie 15),
urządzenia). Aby włączyć nowe ograniczenia dotyczące uruchamiania usług na pierwszym planie
w tle uruchom to polecenie adb
:
adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name
Zmiany dotyczące tego, kiedy aplikacje mogą modyfikować globalny stan trybu Nie przeszkadzać
Aplikacje kierowane na Androida 15 nie mogą już zmieniać globalnego stanu ani zasad trybu Nie przeszkadzać na urządzeniu (przez zmianę ustawień użytkownika lub wyłączenie trybu Nie przeszkadzać). Zamiast tego aplikacje muszą przekazywać element AutomaticZenRule
, który system łączy w globalną zasadę z dotychczasowym schematem wygrywania zasad o największym ograniczeniu. Wywołania istniejących interfejsów API, które wcześniej wpływały na stan globalny (setInterruptionFilter
, setNotificationPolicy
), skutkują utworzeniem lub zaktualizowaniem niejawnej klasy AutomaticZenRule
, która jest włączana i wyłączana w zależności od cyklu wywołań tych wywołań interfejsu API.
Pamiętaj, że ta zmiana wpływa na obserwowalne zachowanie tylko wtedy, gdy aplikacja wywołuje metodę setInterruptionFilter(INTERRUPTION_FILTER_ALL)
i oczekuje, że wywołanie dezaktywacji AutomaticZenRule
, która została wcześniej aktywowana przez ich właścicieli.
Zmiany w interfejsie OpenJDK API
Android 15 kontynuuje pracę nad odświeżaniem podstawowych bibliotek Androida, aby zapewnić zgodność z funkcjami dostępnymi w najnowszych wersjach OpenJDK LTS.
Niektóre z tych zmian mogą wpłynąć na zgodność aplikacji w kierowaniu na aplikacje Android 15 (poziom API 35):
Zmiany w interfejsach API formatowania ciągów znaków: weryfikacja indeksu argumentu, flag, szerokość i precyzja są teraz bardziej rygorystyczne przy korzystaniu z funkcji Interfejsy API
String.format()
iFormatter.format()
:String.format(String, Object[])
String.format(Locale, String, Object[])
Formatter.format(String, Object[])
Formatter.format(Locale, String, Object[])
Na przykład następujący wyjątek jest zgłaszany, gdy indeks argumentów wynosi 0 (
%0
w ciągu formatu):IllegalFormatArgumentIndexException: Illegal format argument index = 0
W tym przypadku problem można rozwiązać, stosując indeks argumentów równy 1 (
%1
w ciągu formatu).Zmiany w typie komponentu
Arrays.asList(...).toArray()
: podczas używania funkcjiArrays.asList(...).toArray()
, typ komponentu tablicy wynikowej to jest to terazObject
, a nie typ elementów tablicy bazowej. Dlatego ten kod zwracaClassCastException
:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
Aby w tym przypadku zachować
String
jako typ komponentu w wyniku tablica, możesz zamiast tego użyćCollection.toArray(Object[])
:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
Zmiany w obsłudze kodu języka: podczas korzystania z interfejsu API
Locale
kodów językowych w językach hebrajskim, jidysz i indonezyjskim nie są już konwertowane na ich przestarzałe formy (hebrajski:iw
, jidysz:ji
i indonezyjski:in
). Aby określić kod języka dla jednego z tych regionów, użyj tych kodów według normy ISO 639-1 (hebrajski:he
, jidysz:yi
i indonezyjski:id
).Zmiany w losowych ciągach int: po zmianach wprowadzonych w https://bugs.openjdk.org/browse/JDK-8301574 Metody
Random.ints()
zwracają teraz inną sekwencję liczb niż metodyRandom.nextInt()
:Zwykle ta zmiana nie powinna powodować rozbijania aplikacji, ale nie powinien oczekiwać sekwencji wygenerowanej z metod
Random.ints()
do:Random.nextInt()
.
Nowy interfejs API SequencedCollection
może wpływać na zgodność Twojej aplikacji
po zaktualizowaniu compileSdk
w konfiguracji kompilacji aplikacji, aby używać
Android 15 (poziom interfejsu API 35):
Kolizja z
MutableList.removeFirst()
oraz Funkcje rozszerzeńMutableList.removeLast()
wkotlin-stdlib
Typ
List
w Javie jest zmapowany na typMutableList
w Kotlin. Ponieważ interfejsy APIList.removeFirst()
iList.removeLast()
zostały wprowadzone w Androidzie 15 (poziom API 35) – kompilatorze Kotlin przekształca statycznie wywołania funkcji, na przykładlist.removeFirst()
, na nowych interfejsów APIList
zamiast funkcji rozszerzeń wkotlin-stdlib
.Jeśli aplikacja jest ponownie skompilowana z ustawieniem
compileSdk
ustawionym na35
, aminSdk
z wartością34
lub niższy, a potem aplikacja działa na Androidzie 14 lub starszym, w środowisku wykonawczym jest zgłaszany błąd:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
Istniejąca opcja lintowania
NewApi
we wtyczce Androida do obsługi Gradle może je wychwytywać nowych zastosowań interfejsu API../gradlew lint
MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi] list.removeFirst()Aby naprawić błędy wyjątku i lintowania w środowisku wykonawczym, funkcje
removeFirst()
i Wywołania funkcjiremoveLast()
można zastąpić wyrażeniamiremoveAt(0)
iremoveAt(list.lastIndex)
w aplikacji Kotlin. Jeśli używasz Android Studio Biedronka | 2024.1.3 lub nowszej, .Jeśli opcja lintowania została wyłączona, rozważ usunięcie interfejsów
@SuppressLint("NewApi")
ilintOptions { disable 'NewApi' }
.Kolizja z innymi metodami w Javie
Do istniejących typów zostały dodane nowe metody, na przykład
List
iDeque
. Te nowe metody mogą nie być zgodne w innych interfejsach z użyciem metod o tej samej nazwie i typach argumentów i zajęcia. W przypadku kolizji podpisów metod z kompilatorjavac
zwraca błąd w czasie kompilacji. Dla: przykład:Przykładowy błąd 1:
javac MyList.java
MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List public void removeLast() { ^ return type void is not compatible with Object where E is a type-variable: E extends Object declared in interface ListPrzykładowy błąd 2:
javac MyList.java
MyList.java:7: error: types Deque<Object> and List<Object> are incompatible; public class MyList implements List<Object>, Deque<Object> { both define reversed(), but with unrelated return types 1 errorPrzykładowy błąd 3:
javac MyList.java
MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible; public static class MyList implements List<Object>, MyInterface<Object> { class MyList inherits unrelated defaults for getFirst() from types List and MyInterface where E#1,E#2 are type-variables: E#1 extends Object declared in interface List E#2 extends Object declared in interface MyInterface 1 errorAby naprawić te błędy kompilacji, klasa implementująca te interfejsy powinna zastąpić metodę zgodnym typem zwracanym. Na przykład:
@Override public Object getFirst() { return List.super.getLast(); }
Bezpieczeństwo
Android 15 zawiera zmiany, które promują bezpieczeństwo systemu i pomagają chronić aplikacje przed użytkownikami ze złośliwych aplikacji.
Uruchomienie bezpiecznej aktywności w tle
Android 15 chroni użytkowników przed złośliwymi aplikacjami i daje im większą kontrolę nad ich urządzeniach, dodając zmiany, które uniemożliwiają złośliwym aplikacjom działającym w tle ujawnianie innych aplikacji, podnoszenie ich przywilejów i nadużywanie interakcji użytkownika. Od wersji Android 10 (poziom interfejsu API 29) ograniczono uruchamianie działań w tle.
Blokowanie uruchamiania aktywności przez aplikacje, których identyfikator nie pasuje do najwyższego identyfikatora na stosie
Złośliwe aplikacje mogą uruchomić inną aplikację w ramach tego samego zadania, a następnie
nakładają się na siebie i tworzą wrażenie, że jest to ta aplikacja. To „zadanie
porwanie” omija obecne ograniczenia uruchamiania w tle,
występuje w ramach tego samego widocznego zadania. Aby zmniejszyć to ryzyko, Android 15 dodaje flagę, która blokuje uruchamianie aktywności przez aplikacje, których identyfikator UID nie pasuje do najwyższego identyfikatora UID w steku. Aby wyrazić zgodę na wszystkie aktywności w aplikacji, zaktualizuj
allowCrossUidActivitySwitchFromBelow
w pliku AndroidManifest.xml
aplikacji:
<application android:allowCrossUidActivitySwitchFromBelow="false" >
Nowe zabezpieczenia są aktywne, jeśli są spełnione wszystkie te warunki:
- Aplikacja, w której wprowadzana jest na rynek, jest kierowana na Androida 15.
- Aplikacja u góry stosu zadań jest kierowana na Androida 15.
- Każda widoczna aktywność została objęta nowymi zabezpieczeniami
Jeśli środki bezpieczeństwa są włączone, aplikacje mogą po zakończeniu działania wracać na ekran główny, a nie do ostatniej widocznej aplikacji.
Inne zmiany
Oprócz ograniczenia dopasowania identyfikatorów UID te inne zmiany również uwzględniono:
- Zmień
PendingIntent
twórców na blokowanie uruchamiania aktywności w tle przez domyślne. Zapobiega to przypadkowemu utworzeniu przez aplikacjePendingIntent
, które mogą być wykorzystywane przez hakerów. - Nie przenoś aplikacji na pierwszy plan, chyba że nadawca
PendingIntent
na to zezwala. Ta zmiana ma na celu zapobieganie wykorzystywaniu uruchamianie działań w tle. Domyślnie aplikacje nie są może przenieść stos zadań na pierwszy plan, chyba że twórca wyrazi zgodę uprawnienia do uruchamiania aktywności w tle lub nadawca ma aktywność w tle uprawnienia do uruchamiania. - Określ, w jaki sposób główna aktywność stosu zadań może wykonać zadanie. Jeśli które kończy zadanie, Android wróci do tego, które było jako ostatnia aktywność. Ponadto jeśli aktywność niebędąca na pierwszym planie zakończy swoje działanie, Android wróci do ekranu głównego. Nie zablokuje to zakończenia tej aktywności.
- Zapobiegaj uruchamianiu dowolnych działań z innych aplikacji we własnym zakresie zadanie. Ta zmiana zapobiega wyłudzaniu informacji przez złośliwe aplikacje, tworząc aktywności, które wyglądają jak z innych aplikacji.
- Nie zezwalaj na uwzględnianie niewidocznych okien w aktywności w tle . Pomaga to zapobiegać wykorzystywaniu działania w tle przez złośliwe aplikacje aby wyświetlać użytkownikom niechciane lub szkodliwe treści.
Bezpieczniejsze intencje
Android 15 wprowadza nowe zabezpieczenia, które zwiększają bezpieczeństwo intencji solidny. Te zmiany mają zapobiegać potencjalnym lukom w zabezpieczeniach nadużywania intencji, które mogą być wykorzystywane przez złośliwe aplikacje. Najważniejsze są dwa sposoby – poprawki dotyczące bezpieczeństwa intencji w Androidzie 15:
- Dopasuj docelowe filtry intencji: intencje kierowane na określone komponenty muszą dokładnie pasują do specyfikacji filtra intencji. Jeśli wyślesz do uruchomienia działania innej aplikacji, komponent intencji docelowej musi do zadeklarowanych filtrów intencji w działaniu odbierającym.
- Intencje muszą zawierać działania: intencje bez działania nie będą już pasować. żadnych filtrów intencji. Oznacza to, że intencje używane do rozpoczynania działań lub usługi muszą mieć jasno określone działanie.
- Intencje oczekujące: twórca oczekującej intencji to traktowany jako nadawca intencji nadrzędnej, a nie nadawcy oczekującej intencja
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() .detectUnsafeIntentLaunch() .build() ) }
Java
public void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() .detectUnsafeIntentLaunch() .build()); }
Wygoda użytkowania i interfejs systemu
W Androidzie 15 wprowadziliśmy kilka zmian, które mają zapewnić intuicyjną obsługę.
Zmiany wstawienia okien
W Androidzie 15 wprowadzono 2 zmiany związane z wstawianiem okien: ustawienie od krawędzi do krawędzi jest domyślnie wymuszane w obszarze od krawędzi do krawędzi oraz zmiany w konfiguracji, takie jak domyślna konfiguracja pasków systemowych.
Egzekwowanie treści od krawędzi do krawędzi
Domyślnie na urządzeniach z Androidem 15 aplikacje działają od brzegu do brzegu, jeśli są są kierowane na Androida 15 (poziom API 35).
Jest to zmiana powodująca niezgodność, która może negatywnie wpłynąć na interfejs Twojej aplikacji. zmiany wpływają na następujące obszary interfejsu:
- Pasek nawigacyjny z uchwytem przy użyciu gestów
- Domyślnie przezroczyste.
- Odsunięcie od dołu jest wyłączone, więc treść jest wyświetlana za nawigacją w systemie. o ile nie są zastosowane wcięcia.
setNavigationBarColor
iR.attr#navigationBarColor
są została wycofana i nie ma wpływu na nawigację przy użyciu gestów.setNavigationBarContrastEnforced
iR.attr#navigationBarContrastEnforced
nadal nie ma wpływu na nawigacji przy użyciu gestów.
- Nawigacja przy użyciu 3 przycisków
- Przezroczystość jest domyślnie ustawiona na 80%, ale kolory mogą być dopasowane do okna w tle.
- Przesunięcie od dołu jest wyłączone, więc treść jest wyświetlana za systemowym paskiem nawigacyjnym o ile nie są zastosowane wstawki.
setNavigationBarColor
iR.attr#navigationBarColor
są jest domyślnie dopasowane do tła okna. Tło okna musi być kolorem, który można narysować, aby ta domyślna została zastosowana. Ten interfejs API jest została wycofana, ale nadal wpływa na nawigację przy użyciu 3 przycisków.setNavigationBarContrastEnforced
iR.attr#navigationBarContrastEnforced
ma domyślnie wartość prawda, co dodaje parametr Nieprzezroczyste tło na poziomie 80% na nawigacji przy użyciu 3 przycisków.
- Pasek stanu
- Domyślnie przezroczyste.
- Przesunięcie od góry jest wyłączone, więc treść jest wyświetlana za paskiem stanu, chyba że stosowane są wstawki.
setStatusBarColor
iR.attr#statusBarColor
są została wycofana i nie będzie miała wpływu na Androida 15.setStatusBarContrastEnforced
i KolumnyR.attr#statusBarContrastEnforced
zostały wycofane, ale nadal występują na Androida 15.
- Wycięcie w ekranie
layoutInDisplayCutoutMode
okien niepływających musi byćLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
SHORT_EDGES
,NEVER
iDEFAULT
są interpretowane jakoALWAYS
, więc użytkownicy nie widzą czarnego paska spowodowane wycięciem w ekranie i wyświetlają się od krawędzi do krawędzi.
Przykład poniżej pokazuje aplikację przed kierowaniem i po nim Android 15 (poziom interfejsu API 35) oraz przed użyciem wstawienia i po nim.
. .Co sprawdzić, czy aplikacja jest już w modelu brzegowym
Jeśli Twoja aplikacja jest już w fazie edge-to-edge i stosuje wstawki, nie ma wpływu na dane, z wyjątkiem tych scenariuszy. Jednak nawet jeśli wydaje Ci się, u Ciebie nie wpłynie to na działanie Twojej aplikacji, dlatego zalecamy, aby ją przetestować.
- Masz okno niepływające, na przykład
Activity
, które używa funkcjiSHORT_EDGES
,NEVER
lubDEFAULT
zamiastLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
. Jeśli przy uruchamianiu aplikacja ulegnie awarii, może to być spowodowane przez ekran powitalny. Możesz uaktualnić wersję podstawowej zależność ekranu powitalnego od 1.2.0-alpha01 lub później albo ustawwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
. - Mogą wyświetlać się ekrany o mniejszym natężeniu ruchu z zasłoniętym interfejsem. Sprawdź
rzadziej używane ekrany nie mają interfejsu użytkownika. Ekrany o mniejszym ruchu to m.in.:
- Ekrany wprowadzenia i ekrany logowania
- Strony ustawień
Co sprawdzić, czy aplikacja nie jest jeszcze w całej sieci brzegowej
Jeśli Twoja aplikacja nie jest jeszcze w trybie brzegowym, ta zmiana prawdopodobnie będzie miała na nią wpływ. W dla aplikacji, które są już w jednej sieci brzegowej, weź pod uwagę następujące kwestie:
- Jeśli Twoja aplikacja korzysta z komponentów Material 3 (
androidx.compose.material3
) w trakcie tworzenia wiadomości, na przykładTopAppBar
,BottomAppBar
iNavigationBar
, prawdopodobnie nie ponieważ automatycznie obsługują wstawki. - Jeśli Twoja aplikacja korzysta z komponentów Material 2 (
androidx.compose.material
) w tworzeniu, te komponenty nie obsługują automatycznie wkładek. Możesz jednak uzyskać dostęp do wektorów i zastosuj je ręcznie. W wersji androidx.compose.material 1.6.0 a później użyj parametruwindowInsets
, aby ręcznie zastosować wstawkiBottomAppBar
,TopAppBar
,BottomNavigation
iNavigationRail
. Podobnie użyj parametrucontentWindowInsets
do:Scaffold
- Jeśli Twoja aplikacja korzysta z widoków i komponentów Material Komponenty
(
com.google.android.material
), Materiał w większości wyświetleń Komponenty, takie jakBottomNavigationView
,BottomAppBar
,NavigationRailView
lubNavigationView
, uchwyty wstawiane i nie wymagają dodatkowej pracy. Musisz jednak dodaćandroid:fitsSystemWindows="true"
w przypadku używania funkcjiAppBarLayout
. - W przypadku niestandardowych funkcji kompozycyjnych zastosuj wstawki ręcznie jako dopełnienie. Jeśli
treści znajduje się w zakresie
Scaffold
, możesz korzystać z wektorów za pomocą funkcjiScaffold
. W przeciwnym razie zastosuj dopełnienie za pomocą jednej zWindowInsets
- Jeśli aplikacja używa widoków danych i
BottomSheet
,SideSheet
lub niestandardowych kontenery, zastosuj dopełnienie za pomocąViewCompat.setOnApplyWindowInsetsListener
. Dla:RecyclerView
, zastosuj dopełnienie za pomocą tego detektora, a także dodajclipToPadding="false"
Co sprawdzić, czy aplikacja musi oferować niestandardową ochronę w tle
Jeśli aplikacja musi oferować niestandardową ochronę w tle do nawigacji przy użyciu 3 przycisków lub
na pasku stanu, aplikacja powinna umieścić za paskiem systemowym funkcję kompozycyjną lub widok
przy użyciu WindowInsets.Type#tappableElement()
, aby pobrać przycisk z 3 przyciskami
wysokość paska nawigacyjnego lub WindowInsets.Type#statusBars
.
Dodatkowe zasoby brzegowe
Zapoznaj się z sekcjami Widoki brzegowe do krawędzi i Tworzenie treści od krawędzi do krawędzi. zawiera dodatkowe informacje na temat stosowania wkładek.
Wycofane interfejsy API
Te interfejsy API zostały wycofane:
R.attr#enforceStatusBarContrast
R.attr#navigationBarColor
R.attr#navigationBarDividerColor
R.attr#statusBarColor
Window#getNavigationBarColor
Window#getNavigationBarDividerColor
Window#getStatusBarColor
Window#isStatusBarContrastEnforced
Window#setDecorFitsSystemWindows
Window#setNavigationBarColor
Window#setNavigationBarDividerColor
Window#setStatusBarColor
Window#setStatusBarContrastEnforced
Stabilna konfiguracja
Jeśli Twoja aplikacja jest kierowana na Androida 15 (poziom API 35) lub nowszego, Configuration
nie wyklucza już pasków systemowych. Jeśli do obliczenia układu używasz rozmiaru ekranu w klasie Configuration
, zastąp go lepszymi alternatywami, np. odpowiednią wartością ViewGroup
, WindowInsets
lub WindowMetricsCalculator
, w zależności od potrzeb.
Interfejs Configuration
jest dostępny od wersji API 1. Zazwyczaj jest pozyskiwany
Activity.onConfigurationChanged
Zawiera on informacje o gęstości okien, orientacji i rozmiarach. Ważna cecha określająca rozmiary okien
zwracanych przez funkcję Configuration
oznacza, że wcześniej były wykluczone słupki systemowe.
Rozmiar konfiguracji jest zwykle używany do wyboru zasobów, na przykład
/res/layout-h500dp
. Jest to nadal prawidłowy przypadek użycia. Nie zalecamy jednak używania go do obliczania układu. Jeśli tak, odejdź od niego. W zależności od przypadku użycia Configuration
należy zastąpić czymś bardziej odpowiednim.
Jeśli używasz go do obliczenia układu, użyj odpowiedniej wartości ViewGroup
, np. CoordinatorLayout
lub ConstraintLayout
. Jeśli używasz go do określania wysokości,
na pasku nawigacyjnym systemu użyj funkcji WindowInsets
. Jeśli chcesz poznać aktualny rozmiar
okna aplikacji, użyj computeCurrentWindowMetrics
.
Poniższa lista zawiera opis pól, na które wpływa ta zmiana:
- Rozmiary
Configuration.screenWidthDp
iscreenHeightDp
nie wykluczają już pasków systemu. - Zmiany w usługach
screenWidthDp
iscreenHeightDp
mają pośredni wpływ na usługęConfiguration.smallestScreenWidthDp
. - Pośredni wpływ na usługę
Configuration.orientation
mają zmiany w usługachscreenWidthDp
iscreenHeightDp
na urządzeniach o zbliżonym kształcie. - Usługa
Display.getSize(Point)
ma pośredni wpływ na zmiany wConfiguration
Został on wycofany od poziomu API 30. - Funkcja
Display.getMetrics()
działa już w ten sposób od poziomu API 33.
AtrybuteleTextHeight ma domyślną wartość true (prawda)
W przypadku aplikacji kierowanych na Androida 15 atrybut elegantTextHeight
TextView
ma domyślnie wartość true
, co powoduje zastąpienie domyślnie używanej domyślnie kompaktowej czcionki pewnymi skryptami o dużych danych pionowych inną, która jest znacznie bardziej czytelna. Wprowadzono kompaktową czcionkę, aby zapobiec naruszaniu układów. Android 13 (poziom interfejsu API 33) zapobiega wielu z tych problemów, umożliwiając układowi tekstu rozciąganie wysokości w pionie za pomocą atrybutu fallbackLineSpacing
.
W Androidzie 15 kompaktowa czcionka pozostaje w systemie, więc aplikacja może ustawić elegantTextHeight
na false
, aby uzyskać takie samo działanie jak wcześniej, ale prawdopodobnie nie będzie obsługiwana w kolejnych wersjach. Jeśli Twoja aplikacja obsługuje te skrypty: arabski, laotański, birmański, tamilski, gudżarati, kannada, malajalam, orija, telugu lub tajski, przetestuj ją, ustawiając w polu elegantTextHeight
opcję true
.
Zmiany szerokości obiektu TextView w przypadku złożonych kształtów liter
W poprzednich wersjach Androida niektóre czcionki kursywą lub języki, w których
złożone kształtowanie może spowodować narysowanie liter w obszarze poprzedniego lub następnego znaku.
Zdarzało się, że takie litery były obcinane na początku lub na końcu.
Począwszy od Androida 15 TextView
określa szerokość, aby zapewnić wystarczającą ilość miejsca
dla takich liter i umożliwia aplikacjom żądanie dodatkowego dopełnienia z lewej strony,
zapobiegają obcinaniu.
Ta zmiana wpływa na sposób określania szerokości przez element TextView
, dlatego TextView
domyślnie przypisuje większą szerokość, jeśli aplikacja jest kierowana na Androida 15 (poziom interfejsu API 35) lub
wyższe. Możesz włączyć lub wyłączyć tę funkcję, wywołując metodę
Interfejs API setUseBoundsForWidth
w systemie TextView
.
Dodanie dopełnienia z lewej strony może spowodować niedopasowanie istniejących układów,
dopełnienie nie jest dodawane domyślnie nawet w przypadku aplikacji kierowanych na Androida 15 lub nowszego.
Można jednak dodać dodatkowe dopełnienie, aby zapobiec przycinaniu obrazu przez wywołanie
setShiftDrawingOffsetForStartOverhang
Poniższe przykłady pokazują, jak te zmiany mogą poprawić układ tekstu w niektórych z nich czcionki i języki.
Domyślna wysokość wiersza z uwzględnieniem języka dla interfejsu EditText
W poprzednich wersjach Androida układ tekstu rozciągnął wysokość tekstu, aby dopasować ją do wysokości czcionki w bieżącym języku. Jeśli na przykład treść była w języku japońskim, ponieważ wysokość wiersza czcionki japońskiej jest nieco większa niż czcionki łacińskiej, wysokość tekstu znacznie się zwiększyła. Pomimo tych różnic w wysokości wierszy, rozmiar elementu EditText
był jednak taki sam niezależnie od używanego regionu, jak na tym przykładzie:
W przypadku aplikacji kierowanych na Androida 15 minimalna wysokość wiersza jest teraz zarezerwowana dla EditText
, aby pasowała do czcionki referencyjnej dla określonego języka, jak widać na tym obrazie:
W razie potrzeby aplikacja może przywrócić poprzednie działanie, określając atrybut useLocalePreferredLineHeightForMinimum
jako false
, a aplikacja może ustawiać niestandardowe minimalne wskaźniki branżowe za pomocą interfejsu API setMinimumFontMetrics
w Kotlin i Javie.
Aparat i multimedia
Android 15 wprowadza te zmiany w działaniu aparatu i multimediów w aplikacjach na Androida 15 lub nowszego.
Ograniczenia dotyczące żądania skupienia się na dźwięku
Aplikacje kierowane na Androida 15 muszą być najlepszą aplikacją lub obsługiwać usługę na pierwszym planie, aby żądać aktywności audio. Jeśli aplikacja próbuje poprosić o koncentrację, gdy nie spełnia jednego z tych wymagań, wywołanie zwraca AUDIOFOCUS_REQUEST_FAILED
.
Więcej informacji o aktywności audio znajdziesz w artykule Zarządzanie aktywnością audio.
Zaktualizowano ograniczenia spoza pakietu SDK
Android 15 zawiera zaktualizowane listy ograniczonych list aplikacji spoza pakietu SDK oparte na współpracy z deweloperami aplikacji na Androida oraz do testów wewnętrznych. Gdy tylko jest to możliwe, dbamy o to, by alternatywne rozwiązania były dostępne publicznie, zanim wprowadzimy ograniczenia dotyczące interfejsów spoza SDK.
Jeśli Twoja aplikacja nie jest kierowana na Androida 15, niektóre z tych zmian mogą nie być od razu widoczne. Mimo że aplikacja może dostęp do niektórych interfejsów spoza SDK w zależności od docelowego poziomu interfejsu API aplikacji, używając dowolnego innego zawsze wiąże się z dużym ryzykiem uszkodzenia aplikacji.
Jeśli nie wiesz, czy Twoja aplikacja korzysta z interfejsów innych niż SDK, przetestować aplikację. Jeśli Twoja aplikacja korzysta z innego pakietu SDK należy planować migrację na alternatywne wersje SDK. Zdajemy sobie jednak sprawę, że niektóre aplikacje mogą mieć z interfejsami innymi niż SDK. Jeśli nie możesz znaleźć alternatywy dla pakietu SDK interfejsu funkcji aplikacji, żądanie nowego publicznego interfejsu API.
Więcej informacji o zmianach w tej wersji Androida znajdziesz w artykule Aktualizacje ograniczeń interfejsu innego niż SDK na Androidzie 15. Więcej informacji o interfejsach innych niż SDK znajdziesz w tym artykule.