Podobnie jak w przypadku poprzednich wersji, Android 15 wprowadza zmiany w działaniu, które mogą mieć wpływ na Twoją aplikację. Poniższe zmiany dotyczą wyłącznie aplikacji kierowanych na Androida 15 lub nowszego. Jeśli Twoja aplikacja jest kierowana na Androida 15 lub nowszego, zmodyfikuj ją tak, aby prawidłowo obsługiwała te zachowania w odpowiednich przypadkach.
Zapoznaj się też z listą zmian w zachowaniu, które mają wpływ na wszystkie aplikacje działające na Androidzie 15, niezależnie od targetSdkVersion
aplikacji.
Główna funkcja
Android 15 modyfikuje lub rozszerza różne podstawowe funkcje systemu Android.
Zmiany w usługach działających na pierwszym planie
We are making the following changes to foreground services with Android 15.
- Data sync foreground service timeout behavior
- New media processing foreground service type
- Restrictions on
BOOT_COMPLETED
broadcast receivers launching foreground services - Restrictions on starting foreground services while an app holds the
SYSTEM_ALERT_WINDOW
permission
Data sync foreground service timeout behavior
Android 15 wprowadza nowe zachowanie dotyczące limitu czasu w przypadku dataSync
w aplikacjach kierowanych na Androida 15 (poziom interfejsu API 35) lub nowszego. Takie zachowanie dotyczy też nowego mediaProcessing
typu usługi działającej na pierwszym planie.
System zezwala na działanie usług dataSync
aplikacji przez łącznie 6 godzin w ciągu 24 godzin, po czym system wywołuje metodę Service.onTimeout(int, int)
(wprowadzoną w Androidzie 15). Obecnie usługa ma kilka sekund na wywołanie funkcji Service.stopSelf()
. Gdy wywołana zostanie usługa Service.onTimeout()
, nie będzie ona już usługą na pierwszym planie. Jeśli usługa nie wywołuje funkcji Service.stopSelf()
, system zgłasza wewnętrzny wyjątek. Wyjątek jest rejestrowany w Logcat z tym 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 z tą zmianą zachowania, możesz wykonać co najmniej jedną z tych czynności:
- Zaimplementuj nową metodę
Service.onTimeout(int, int)
w swojej usłudze. Gdy aplikacja otrzyma połączenie zwrotne, w ciągu kilku sekund zadzwoń pod numerstopSelf()
. Jeśli nie zatrzymasz aplikacji od razu, system wygeneruje błąd. - Upewnij się, że usługi
dataSync
w aplikacji nie działają dłużej niż 6 godzin w ciągu 24 godzin (chyba że użytkownik wchodzi w interakcję z aplikacją, resetując timer). - Uruchamiaj
dataSync
usługi na pierwszym planie wyłącznie w wyniku bezpośredniej interakcji z użytkownikiem. Ponieważ aplikacja znajduje się na pierwszym planie w momencie uruchomienia usługi, usługa ma pełne 6 godzin od uruchomienia w tle. - Zamiast usługi na pierwszym planie
dataSync
użyj alternatywnego interfejsu API.
Jeśli w ciągu ostatnich 24 godzin usługi dataSync
na pierwszym planie Twojej aplikacji działały przez 6 godzin, nie możesz uruchomić innej usługi dataSync
na pierwszym planie chyba że użytkownik przełączył aplikację na pierwszy plan (co spowoduje zresetowanie minutnika). Jeśli spróbujesz uruchomić inną usługę dataSync
na pierwszym planie, system wyświetli komunikat o błędzie, np. „Czas limitu został już wyczerpany dla usługi na pierwszym planie typu dataSync”.ForegroundServiceStartNotAllowedException
Testowanie
Aby przetestować działanie aplikacji, możesz włączyć limity czasu synchronizacji danych, nawet jeśli aplikacja nie jest kierowana na Androida 15 (o ile jest uruchomiona 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, aby łatwiej testować działanie aplikacji po osiągnięciu limitu. Aby ustawić nowy okres oczekiwania, uruchom to polecenie adb
:
adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds
New media processing foreground service type
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 multimedialna może pobrać plik audio i przed odtworzeniem musi przekonwertować go na inny format. Możesz użyć usługi mediaProcessing
na pierwszym planie, aby mieć pewność, że konwersja będzie kontynuowana nawet wtedy, gdy aplikacja będzie 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). Obecnie usługa ma kilka sekund na wywołanie funkcji Service.stopSelf()
. Jeśli usługa nie wywołuje funkcji Service.stopSelf()
, system zgłasza wewnętrzny wyjątek. 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:
- Zaimplementuj nową metodę
Service.onTimeout(int, int)
w swojej usłudze. Gdy aplikacja otrzyma połączenie zwrotne, w ciągu kilku sekund zadzwoń pod numerstopSelf()
. (jeśli nie zatrzymasz aplikacji od razu, system wygeneruje błąd). - Upewnij się, że usługi
mediaProcessing
w aplikacji nie działają dłużej niż 6 godzin w ciągu 24 godzin (chyba że użytkownik wchodzi w interakcję z aplikacją, zresetowując w ten sposób timer). - Uruchamiaj usługi na pierwszym planie
mediaProcessing
tylko w wyniku bezpośredniej interakcji z użytkownikiem. Ponieważ aplikacja jest na pierwszym planie, gdy usługa się uruchamia, ma ona 6 godzin na działanie po przejściu aplikacji w tło. - Zamiast usługi na pierwszym planie
mediaProcessing
użyj alternatywnego interfejsu API, takiego jak WorkManager.
Jeśli w ciągu ostatnich 24 godzin usługi mediaProcessing
na pierwszym planie aplikacji działały przez 6 godzin, nie możesz uruchomić innej usługi mediaProcessing
na pierwszym planie chyba że użytkownik przełączył aplikację na pierwszy plan (co spowoduje zresetowanie minutnika). Jeśli spróbujesz uruchomić inną usługę działającą na pierwszym planie mediaProcessing
, system wyświetli komunikat o błędzie podobny do „Czas limitu usługi działającej na pierwszym planie typu mediaProcessing został już wykorzystany”.ForegroundServiceStartNotAllowedException
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 jest uruchomiona 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ć czas oczekiwania, aby łatwiej testować działanie aplikacji po osiągnięciu limitu. Aby ustawić nowy okres oczekiwania, uruchom to polecenie adb
:
adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds
Restrictions on BOOT_COMPLETED
broadcast receivers launching foreground services
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
Restrictions on starting foreground services while an app holds the SYSTEM_ALERT_WINDOW
permission
Previously, if an app held the SYSTEM_ALERT_WINDOW
permission, it could launch
a foreground service even if the app was currently in the background (as
discussed in exemptions from background start restrictions).
If an app targets Android 15, this exemption is now narrower. The app now needs
to have the SYSTEM_ALERT_WINDOW
permission and also have a visible overlay
window. That is, the app needs to first launch a
TYPE_APPLICATION_OVERLAY
window and the window
needs to be visible before you start a foreground service.
If your app attempts to start a foreground service from the background without
meeting these new requirements (and it does not have some other exemption), the
system throws ForegroundServiceStartNotAllowedException
.
If your app declares the SYSTEM_ALERT_WINDOW
permission
and launches foreground services from the background, it may be affected by this
change. If your app gets a ForegroundServiceStartNotAllowedException
, check
your app's order of operations and make sure your app already has an active
overlay window before it attempts to start a foreground service from the
background. You can check if your overlay window is currently visible
by calling View.getWindowVisibility()
, or you
can override View.onWindowVisibilityChanged()
to get notified whenever the visibility changes.
Testing
To test your app's behavior, you can enable these new restrictions even if your
app is not targeting Android 15 (as long as the app is running on an Android 15
device). To enable these new restrictions on starting foreground services
from the background, run the following adb
command:
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 (poziom API 35) lub nowszego nie mogą już zmieniać globalnego stanu ani zasad trybu Nie przeszkadzać na urządzeniu (ani przez modyfikowanie ustawień użytkownika, ani przez wyłączanie trybu Nie przeszkadzać). Zamiast tego aplikacje muszą przekazać AutomaticZenRule
, które system połączy w globalne zasady z dotychczasowym schematem „najbardziej restrykcyjne zasady wygrywają”. Wywołania istniejących interfejsów API, które wcześniej wpływały na stan globalny (setInterruptionFilter
,
setNotificationPolicy
), powodują utworzenie lub zaktualizowanie niejawnego AutomaticZenRule
, który jest włączany i wyłączany w zależności od cyklu wywołań tych interfejsów API.
Pamiętaj, że ta zmiana wpływa tylko na obserwowalne zachowanie, jeśli aplikacja wywołuje funkcję setInterruptionFilter(INTERRUPTION_FILTER_ALL)
i oczekuje, że ta funkcja dezaktywuje AutomaticZenRule
, który został wcześniej aktywowany przez właścicieli.
Zmiany w interfejsie OpenJDK API
Android 15 continues the work of refreshing Android's core libraries to align with the features in the latest OpenJDK LTS releases.
Some of these changes can affect app compatibility for apps targeting Android 15 (API level 35):
Changes to string formatting APIs: Validation of argument index, flags, width, and precision are now more strict when using the following
String.format()
andFormatter.format()
APIs:String.format(String, Object[])
String.format(Locale, String, Object[])
Formatter.format(String, Object[])
Formatter.format(Locale, String, Object[])
For example, the following exception is thrown when an argument index of 0 is used (
%0
in the format string):IllegalFormatArgumentIndexException: Illegal format argument index = 0
In this case, the issue can be fixed by using an argument index of 1 (
%1
in the format string).Changes to component type of
Arrays.asList(...).toArray()
: When usingArrays.asList(...).toArray()
, the component type of the resulting array is now anObject
—not the type of the underlying array's elements. So the following code throws aClassCastException
:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
For this case, to preserve
String
as the component type in the resulting array, you could useCollection.toArray(Object[])
instead:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
Changes to language code handling: When using the
Locale
API, language codes for Hebrew, Yiddish, and Indonesian are no longer converted to their obsolete forms (Hebrew:iw
, Yiddish:ji
, and Indonesian:in
). When specifying the language code for one of these locales, use the codes from ISO 639-1 instead (Hebrew:he
, Yiddish:yi
, and Indonesian:id
).Changes to random int sequences: Following the changes made in https://bugs.openjdk.org/browse/JDK-8301574, the following
Random.ints()
methods now return a different sequence of numbers than theRandom.nextInt()
methods do:Generally, this change shouldn't result in app-breaking behavior, but your code shouldn't expect the sequence generated from
Random.ints()
methods to matchRandom.nextInt()
.
The new SequencedCollection
API can affect your app's compatibility
after you update compileSdk
in your app's build configuration to use
Android 15 (API level 35):
Collision with
MutableList.removeFirst()
andMutableList.removeLast()
extension functions inkotlin-stdlib
The
List
type in Java is mapped to theMutableList
type in Kotlin. Because theList.removeFirst()
andList.removeLast()
APIs have been introduced in Android 15 (API level 35), the Kotlin compiler resolves function calls, for examplelist.removeFirst()
, statically to the newList
APIs instead of to the extension functions inkotlin-stdlib
.If an app is re-compiled with
compileSdk
set to35
andminSdk
set to34
or lower, and then the app is run on Android 14 and lower, a runtime error is thrown:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
The existing
NewApi
lint option in Android Gradle Plugin can catch these new API usages../gradlew lint
MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi] list.removeFirst()To fix the runtime exception and lint errors, the
removeFirst()
andremoveLast()
function calls can be replaced withremoveAt(0)
andremoveAt(list.lastIndex)
respectively in Kotlin. If you're using Android Studio Ladybug | 2024.1.3 or higher, it also provides a quick fix option for these errors.Consider removing
@SuppressLint("NewApi")
andlintOptions { disable 'NewApi' }
if the lint option has been disabled.Collision with other methods in Java
New methods have been added into the existing types, for example,
List
andDeque
. These new methods might not be compatible with the methods with the same name and argument types in other interfaces and classes. In the case of a method signature collision with incompatibility, thejavac
compiler outputs a build-time error. For example:Example error 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 ListExample error 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 errorExample error 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 errorTo fix these build errors, the class implementing these interfaces should override the method with a compatible return type. For example:
@Override public Object getFirst() { return List.super.getFirst(); }
Bezpieczeństwo
Android 15 zawiera zmiany, które zwiększają bezpieczeństwo systemu, aby chronić aplikacje i użytkowników przed złośliwymi aplikacjami.
Ograniczone wersje protokołu TLS
Android 15 ogranicza użycie TLS w wersjach 1.0 i 1.1. Te wersje zostały wcześniej wycofane w Androidzie, ale teraz są niedozwolone w przypadku aplikacji kierowanych na Androida 15.
Zabezpieczone uruchamianie 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 zamiary
Android 15 wprowadza nowe opcjonalne środki bezpieczeństwa, które zwiększają bezpieczeństwo i stabilność intencji. Te zmiany mają na celu zapobieganie potencjalnym luk w zabezpieczeniach i niewłaściwemu wykorzystywaniu intencji, które mogą być wykorzystywane przez złośliwe aplikacje. W Androidzie 15 wprowadziliśmy 2 główne ulepszenia dotyczące bezpieczeństwa intencji:
- Pasowanie do docelowych filtrów intencji: intencje kierowane na konkretne komponenty muszą dokładnie odpowiadać specyfikacji filtrów intencji docelowych. Jeśli wysyłasz intencję, aby uruchomić działanie innej aplikacji, docelowy komponent intencji musi być zgodny z deklarowanymi filtrami intencji działania odbierającego.
- Intencje muszą mieć działania: intencje bez działania nie będą już pasować do żadnych filtrów intencji. Oznacza to, że intencje używane do uruchamiania działań lub usług muszą mieć wyraźnie zdefiniowane działanie.
Aby sprawdzić, jak Twoja aplikacja reaguje na te zmiany, użyj w niej metody StrictMode
. Aby wyświetlić szczegółowe dzienniki dotyczące naruszeń zasad Intent
, dodaj tę metodę:
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() .detectUnsafeIntentLaunch() .build() ) }
Java
public void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() .detectUnsafeIntentLaunch() .build()); }
Interfejs użytkownika i systemu
Android 15 zawiera kilka zmian, które mają na celu zapewnienie bardziej spójnej i intuicyjnej obsługi.
Zmiany w oknie wstawki
W Androidzie 15 wprowadzono 2 zmiany związane z współrzędnymi okna: domyślnie wymuszono tryb pełnoekranowy, a także wprowadzono zmiany konfiguracji, takie jak domyślna konfiguracja pasków systemowych.
Edge-to-edge enforcement
Apps are edge-to-edge by default on devices running Android 15 if the app is targeting Android 15 (API level 35).

