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 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
Androida w wersji 15 lub nowszej. To zachowanie dotyczy również nowej wersji mediaProcessing
typ usługi na pierwszym planie.
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ć nowe ograniczenia, nawet jeśli
aplikacja nie jest kierowana na Androida 15 (o ile działa na Androidzie 15),
urządzenia). 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ć
以 Android 15 为目标平台的应用无法再更改设备上的全局状态或勿扰 (DND) 政策(通过修改用户设置或关闭 DND 模式)。相反,应用必须提供一个 AutomaticZenRule
,系统会将后者合并到一个具有现有最严格的政策胜出方案的全局政策中。调用之前影响全局状态的现有 API(setInterruptionFilter
、setNotificationPolicy
)会导致创建或更新隐式 AutomaticZenRule
,该 AutomaticZenRule
根据这些 API 调用的调用周期而开启或关闭。
请注意,只有在应用调用 setInterruptionFilter(INTERRUPTION_FILTER_ALL)
且预期调用会停用之前由其所有者激活的 AutomaticZenRule
时,此变更才会影响可观察的行为。
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(); }
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 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. Uruchamianie aktywności w tle jest ograniczone od Android 10 (poziom API 29).
Blokuj uruchamianie aktywności aplikacjom, które nie pasują do górnego identyfikatora UID w 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” atak omija obecne ograniczenia uruchamiania w tle, ponieważ
występuje w ramach tego samego widocznego zadania. Aby ograniczyć to ryzyko, Android 15 dodaje
flaga blokująca uruchamianie aplikacji, które nie są zgodne z górnym identyfikatorem UID w stosie
aktywności. 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 zabezpieczenia są włączone, aplikacje mogą wrócić do ekranu głównego, jako ostatnia widoczna aplikacja, jeśli ukończy ona swoje zadanie.
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ślny. 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 zostało jako ostatnia aktywność. Ponadto, jeśli aktywność inna niż główna zakończy swoje zadanie, Android powrót do ekranu głównego; Nie zablokuje ono zakończenia reklamy działania.
- 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 引入了新的安全措施,可让 intent 更加安全且更安全 稳健。这些变更旨在防范潜在的漏洞和 可能会被恶意应用利用的 intent 滥用。有两个主要的 Android 15 中对 intent 安全性的改进:
- 匹配目标 intent 过滤器:针对特定组件的 intent 准确匹配目标的 intent 过滤器规范。如果您发送 intent 来启动另一个应用的 activity,则目标 intent 组件需要 与接收 activity 声明的 intent 过滤器保持一致。
- intent 必须具有操作:没有操作的 intent 将不再匹配 任何 intent 过滤器。也就是说,用于启动 activity 或 服务都必须有明确定义的操作。
- 待处理 intent:待处理 intent 的创建者为 被视为封装 intent 的发送者,而非待处理 intent 的发送者 意图
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
在搭载 Android 15 的设备上,应用会默认采用全屏 以 Android 15(API 级别 35)为目标平台。
<ph type="x-smartling-placeholder">![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-1.png?authuser=9&hl=pl)
这是一项可能会对应用的界面产生负面影响的破坏性更改。通过 更改会影响以下界面区域:
- 手势手柄导航栏
- 默认透明。
- 底部偏移量已停用,因此内容绘制在系统导航栏后面 栏。
setNavigationBarColor
和R.attr#navigationBarColor
已弃用,不会影响手势导航。setNavigationBarContrastEnforced
和R.attr#navigationBarContrastEnforced
不会对 手势导航。
- “三按钮”导航
- 默认不透明度设为 80%,颜色可能与窗口一致 背景。
- 底部偏移值已停用,因此内容绘制在系统导航栏后面 除非应用了边衬区。
setNavigationBarColor
和R.attr#navigationBarColor
默认设置为与窗口背景匹配。窗口背景 必须是颜色可绘制对象,才能应用此默认值。此 API 是 但会继续影响“三按钮”导航。setNavigationBarContrastEnforced
和R.attr#navigationBarContrastEnforced
默认为 true,这会添加一个 “三按钮”导航模式显示 80% 不透明的背景。
- 状态栏
- 默认透明。
- 顶部偏移量已停用,因此除非 边衬区。
setStatusBarColor
和R.attr#statusBarColor
已废弃,对 Android 15 没有任何影响。setStatusBarContrastEnforced
和R.attr#statusBarContrastEnforced
已弃用,但仍具有 对 Android 15 的影响。
- 刘海屏
layoutInDisplayCutoutMode
的非浮动窗口必须是LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
。SHORT_EDGES
、NEVER
和 系统会将DEFAULT
解读为ALWAYS
,这样用户就不会看到黑色图标 长条形尺寸,显示为无边框。
以下示例展示了定位前和定位后的应用 Android 15(API 级别 35)以及应用边衬区之前和之后。
<ph type="x-smartling-placeholder">![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-4.png?authuser=9&hl=pl)
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-6.png?authuser=9&hl=pl)
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-2.png?authuser=9&hl=pl)
检查应用是否已采用全屏的检查步骤
如果您的应用已经采用无边框且应用了边衬区, 基本未受影响,但下列情况除外。但即使您认为 您不会受到影响,但我们建议您测试自己的应用。
- 您的非浮动窗口(例如
Activity
)使用SHORT_EDGES
、NEVER
或DEFAULT
,而不是LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
。如果您的应用在启动时崩溃 可能是启动画面所致您可以升级核心 初始屏幕依赖项更改为 1.2.0-alpha01 或更高版本,或者设置window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
。 - 可能会有流量较低的屏幕显示被遮挡的界面。验证这些
访问较少的屏幕也不会显示被遮挡的界面。流量较低的屏幕包括:
<ph type="x-smartling-placeholder">
- </ph>
- 初始配置或登录屏幕
- “设置”页面
如何检查应用尚未实现无边框
如果您的应用还没有全面屏,那么您很可能会受到影响。在 除了针对已经采用无边框的应用的情况之外, 请考虑以下事项:
- 如果您的应用使用 Material 3 组件 (
androidx.compose.material3
),例如TopAppBar
,BottomAppBar
和NavigationBar
,那么这些组件可能不 会受到影响,因为它们会自动处理边衬区。 - 如果您的应用使用 Material 2 组件 (
androidx.compose.material
),那么这些组件 不会自动处理边衬区。不过,您可以使用边衬区 并手动应用这些设置在 androidx.compose.material 1.6.0 中 然后使用windowInsets
参数手动应用边衬区BottomAppBar
、TopAppBar
、BottomNavigation
和NavigationRail
。 同样,对以下内容使用contentWindowInsets
形参:Scaffold
。 - 如果您的应用使用视图和 Material 组件
(
com.google.android.material
),大多数基于 View 的 Material 如BottomNavigationView
、BottomAppBar
、NavigationRailView
或NavigationView
,处理边衬区,不需要 额外工作。但是,您需要将android:fitsSystemWindows="true"
如果使用AppBarLayout
,则会发生此错误。 - 对于自定义可组合项,请手动将边衬区作为内边距应用。如果您的
内容位于
Scaffold
内,因此您可以使用Scaffold
来使用边衬区 内边距值。否则,使用WindowInsets
。 - 如果您的应用使用的是视图和
BottomSheet
、SideSheet
或自定义 使用ViewCompat.setOnApplyWindowInsetsListener
。对于RecyclerView
,使用此监听器应用内边距,同时添加clipToPadding="false"
。
检查应用是否必须提供自定义后台保护的注意事项
如果您的应用必须为“三按钮”导航或
状态栏,则应用应将可组合项或视图放在系统栏后面
使用 WindowInsets.Type#tappableElement()
获取三按钮
导航栏高度或 WindowInsets.Type#statusBars
。
其他无边框资源
请参阅无边框视图和无边框 Compose 了解应用边衬区的其他注意事项。
已弃用的 API
以下 API 现已弃用:
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 interfejsu API 35) lub nowszego, Configuration
nie
nie uwzględnia słupków systemowych. Jeśli użyjesz rozmiaru ekranu w
Configuration
do obliczania układu, zastąp ją lepszym
alternatywne opcje, takie jak odpowiednie ViewGroup
, WindowInsets
lub
WindowMetricsCalculator
w zależności od potrzeb.
Interfejs Configuration
jest dostępny od wersji API 1. Zazwyczaj jest pozyskiwany
Activity.onConfigurationChanged
Dostarcza informacji takich jak gęstość okien,
orientacja i rozmiary. 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. Jednak użycie go
obliczanie układu zawsze jest odradzane. W takim przypadku
z dala od siebie. Wyrażenie Configuration
należy zastąpić czymś
w zależności od konkretnego przypadku użycia.
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 są już dostępne słupki systemowe. - Zmiany wpływają pośrednio na usługę
Configuration.smallestScreenWidthDp
doscreenWidthDp
iscreenHeightDp
. - Pośredni wpływ na usługę
Configuration.orientation
mają zmiany w usługachscreenWidthDp
iscreenHeightDp
na urządzeniach o zbliżonym kształcie. - Platforma
Display.getSize(Point)
ma pośredni wpływ na zmiany wConfiguration
Jest ono wycofywane od poziomu interfejsu API 30. - Funkcja
Display.getMetrics()
działa już w ten sposób od poziomu interfejsu 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
.
![](https://developer.android.google.cn/static/about/versions/15/images/elegant-text-height-before.png?authuser=9&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=9&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
确定宽度的方式,因此 TextView
如果应用以 Android 15 或更高版本为目标平台,则默认分配更多宽度。您可以
通过对以下对象调用 setUseBoundsForWidth
API 来启用或停用此行为:
TextView
。
由于添加左侧内边距可能会导致现有布局出现错位,
默认情况下,系统不会添加内边距,即使是以 Android 15 或更高版本为目标平台的应用也是如此。
不过,您可以通过调用
setShiftDrawingOffsetForStartOverhang
。
以下示例展示了这些更改可如何改进某些客户的文本布局 字体和语言。
![](https://developer.android.google.cn/static/about/versions/15/images/cursive-clipped.png?authuser=9&hl=pl)
<TextView android:fontFamily="cursive" android:text="java" />
![](https://developer.android.google.cn/static/about/versions/15/images/cursive-noclipping.png?authuser=9&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=9&hl=pl)
<TextView android:text="คอมพิวเตอร์" />
![](https://developer.android.google.cn/static/about/versions/15/images/thai-noclipping.png?authuser=9&hl=pl)
<TextView android:text="คอมพิวเตอร์" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
Domyślna wysokość wiersza z uwzględnieniem języka dla interfejsu EditText
在以前的 Android 版本中,文本布局拉伸了文本的高度,使其适应与当前语言区域匹配的字体的行高。例如,如果内容是日语,由于日语字体的行高比拉丁字体的行高略大,因此文本的高度就略大了。不过,尽管行高存在这些差异,但无论使用何种语言区域,EditText
元素的大小都是一致的,如下图所示:
![](https://developer.android.google.cn/static/about/versions/15/images/locale-aware-line-height-before.png?authuser=9&hl=pl)
EditText
元素的框,这些框可以包含英语 (en)、日语 (ja) 和缅甸语 (my) 的文本。EditText
的高度相同,即使这两种语言的行高不同。对于以 Android 15 为目标平台的应用,系统现在会为 EditText
预留最小行高,以匹配指定语言区域的参考字体,如下图所示:
![](https://developer.android.google.cn/static/about/versions/15/images/locale-aware-line-height-after.png?authuser=9&hl=pl)
EditText
元素的框,这些框可以包含英语 (en)、日语 (ja) 和缅甸语 (my) 的文本。EditText
的高度现在包含空间,可适应这些语言字体的默认行高。如果需要,您的应用可以通过将 useLocalePreferredLineHeightForMinimum
属性设置为 false
来恢复之前的行为,并且可以通过 Kotlin 和 Java 中的 setMinimumFontMetrics
API 设置自定义最小行业指标。
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 includes updated lists of restricted non-SDK interfaces based on collaboration with Android developers and the latest internal testing. Whenever possible, we make sure that public alternatives are available before we restrict non-SDK interfaces.
If your app does not target Android 15, some of these changes might not immediately affect you. However, while it's possible for your app to access some non-SDK interfaces depending on your app's target API level, using any non-SDK method or field always carries a high risk of breaking your app.
If you are unsure if your app uses non-SDK interfaces, you can test your app to find out. If your app relies on non-SDK interfaces, you should begin planning a migration to SDK alternatives. Nevertheless, we understand that some apps have valid use cases for using non-SDK interfaces. If you can't find an alternative to using a non-SDK interface for a feature in your app, you should request a new public 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.