Podobnie jak w poprzednich wersjach Android 15 obejmuje zmiany w działaniu, które mogą mieć wpływ na Twoją aplikację. Poniższe zmiany w działaniu dotyczą tylko aplikacji kierowanych na Androida 15 lub nowszego. Jeśli Twoja aplikacja jest kierowana na Androida 15 lub nowszego, w razie potrzeby zmodyfikuj aplikację, aby prawidłowo obsługiwała te zachowania.
Zapoznaj się też z listą zmian w działaniu, które wpływają na wszystkie aplikacje działające na Androidzie 15, niezależnie od targetSdkVersion
w Twojej aplikacji.
Główna funkcja
Android 15 zmienia lub rozszerza różne podstawowe funkcje systemu Android.
Zmiany w usługach na pierwszym planie
Wprowadzamy następujące zmiany w usługach działających na pierwszym planie w Androidzie 15.
- Nowy typ usługi na pierwszym planie przetwarzania multimediów
- Ograniczenia dotyczące
BOOT_COMPLETED
odbiorników uruchamiających usługi na pierwszym planie
Zachowanie limitu czasu usługi synchronizacji danych na pierwszym planie
Android 15 introduces a new timeout behavior to dataSync
for apps targeting
Android 15 or higher. This behavior also applies to the new mediaProcessing
foreground service type.
The system permits an app's dataSync
services to run for a total of 6 hours
in a 24-hour period, after which the system calls the running service's
Service.onTimeout(int, int)
method (introduced in Android
15). At this time, the service has a few seconds to call
Service.stopSelf()
. When Service.onTimeout()
is called, the
service is no longer considered a foreground service. If the service does not
call Service.stopSelf()
, the system throws an internal exception. The
exception is logged in Logcat with the following message:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"
To avoid problems with this behavior change, you can do one or more of the following:
- Have your service implement the new
Service.onTimeout(int, int)
method. When your app receives the callback, make sure to callstopSelf()
within a few seconds. (If you don't stop the app right away, the system generates a failure.) - Make sure your app's
dataSync
services don't run for more than a total of 6 hours in any 24-hour period (unless the user interacts with the app, resetting the timer). - Only start
dataSync
foreground services as a result of direct user interaction; since your app is in the foreground when the service starts, your service has the full six hours after the app goes to the background. - Instead of using a
dataSync
foreground service, use an alternative API.
If your app's dataSync
foreground services have run for 6 hours in the last
24, you cannot start another dataSync
foreground service unless the user
has brought your app to the foreground (which resets the timer). If you try to
start another dataSync
foreground service, the system throws
ForegroundServiceStartNotAllowedException
with an error message like "Time limit already exhausted for foreground service
type dataSync".
Testing
To test your app's behavior, you can enable data sync timeouts even if your app
is not targeting Android 15 (as long as the app is running on an Android 15
device). To enable timeouts, run the following adb
command:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
You can also adjust the timeout period, to make it easier to test how your
app behaves when the limit is reached. To set a new timeout period, run the
following adb
command:
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 typ usługi jest odpowiedni do operacji takich jak transkodowanie plików multimedialnych. Na przykład aplikacja do multimediów może pobrać plik audio i przed odtworzeniem go musi przekonwertować go na inny format. Możesz użyć usługi na pierwszym planie mediaProcessing
, aby mieć pewność, że konwersja będzie kontynuowana nawet wtedy, gdy aplikacja działa w tle.
System zezwala na działanie usług mediaProcessing
aplikacji przez łącznie 6 godzin w okresie 24 godzin. Po tym czasie system wywołuje metodę Service.onTimeout(int, int)
(wprowadzoną w Androidzie 15). W tej chwili usługa ma kilka sekund na wywołanie metody Service.stopSelf()
. Jeśli usługa nie wywoła funkcji Service.stopSelf()
, system zgłosi wyjątek wewnętrzny. Wyjątek jest logowany w Logcat z tym 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, pamiętaj, aby wywołać funkcjęstopSelf()
w ciągu kilku sekund. Jeśli nie zatrzymasz aplikacji od razu, system wygeneruje błąd. - Dopilnuj, aby usługi
mediaProcessing
w Twojej aplikacji nie działały przez łącznie 6 godzin w dowolnym okresie 24 godzin (chyba że użytkownik wejdzie w interakcję z aplikacją, resetując minutnik). - Uruchamiaj
mediaProcessing
usługi na pierwszym planie wyłącznie w wyniku bezpośredniej interakcji z użytkownikiem. Ponieważ w momencie uruchomienia usługi Twoja aplikacja znajduje się na pierwszym planie, usługa ma pełne 6 godzin od momentu przejścia do działania w tle. - Zamiast usługi na pierwszym planie
mediaProcessing
użyj alternatywnego interfejsu API, takiego jak WorkManager.
Jeśli usługi na pierwszym planie mediaProcessing
w Twojej aplikacji działały przez 6 godzin w ciągu ostatnich 24 godzin, nie możesz uruchomić kolejnej usługi mediaProcessing
na pierwszym planie, chyba że użytkownik przeniósł aplikację na pierwszy plan (co spowoduje zresetowanie licznika). Jeśli spróbujesz uruchomić inną usługę na pierwszym planie mediaProcessing
, system wygeneruje ForegroundServiceStartNotAllowedException
z komunikatem o błędzie, np. „Limit czasu dla usługi działającej na pierwszym planie typu mediaProcessing został już wyczerpany”.
Więcej informacji o typie usługi mediaProcessing
znajdziesz w artykule Zmiany w typach usług 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 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ć limit czasu oczekiwania, by łatwiej testować działanie aplikacji 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
Obowiązują nowe ograniczenia dotyczące odbiorników transmisji (BOOT_COMPLETED
) uruchamiających usługi na pierwszym planie. Odbiorniki BOOT_COMPLETED
nie mogą uruchamiać tych typów usług działających na pierwszym planie:
dataSync
camera
mediaPlayback
phoneCall
mediaProjection
microphone
(to ograniczenie obowiązuje w przypadku aplikacjimicrophone
od wersji Androida 14)
Jeśli odbiornik BOOT_COMPLETED
spróbuje uruchomić którykolwiek z tych typów usług na pierwszym planie, system zgłosi ForegroundServiceStartNotAllowedException
.
Ograniczenia dotyczące uruchamiania usług działających na pierwszym planie, gdy aplikacja ma uprawnienie SYSTEM_ALERT_WINDOW
Wcześniej aplikacja, która miała uprawnienie SYSTEM_ALERT_WINDOW
, mogła uruchamiać usługę na pierwszym planie, nawet jeśli działała w tle (co omówiono w sekcji wyjątki z ograniczeń uruchamiania w tle).
Jeśli aplikacja jest kierowana na Androida 15, to wykluczenie jest teraz węższe. Aplikacja musi teraz mieć uprawnienie SYSTEM_ALERT_WINDOW
oraz również mieć widoczne nakładki. Oznacza to, że aplikacja musi najpierw uruchomić okno TYPE_APPLICATION_OVERLAY
oraz okno musi być widoczne przed uruchomieniem usługi na pierwszym planie.
Jeśli aplikacja próbuje uruchomić usługę na pierwszym planie w tle i nie spełnia tych nowych wymagań (i nie jest objęta innym wyjątkiem), system zgłasza ForegroundServiceStartNotAllowedException
.
Jeśli Twoja aplikacja zadeklaruje uprawnienie SYSTEM_ALERT_WINDOW
i uruchamia usługi działające na pierwszym planie w tle, ta zmiana może mieć na nią wpływ. Jeśli Twoja aplikacja otrzyma właściwość ForegroundServiceStartNotAllowedException
, sprawdź jej kolejność działań i upewnij się, że ma już aktywne okno nakładki, zanim będzie próbowała uruchomić usługę na pierwszym planie z poziomu tła. Aby sprawdzić, czy okno nakładki jest obecnie widoczne, wywołaj View.getWindowVisibility()
. Możesz też zastąpić metodę View.onWindowVisibilityChanged()
, aby otrzymywać powiadomienia o zmianie widoczności.
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
W Androidzie 15 wciąż pracujemy nad odświeżaniem podstawowych bibliotek Androida, aby zapewnić zgodność z funkcjami w najnowszych wersjach OpenJDK LTS.
Jedna z tych zmian może wpłynąć na zgodność aplikacji kierowanych na Androida 15 (poziom API 35):
Zmiany w interfejsach API formatowania ciągów znaków: weryfikacja indeksu argumentu, flag, szerokości i precyzji jest teraz bardziej rygorystyczna w przypadku korzystania z tych interfejsów 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 w przypadku użycia indeksu argumentu 0 (
%0
w ciągu formatu ciągu znaków) zgłaszany jest następujący wyjątek: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 typu komponentu
Arrays.asList(...).toArray()
: gdy używaszArrays.asList(...).toArray()
, typ komponentu tablicy wynikowej to terazObject
, a nie typ elementów tablicy bazowej. Poniższy kod zgłaszaClassCastException
:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
Aby w tym przypadku zachować
String
jako typ komponentu w tablicy wynikowej, możesz zamiast tego użyćCollection.toArray(Object[])
:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
Zmiany w obsłudze kodów językowych: w przypadku interfejsu API
Locale
kody języków dla hebrajskiego, jidysz i indonezyjskiego nie są już konwertowane na stare formy (hebrajski:iw
, jidysz:ji
i indonezyjski:in
). Przy określaniu kodu języka dla jednego z tych języków użyj kodów z języków hebrajskich, jidysz , indonezyjskiego:he
, Y (język angielski, indonezyjski:he
, Y).yi
id
Zmiany w losowych sekwencji int: po zmianach wprowadzonych na https://bugs.openjdk.org/browse/JDK-8301574 poniższe metody
Random.ints()
zwracają teraz inną sekwencję liczb niż metodyRandom.nextInt()
:Zwykle ta zmiana nie powinna powodować rozbijania aplikacji, ale Twój kod nie powinien oczekiwać, że sekwencja wygenerowana za pomocą metod
Random.ints()
będzie zgodna z zasadąRandom.nextInt()
.
Gdy zaktualizujesz compileSdk
w konfiguracji kompilacji aplikacji, nowy interfejs API SequencedCollection
może wpłynąć na zgodność aplikacji z Androidem 15 (poziom interfejsu API 35):
Zderzenie z funkcjami rozszerzeń
MutableList.removeFirst()
iMutableList.removeLast()
wkotlin-stdlib
Typ
List
w Javie jest zmapowany na typMutableList
w Kotlin. Interfejsy APIList.removeFirst()
iList.removeLast()
zostały wprowadzone w Androidzie 15 (poziom API 35), dlatego kompilator Kotlin traktuje statycznie wywołania funkcji, np.list.removeFirst()
, na nowe interfejsy APIList
, a nie na funkcje rozszerzeń podane w tym artykulekotlin-stdlib
.Jeśli aplikacja zostanie ponownie skompilowana z ustawieniem
compileSdk
ustawionym na35
i ustawieniemminSdk
na34
lub niższym, a potem będzie działać na Androidzie 14 i starszych wersjach, pojawi się błąd czasu działania: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 wychwytywać te nowe przypadki wykorzystania 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, wywołania funkcji
removeFirst()
iremoveLast()
można zastąpić w Kotlin odpowiednioremoveAt(0)
iremoveAt(list.lastIndex)
. Jeśli używasz Androida Studio Ladybug | 2024.1.3 lub nowszego, tutaj znajdziesz opcję szybkiego naprawiania tych błędów.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, np.
List
iDeque
. Te nowe metody mogą być niezgodne z metodami o tej samej nazwie i typach argumentów w innych interfejsach i klasach. W przypadku kolizji podpisów metod kompilatorjavac
zwraca błąd w czasie kompilacji. 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(); }
Zabezpieczenia
Android 15 zawiera zmiany, które promują bezpieczeństwo systemu, aby chronić aplikacje i użytkowników przed złośliwymi aplikacjami.
Uruchomienie bezpiecznej aktywności w tle
Android 15 protects users from malicious apps and gives them more control over their devices by adding changes that prevent malicious background apps from bringing other apps to the foreground, elevating their privileges, and abusing user interaction. Background activity launches have been restricted since Android 10 (API level 29).
Block apps that don't match the top UID on the stack from launching activities
Malicious apps can launch another app's activity within the same task, then
overlay themselves on top, creating the illusion of being that app. This "task
hijacking" attack bypasses current background launch restrictions because it all
occurs within the same visible task. To mitigate this risk, Android 15 adds a
flag that blocks apps that don't match the top UID on the stack from launching
activities. To opt in for all of your app's activities, update the
allowCrossUidActivitySwitchFromBelow
attribute in your app's AndroidManifest.xml
file:
<application android:allowCrossUidActivitySwitchFromBelow="false" >
The new security measures are active if all of the following are true:
- The app performing the launch targets Android 15.
- The app on top of the task stack targets Android 15.
- Any visible activity has opted in to the new protections
If the security measures are enabled, apps might return home, rather than the last visible app, if they finish their own task.
Other changes
In addition to the restriction for UID matching, these other changes are also included:
- Change
PendingIntent
creators to block background activity launches by default. This helps prevent apps from accidentally creating aPendingIntent
that could be abused by malicious actors. - Don't bring an app to the foreground unless the
PendingIntent
sender allows it. This change aims to prevent malicious apps from abusing the ability to start activities in the background. By default, apps are not allowed to bring the task stack to the foreground unless the creator allows background activity launch privileges or the sender has background activity launch privileges. - Control how the top activity of a task stack can finish its task. If the top activity finishes a task, Android will go back to whichever task was last active. Moreover, if a non-top activity finishes its task, Android will go back to the home screen; it won't block the finish of this non-top activity.
- Prevent launching arbitrary activities from other apps into your own task. This change prevents malicious apps from phishing users by creating activities that appear to be from other apps.
- Block non-visible windows from being considered for background activity launches. This helps prevent malicious apps from abusing background activity launches to display unwanted or malicious content to users.
Bezpieczniejsze intencje
Android 15 wprowadza nowe zabezpieczenia, które zwiększają bezpieczeństwo intencji. Te zmiany mają zapobiegać potencjalnym lukom w zabezpieczeniach i niewłaściwemu wykorzystaniu intencji, które mogą być wykorzystywane przez złośliwe aplikacje. W Androidzie 15 występują 2 główne ulepszenia w zakresie bezpieczeństwa intencji:
- Dopasuj do filtrów intencji: intencje kierowane na określone komponenty muszą dokładnie odpowiadać specyfikacji filtra intencji. Jeśli wyślesz zamiar uruchomienia innej aplikacji, komponent intencji docelowej musi być zgodny z zadeklarowanymi filtrami intencji odbierającej.
- Intencje muszą zawierać działania: intencje bez działania nie będą już pasować do żadnych filtrów intencji. Oznacza to, że intencje służące do rozpoczynania działań lub świadczenia usług muszą mieć jasno określone działanie.
- Intencje oczekujące: twórca intencji oczekującej jest traktowany jako nadawca intencji zamykającej, a nie jako nadawca oczekującej intencji
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 wprowadzono kilka zmian, które mają zapewnić użytkownikom bardziej spójne i intuicyjne wrażenia.
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 zasad 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).
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-1.png?authuser=7&hl=pl)
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.
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-4.png?authuser=7&hl=pl)
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-6.png?authuser=7&hl=pl)
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-2.png?authuser=7&hl=pl)
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
如果您的应用以 Android 15(API 级别 35)或更高版本为目标平台,Configuration
否
不再包含系统栏。如果您使用
Configuration
类,您应将其替换为更好的
相应的 ViewGroup
、WindowInsets
或
WindowMetricsCalculator
,具体取决于您的需求。
Configuration
从 API 1 开始提供。它通常从
Activity.onConfigurationChanged
.它提供窗口密度、
屏幕方向和尺寸窗口大小的一个重要特征
Configuration
之前会排除系统栏。
配置大小通常用于选择资源,例如
/res/layout-h500dp
,这仍然是一个有效的用例。但将其用于
但一直不建议进行布局计算。如果需要,您应该将
现在离它远去。您应该使用 Configuration
具体取决于您的应用场景。
如果使用它来计算布局,请使用适当的 ViewGroup
,例如
CoordinatorLayout
或 ConstraintLayout
。如果使用该属性确定高度
,请使用 WindowInsets
。如果您想知道当前尺寸
,请使用 computeCurrentWindowMetrics
。
以下列表介绍了受此变更影响的字段:
Configuration.screenWidthDp
和screenHeightDp
尺寸不再 排除系统栏。Configuration.smallestScreenWidthDp
受到更改的间接影响 发送给screenWidthDp
和screenHeightDp
。Configuration.orientation
受到以下项的更改间接影响:screenWidthDp
和screenHeightDp
,在近似方形设备上显示。Display.getSize(Point)
会间接受到Configuration
。从 API 级别 30 开始,此 API 已废弃。- 从 API 级别 33 开始,
Display.getMetrics()
已采用这种方式。
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
.
![](https://developer.android.google.cn/static/about/versions/15/images/elegant-text-height-before.png?authuser=7&hl=pl)
elegantTextHeight
w przypadku aplikacji kierowanych na Androida 14 (poziom API 34) i starsze.![](https://developer.android.google.cn/static/about/versions/15/images/elegant-text-height-after.png?authuser=7&hl=pl)
elegantTextHeight
w przypadku aplikacji kierowanych na Androida 15.Zmiany szerokości obiektu TextView w przypadku złożonych kształtów liter
在以前的 Android 版本中,一些采用复杂形状的草体字体或语言可能会在上一个或下一个字符区域中绘制字母。在某些情况下,此类字母会在开始或结束位置被截断。从 Android 15 开始,TextView
会分配宽度来为此类字母绘制足够的空间,并允许应用请求左侧添加额外的内边距以防止被裁剪。
由于此变更会影响 TextView
确定宽度的方式,因此如果应用以 Android 15 或更高版本为目标平台,TextView
会默认分配更多宽度。您可以通过对 TextView
调用 setUseBoundsForWidth
API 来启用或停用此行为。
由于添加左侧内边距可能会导致现有布局未对齐,因此默认情况下,系统不会添加内边距,即使对于以 Android 15 或更高版本为目标平台的应用也是如此。不过,您可以通过调用 setShiftDrawingOffsetForStartOverhang
添加额外的内边距以防止裁剪。
以下示例展示了这些更改如何改进某些字体和语言的文本布局。
![](https://developer.android.google.cn/static/about/versions/15/images/cursive-clipped.png?authuser=7&hl=pl)
<TextView android:fontFamily="cursive" android:text="java" />
![](https://developer.android.google.cn/static/about/versions/15/images/cursive-noclipping.png?authuser=7&hl=pl)
<TextView android:fontFamily="cursive" android:text="java" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
![](https://developer.android.google.cn/static/about/versions/15/images/thai-clipped.png?authuser=7&hl=pl)
<TextView android:text="คอมพิวเตอร์" />
![](https://developer.android.google.cn/static/about/versions/15/images/thai-noclipping.png?authuser=7&hl=pl)
<TextView android:text="คอมพิวเตอร์" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
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:
![](https://developer.android.google.cn/static/about/versions/15/images/locale-aware-line-height-before.png?authuser=7&hl=pl)
EditText
, które mogą zawierać tekst w języku angielskim (en), japońskim (ja) i birmańskim (my). Wysokość wiersza EditText
jest taka sama, mimo że te języki różnią się wysokością wierszy.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:
![](https://developer.android.google.cn/static/about/versions/15/images/locale-aware-line-height-after.png?authuser=7&hl=pl)
EditText
, które mogą zawierać tekst w języku angielskim (en), japońskim (ja) i birmańskim (my). Wysokość elementu EditText
obejmuje teraz miejsce na domyślną wysokość wiersza dla czcionek w tych językach.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 kierowanych 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.