This is a breaking change that might negatively impact your app's UI. The changes affect the following UI areas:
- Gesture handle navigation bar
- Transparent by default.
- Bottom offset is disabled so content draws behind the system navigation bar unless insets are applied.
setNavigationBarColor
andR.attr#navigationBarColor
are deprecated and don't affect gesture navigation.setNavigationBarContrastEnforced
andR.attr#navigationBarContrastEnforced
continue to have no effect on gesture navigation.
- 3-button navigation
- Opacity set to 80% by default, with color possibly matching the window background.
- Bottom offset disabled so content draws behind the system navigation bar unless insets are applied.
setNavigationBarColor
andR.attr#navigationBarColor
are set to match the window background by default. The window background must be a color drawable for this default to apply. This API is deprecated but continues to affect 3-button navigation.setNavigationBarContrastEnforced
andR.attr#navigationBarContrastEnforced
is true by default, which adds an 80% opaque background across 3-button navigation.
- Status bar
- Transparent by default.
- The top offset is disabled so content draws behind the status bar unless insets are applied.
setStatusBarColor
andR.attr#statusBarColor
are deprecated and have no effect on Android 15.setStatusBarContrastEnforced
andR.attr#statusBarContrastEnforced
are deprecated but still have an effect on Android 15.
- Display cutout
layoutInDisplayCutoutMode
of non-floating windows must beLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
.SHORT_EDGES
,NEVER
, andDEFAULT
are interpreted asALWAYS
so that users don't see a black bar caused by the display cutout and appear edge-to-edge.
The following example shows an app before and after targeting Android 15 (API level 35), and before and after applying insets.



What to check if your app is already edge-to-edge
If your app is already edge-to-edge and applies insets, you are mostly unimpacted, except in the following scenarios. However, even if you think you aren't impacted, we recommend you test your app.
- You have a non-floating window, such as an
Activity
that usesSHORT_EDGES
,NEVER
orDEFAULT
instead ofLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
. If your app crashes on launch, this might be due to your splashscreen. You can either upgrade the core splashscreen dependency to 1.2.0-alpha01 or later or setwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
. - There might be lower-traffic screens with occluded UI. Verify these
less-visited screens don't have occluded UI. Lower-traffic screens include:
- Onboarding or sign-in screens
- Settings pages
What to check if your app is not already edge-to-edge
If your app is not already edge-to-edge, you are most likely impacted. In addition to the scenarios for apps that are already edge-to-edge, you should consider the following:
- If your app uses Material 3 Components (
androidx.compose.material3
) in compose, such asTopAppBar
,BottomAppBar
, andNavigationBar
, these components are likely not impacted because they automatically handle insets. - If your app is using Material 2 Components (
androidx.compose.material
) in Compose, these components don't automatically handle insets. However, you can get access to the insets and apply them manually. In androidx.compose.material 1.6.0 and later, use thewindowInsets
parameter to apply the insets manually forBottomAppBar
,TopAppBar
,BottomNavigation
, andNavigationRail
. Likewise, use thecontentWindowInsets
parameter forScaffold
. - If your app uses views and Material Components
(
com.google.android.material
), most views-based Material Components such asBottomNavigationView
,BottomAppBar
,NavigationRailView
, orNavigationView
, handle insets and require no additional work. However, you need to addandroid:fitsSystemWindows="true"
if usingAppBarLayout
. - For custom composables, apply the insets manually as padding. If your
content is within a
Scaffold
, you can consume insets using theScaffold
padding values. Otherwise, apply padding using one of theWindowInsets
. - If your app is using views and
BottomSheet
,SideSheet
or custom containers, apply padding usingViewCompat.setOnApplyWindowInsetsListener
. ForRecyclerView
, apply padding using this listener and also addclipToPadding="false"
.
What to check if your app must offer custom background protection
If your app must offer custom background protection to 3-button navigation or
the status bar, your app should place a composable or view behind the system bar
using WindowInsets.Type#tappableElement()
to get the 3-button
navigation bar height or WindowInsets.Type#statusBars
.
Additional edge-to-edge resources
See the Edge to Edge Views and Edge to Edge Compose guides for additional considerations on applying insets.
Deprecated APIs
The following APIs are deprecated but not disabled:
R.attr#enforceStatusBarContrast
R.attr#navigationBarColor
(for 3 button navigation, with 80% alpha)Window#isStatusBarContrastEnforced
Window#setNavigationBarColor
(for 3 button navigation, with 80% alpha)Window#setStatusBarContrastEnforced
The following APIs are deprecated and disabled:
R.attr#navigationBarColor
(for gesture navigation)R.attr#navigationBarDividerColor
R.attr#statusBarColor
Window#setDecorFitsSystemWindows
Window#getNavigationBarColor
Window#getNavigationBarDividerColor
Window#getStatusBarColor
Window#setNavigationBarColor
(for gesture navigation)Window#setNavigationBarDividerColor
Window#setStatusBarColor
Stable configuration
Jeśli Twoja aplikacja jest kierowana na Androida 15 (API na poziomie 35) lub nowszego, Configuration
nie wyklucza już pasków systemowych. Jeśli używasz rozmiaru ekranu w klasie Configuration
do obliczania układu, zastąp go lepszymi alternatywami, takimi jak odpowiedni ViewGroup
, WindowInsets
lub WindowMetricsCalculator
w zależności od potrzeb.
Configuration
jest dostępny od API 1. Zwykle jest ona uzyskiwana z Activity.onConfigurationChanged
. Zawiera informacje takie jak gęstość okien, orientacja i rozmiary. Ważną cechą rozmiarów okien zwracanych przez Configuration
jest to, że wcześniej wykluczały one paski systemowe.
Rozmiar konfiguracji jest zwykle używany do wyboru zasobów, np. /res/layout-h500dp
, i nadal jest to prawidłowy przypadek użycia. Jednak używanie go do obliczania układu zawsze było odradzane. Jeśli tak jest, odsuń się od niego. Zamiast Configuration
użyj bardziej odpowiedniego elementu, w zależności od konkretnego przypadku użycia.
Jeśli używasz go do obliczania układu, użyj odpowiedniego ViewGroup
, np. CoordinatorLayout
lub ConstraintLayout
. Jeśli używasz go do określania wysokości paska nawigacyjnego systemu, użyj WindowInsets
. Jeśli chcesz poznać bieżący rozmiar okna aplikacji, użyj computeCurrentWindowMetrics
.
Poniżej znajdziesz listę pól, których dotyczy ta zmiana:
- Rozmiary
Configuration.screenWidthDp
iscreenHeightDp
nie wykluczają już pasków systemowych. Configuration.smallestScreenWidthDp
jest pośrednio powiązana ze zmianami wscreenWidthDp
iscreenHeightDp
.- Na
Configuration.orientation
pośrednio wpływają zmiany wscreenWidthDp
iscreenHeightDp
na urządzeniach o proporcjach zbliżonych do kwadratu. Display.getSize(Point)
jest pośrednio objęty zmianami wConfiguration
. Zostało to wycofane od poziomu interfejsu API 30.Display.getMetrics()
działa w ten sposób od poziomu API 33.
Atrybut elegantTextHeight ma domyślnie wartość true.
W przypadku aplikacji przeznaczonych na Androida 15 (poziom interfejsu API 35) atrybut elegantTextHeight
TextView
domyślnie staje się true
, co zastępuje czcionkę kompaktową używaną domyślnie w niektórych skryptach, które mają duże wymiary pionowe, czcionką o znacznie lepszej czytelności.
Czcionka kompaktowa została wprowadzona, aby zapobiec rozmieszczaniu elementów układu. Android 13 (poziom interfejsu API 33) zapobiega wielu takim problemom, ponieważ pozwala na rozciąganie wysokości układu tekstu za pomocą atrybutu fallbackLineSpacing
.
W Androidzie 15 czcionka kompaktowa nadal pozostaje w systemie, więc aplikacja może ustawić wartość elegantTextHeight
na false
, aby uzyskać takie samo działanie jak wcześniej, ale jest mało prawdopodobne, aby była obsługiwana w przyszłych wersjach. Jeśli Twoja aplikacja obsługuje te pismo: arabski, kannada, oriya, tamilski, telugu, gudżarati, malajalam, birmański, gudźarati, kannada, malajalam, oriya, telugu lub tajski, przetestuj ją, ustawiając wartość elegantTextHeight
na true
.

elegantTextHeight
dla aplikacji kierowanych na Androida 14 (poziom API 34) i starszego.
elegantTextHeight
zachowanie w przypadku aplikacji kierowanych na Androida 15.Szerokość widoku TextView zmienia się w przypadku złożonych kształtów liter
W poprzednich wersjach Androida niektóre czcionki kursywe lub języki ze złożonym kształtem mogą rysować litery w obszarze poprzedniego lub następnego znaku.
Zdarzało się, że takie litery były obcinane na początku lub na końcu.
Od Androida 15 TextView
przydziela wystarczającą ilość miejsca na wyświetlenie takich liter, a aplikacje mogą prosić o dodatkowe wypełnienie po lewej stronie, aby zapobiec przycięciu.
Ta zmiana wpływa na sposób określania szerokości przez TextView
, więc TextView
domyślnie przydziela więcej szerokości, jeśli aplikacja jest kierowana na Androida 15 (poziom API 35) lub nowszego. Możesz włączyć lub wyłączyć tę funkcję, wywołując interfejs API setUseBoundsForWidth
w komponencie TextView
.
Dodanie dopełnienia z lewej strony może spowodować niewłaściwe ułożenie istniejących układów, dlatego dopełnienie nie jest dodawane domyślnie nawet w przypadku aplikacji kierowanych na Androida 15 lub nowszego.
Możesz jednak dodać dodatkowy margines, aby zapobiec przycięciu, wywołując funkcję setShiftDrawingOffsetForStartOverhang
.
W poniższych przykładach pokazujemy, jak te zmiany mogą poprawić układ tekstu w przypadku niektórych czcionek i języków.

<TextView android:fontFamily="cursive" android:text="java" />

<TextView android:fontFamily="cursive" android:text="java" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />

<TextView android:text="คอมพิวเตอร์" />

<TextView android:text="คอมพิวเตอร์" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
Domyślna wysokość wiersza w elemencie EditText dostosowana do ustawień regionalnych
W poprzednich wersjach Androida układ tekstu rozciągał wysokość tekstu, aby dopasować ją do wysokości wiersza czcionki odpowiadającej bieżącemu ustawieniu języka. Jeśli na przykład treści były w języku japońskim, to ze względu na to, że wysokość linii czcionki japońskiej jest nieco większa niż czcionki łacińskiej, wysokość tekstu była nieco większa. Jednak pomimo tych różnic w wysokościach wierszy element EditText
miał jednakowy rozmiar niezależnie od używanej lokalizacji, jak pokazano na poniższym obrazku:

EditText
, które mogą zawierać tekst w języku angielskim (en), japońskim (ja) i birmańskim (my). Wysokość EditText
jest taka sama, mimo że te języki mają różne wysokości linii.W przypadku aplikacji kierowanych na Androida 15 (poziom interfejsu API 35) minimalna wysokość linii jest teraz zarezerwowana dla EditText
, aby pasowała do czcionki referencyjnej dla określonego języka, jak pokazano na poniższym obrazie:

EditText
, które mogą zawierać tekst w języku angielskim (en), japońskim (ja) i birmańskim (my). Wysokość EditText
uwzględnia teraz miejsce na domyślną wysokość wiersza dla czcionek w tych językach.W razie potrzeby aplikacja może przywrócić poprzednie działanie, ustawiając atrybut useLocalePreferredLineHeightForMinimum
na false
. Może też ustawić niestandardowe minimalne dane pionowe za pomocą interfejsu API setMinimumFontMetrics
w językach Kotlin i Java.
Aparat i multimedia
Android 15 wprowadza te zmiany w działaniu aplikacji w zakresie kamery i multimediów, które są kierowane na Androida 15 lub nowszego.
Ograniczenia dotyczące żądania fokusu audio
Apps that target Android 15 (API level 35) must be the top app or running a
foreground service in order to request audio focus. If an app
attempts to request focus when it does not meet one of these requirements, the
call returns AUDIOFOCUS_REQUEST_FAILED
.
You can learn more about audio focus at Manage audio focus.
Zaktualizowane ograniczenia dotyczące interfejsów API innych niż SDK
Android 15 zawiera zaktualizowane listy ograniczonych interfejsów innych niż SDK, które powstały na podstawie współpracy z deweloperami Androida i najnowszych testów wewnętrznych. W miarę możliwości przed ograniczeniem interfejsów innych niż SDK udostępniamy publiczne alternatywy.
Jeśli Twoja aplikacja nie jest kierowana na Androida 15, niektóre z tych zmian mogą nie mieć na Ciebie natychmiastowego wpływu. Jednak chociaż Twoja aplikacja może mieć dostęp do niektórych interfejsów spoza SDK w zależności od docelowego poziomu interfejsu API, używanie dowolnej metody lub pola spoza SDK zawsze wiąże się z wysokim ryzykiem awarii aplikacji.
Jeśli nie masz pewności, czy Twoja aplikacja używa interfejsów innych niż SDK, możesz to sprawdzić, testując aplikację. Jeśli Twoja aplikacja korzysta z interfejsów spoza SDK, zacznij planować migrację do alternatywnych pakietów SDK. Zdajemy sobie jednak sprawę, że w przypadku niektórych aplikacji używanie interfejsów innych niż SDK jest uzasadnione. Jeśli nie możesz znaleźć alternatywy dla używania interfejsu innego niż SDK w przypadku funkcji w aplikacji, poproś o nowy publiczny interfejs API.
Więcej informacji o zmianach w tej wersji Androida znajdziesz w artykule Zmiany ograniczeń interfejsu niebędącego interfejsem SDK w Androidzie 15. Więcej informacji o interfejsach innych niż SDK znajdziesz w artykule Ograniczenia interfejsów innych niż SDK.