Zmiany w działaniu: aplikacje kierowane na Androida 15 lub nowszego

Podobnie jak w poprzednich wersjach, Android 15 zawiera zmiany w działaniu, które mogą mieć do aplikacji. Opisane poniżej zmiany w działaniu dotyczą tylko aplikacji, które: na Androida 15 lub nowszego. Jeśli aplikacja jest kierowana na Androida 15 lub nowszego, należy zmodyfikować aplikację, aby obsługiwała te zachowania. mają zastosowanie.

Zapoznaj się też z listą zmian w działaniu, które mają wpływ na wszystkie aplikacje z Androidem 15 niezależnie od tego, jaki masz targetSdkVersion w aplikacji.

Główna funkcja

Android 15 zmienia lub rozszerza różne podstawowe funkcje systemu Android.

Zmiany w usługach na pierwszym planie

Wprowadzamy te zmiany w usługach działających na pierwszym planie w Androidzie 15.

Zachowanie limitu czasu oczekiwania usługi działającej na pierwszym planie w ramach synchronizacji danych

Android 15 wprowadza nowy limit czasu oczekiwania w dataSync w przypadku kierowania na aplikacje Android 15 (poziom interfejsu API 35) lub nowszy. Odnosi się to również do nowych funkcji Typ usługi na pierwszym planie: mediaProcessing.

System pozwala na działanie usług aplikacji dataSync przez łącznie 6 godzin w ciągu 24 godzin, po czym system wywołuje metodę Metoda Service.onTimeout(int, int) (wprowadzona w Androidzie) 15) W tej chwili usługa ma kilka sekund na nawiązanie połączenia Service.stopSelf() W przypadku wywołania funkcji Service.onTimeout() makro usługa nie jest już uznawana za usługę na pierwszym planie. Jeśli usługa nie wywoła Service.stopSelf(), system zgłosi wyjątek wewnętrzny. jest rejestrowany w Logcat z następującym komunikatem:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"

Aby uniknąć problemów związanych ze zmianą działania, możesz wykonać co najmniej jedną z :

  1. Pozwól usłudze wdrożyć nową metodę Service.onTimeout(int, int). Gdy Twoja aplikacja otrzyma wywołanie zwrotne, wywołaj stopSelf() w za kilka sekund. (Jeśli nie zatrzymasz aplikacji od razu, system wygeneruje komunikat niepowodzenie).
  2. 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).
  3. 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.
  4. 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

Android 15 引入了一种新的前台服务类型,即 mediaProcessing。本次 服务类型适用于对媒体文件进行转码等操作。对于 例如,媒体应用可能会下载音频文件并需要将其转换为 然后再播放之前的视频您可以使用 mediaProcessing 前台 以确保即使应用处于打开或关闭状态,转化仍会继续进行 背景。

系统允许应用的 mediaProcessing 服务共运行 6 次 之后,系统会调用正在运行的服务的 Service.onTimeout(int, int) 方法(在 Android 中引入) 15)。此时,服务有几秒钟的时间来调用 Service.stopSelf()。如果该服务没有 调用 Service.stopSelf() 时,系统会抛出内部异常。通过 Logcat 中会记录以下异常:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"

为避免出现异常,您可以执行以下操作之一:

  1. 让您的服务实现新的 Service.onTimeout(int, int) 方法。 当您的应用收到回调时,请务必在stopSelf() 几秒。(如果您不立即停止应用,则系统会生成 失败。)
  2. 确保应用的 mediaProcessing 服务的运行时间不超过 总计 在任何 24 小时内为 6 小时(除非用户与应用互动; 重置计时器)。
  3. 仅在用户执行直接操作后启动 mediaProcessing 项前台服务 互动;由于服务启动时您的应用位于前台 您的服务在应用转入后台后的完整运行 6 小时。
  4. 不使用 mediaProcessing 前台服务,而是使用替代方法 API,例如 WorkManager。

如果您的应用的 mediaProcessing 前台服务已在 不能启动其他 mediaProcessing 前台服务,除非 用户将您的应用转至前台(这会重置计时器)。如果您 尝试启动另一个 mediaProcessing 前台服务,系统会抛出 ForegroundServiceStartNotAllowedException 并显示类似“前台服务的时限已用尽”的错误消息 type mediaProcessing”。

要详细了解 mediaProcessing 服务类型,请参阅对 前台服务类型:媒体处理

测试

如需测试应用的行为,您可以启用媒体处理超时,即使 您的应用并非以 Android 15 为目标平台(只要该应用在 Android 15 上运行) Android 15 设备)。如需启用超时功能,请运行以下 adb 命令:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

您还可以调整超时期限,以便更轻松地测试 在达到该限制时,应用的行为。要设置新的超时期限,请运行 以下 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:

Jeśli odbiornik BOOT_COMPLETED próbuje uruchomić którykolwiek z tych typów działania na pierwszym planie usług, system wywołuje ForegroundServiceStartNotAllowedException.

Testowanie

Aby przetestować działanie aplikacji, możesz włączyć te nowe ograniczenia, nawet jeśli aplikacja nie jest kierowana na Androida 15 (o ile jest ona uruchomiona na urządzeniu z Androidem 15). Uruchom to polecenie adb:

adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name

Aby wysłać komunikat typu BOOT_COMPLETED bez ponownego uruchamiania urządzenia: uruchom to polecenie adb:

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name

Ograniczenia dotyczące uruchamiania usług na pierwszym planie, gdy aplikacja ma uprawnienie SYSTEM_ALERT_WINDOW

以前,如果应用拥有 SYSTEM_ALERT_WINDOW 权限,则可以启动 前台服务,即使应用当前在后台运行(如 请参阅后台启动限制的豁免部分)。

如果应用以 Android 15 为目标平台,则此豁免的范围现在更窄。现在,该应用需要 具有 SYSTEM_ALERT_WINDOW 权限,并且还应显示一个可见叠加层 窗口。也就是说,应用需要先启动一个 TYPE_APPLICATION_OVERLAY 窗口窗口 在您启动前台服务之前必须处于可见状态。

如果您的应用试图在后台启动前台服务,却没有启动 符合这些新要求(并且不具有某些其他豁免情况), 系统会抛出 ForegroundServiceStartNotAllowedException

如果您的应用声明了 SYSTEM_ALERT_WINDOW 权限 并在后台启动前台服务时,可能会受此影响 更改。如果您的应用收到 ForegroundServiceStartNotAllowedException,请检查 应用的操作顺序,并确保应用已有 叠加层窗口,然后再尝试从 背景。您可以检查叠加窗口当前是否可见 致电 View.getWindowVisibility(),或者 可以替换 View.onWindowVisibilityChanged() 以便在公开范围发生变化时收到通知。

测试

如需测试应用的行为,即使您的 应用并非以 Android 15 为目标平台(只要该应用在 Android 15 上运行即可) 设备)。为了在启动前台服务时启用这些新限制 在后台运行以下 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(setInterruptionFiltersetNotificationPolicy)会导致创建或更新隐式 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() i Formatter.format():

    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 funkcji Arrays.asList(...).toArray(), typ komponentu tablicy wynikowej to jest to teraz Object, a nie typ elementów tablicy bazowej. Dlatego ten kod zwraca ClassCastException:

    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ż metody Random.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() w kotlin-stdlib

    Typ List w Javie jest zmapowany na typ MutableList w Kotlin. Ponieważ interfejsy API List.removeFirst() i List.removeLast() zostały wprowadzone w Androidzie 15 (poziom API 35) – kompilatorze Kotlin przekształca statycznie wywołania funkcji, na przykład list.removeFirst(), na nowych interfejsów API List zamiast funkcji rozszerzeń w kotlin-stdlib.

    Jeśli aplikacja jest ponownie skompilowana z ustawieniem compileSdk ustawionym na 35, a minSdk 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 funkcji removeLast() można zastąpić wyrażeniami removeAt(0) i removeAt(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") i lintOptions { disable 'NewApi' }.

  • Kolizja z innymi metodami w Javie

    Do istniejących typów zostały dodane nowe metody, na przykład List i Deque. 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 kompilator javac 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 List
    

    Przykł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 error
    

    Przykł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 error
    

    Aby naprawić te błędy kompilacji, klasa implementująca te interfejsy powinna zastąpić metodę zgodnym typem zwracanym. Na przykład:

    @Override
    public Object getFirst() {
        return List.super.getLast();
    }
    

Bezpieczeństwo

Android 15 zawiera zmiany, które promują bezpieczeństwo systemu i pomagają chronić aplikacje przed użytkownikami ze złośliwych aplikacji.

Uruchomienie bezpiecznej aktywności w tle

Android 15 chroni użytkowników przed złośliwymi aplikacjami i daje im większą kontrolę nad ich urządzeniach, dodając zmiany, które uniemożliwiają złośliwym aplikacjom działającym w tle ujawnianie innych aplikacji, podnoszenie ich przywilejów i nadużywanie interakcji użytkownika. Od wersji Android 10 (poziom interfejsu API 29) ograniczono uruchamianie działań w tle.

Blokowanie uruchamiania aktywności przez aplikacje, których identyfikator nie pasuje do najwyższego identyfikatora na stosie

Złośliwe aplikacje mogą uruchomić inną aplikację w ramach tego samego zadania, a następnie nakładają się na siebie i tworzą wrażenie, że jest to ta aplikacja. To „zadanie porwanie” omija obecne ograniczenia uruchamiania w tle, występuje w ramach tego samego widocznego zadania. Aby zmniejszyć to ryzyko, Android 15 dodaje flagę, która blokuje uruchamianie aktywności przez aplikacje, których identyfikator UID nie pasuje do najwyższego identyfikatora UID w steku. Aby wyrazić zgodę na wszystkie aktywności w aplikacji, zaktualizuj allowCrossUidActivitySwitchFromBelow w pliku AndroidManifest.xml aplikacji:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

Nowe zabezpieczenia są aktywne, jeśli są spełnione wszystkie te warunki:

  • Aplikacja, w której wprowadzana jest na rynek, jest kierowana na Androida 15.
  • Aplikacja u góry stosu zadań jest kierowana na Androida 15.
  • Każda widoczna aktywność została objęta nowymi zabezpieczeniami

Jeśli środki bezpieczeństwa są włączone, aplikacje mogą po zakończeniu działania wracać na ekran główny, a nie do ostatniej widocznej aplikacji.

Inne zmiany

Oprócz ograniczenia dopasowania identyfikatorów UID te inne zmiany również uwzględniono:

  • Zmień PendingIntent twórców na blokowanie uruchamiania aktywności w tle przez domyślne. Zapobiega to przypadkowemu utworzeniu przez aplikacje PendingIntent, które mogą być wykorzystywane przez hakerów.
  • Nie przenoś aplikacji na pierwszy plan, chyba że nadawca PendingIntent na to zezwala. Ta zmiana ma na celu zapobieganie wykorzystywaniu uruchamianie działań w tle. Domyślnie aplikacje nie są może przenieść stos zadań na pierwszy plan, chyba że twórca wyrazi zgodę uprawnienia do uruchamiania aktywności w tle lub nadawca ma aktywność w tle uprawnienia do uruchamiania.
  • Określ, w jaki sposób główna aktywność stosu zadań może wykonać zadanie. Jeśli które kończy zadanie, Android wróci do tego, które było jako ostatnia aktywność. Ponadto jeśli aktywność niebędąca na pierwszym planie zakończy swoje działanie, Android wróci do ekranu głównego. Nie zablokuje to zakończenia tej aktywności.
  • Zapobiegaj uruchamianiu dowolnych działań z innych aplikacji we własnym zakresie zadanie. Ta zmiana zapobiega wyłudzaniu informacji przez złośliwe aplikacje, tworząc aktywności, które wyglądają jak z innych aplikacji.
  • Nie zezwalaj na uwzględnianie niewidocznych okien w aktywności w tle . Pomaga to zapobiegać wykorzystywaniu działania w tle przez złośliwe aplikacje aby wyświetlać użytkownikom niechciane lub szkodliwe treści.

Bezpieczniejsze intencje

Android 15 引入了新的安全措施,可让 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 wprowadziliśmy kilka zmian, które mają zapewnić intuicyjną obsługę.

Zmiany wstawienia okien

W Androidzie 15 wprowadzono 2 zmiany związane z wstawianiem okien: ustawienie od krawędzi do krawędzi jest domyślnie wymuszane w obszarze od krawędzi do krawędzi oraz zmiany w konfiguracji, takie jak domyślna konfiguracja pasków systemowych.

Egzekwowanie treści od krawędzi do krawędzi

Domyślnie na urządzeniach z Androidem 15 aplikacje działają od brzegu do brzegu, jeśli są są kierowane na Androida 15 (poziom API 35).

Aplikacja, która jest kierowana na Androida 14 i nie obsługuje połączeń od brzegu sieci Urządzenie z Androidem 15.


Aplikacja jest kierowana na Androida 15 (poziom interfejsu API 35) i zapewnia dostęp od krawędzi do krawędzi na urządzeniu z Androidem 15. Ta aplikacja głównie wykorzystuje komponenty Material 3 Compose który automatycznie stosuje wstawki. Na ten ekran nie wpływa negatywnie Egzekwowanie zasad brzegu do brzegu Androida 15.

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 i R.attr#navigationBarColor są została wycofana i nie ma wpływu na nawigację przy użyciu gestów.
    • setNavigationBarContrastEnforced i R.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 i R.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 i R.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 i R.attr#statusBarColor są została wycofana i nie będzie miała wpływu na Androida 15.
    • setStatusBarContrastEnforced i Kolumny R.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 i DEFAULT są interpretowane jako ALWAYS, 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.

Aplikacja, która jest kierowana na Androida 14 i nie obsługuje połączeń od brzegu sieci Urządzenie z Androidem 15.
.
Aplikacja, która jest kierowana na Androida 15 (poziom interfejsu API 35) i zapewnia dostęp od krawędzi do krawędzi na urządzeniu z Androidem 15. Jednak wiele elementów jest teraz ukrytych ze względu na stan lub pasek nawigacyjny z 3 przyciskami lub wycięcie w ekranie ze względu na Androida 15. egzekwowanie zasad od krawędzi do krawędzi. Ukryty interfejs obejmuje interfejs Material 2. górny pasek aplikacji, pływające przyciski poleceń i elementy listy.
.
Aplikacja kierowana na Androida 15 (poziom interfejsu API 35) jest na bieżąco z rozmową na urządzeniu z Androidem 15 i stosują wstawki, aby interfejs nie był ukryte.
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 funkcji SHORT_EDGES, NEVER lub DEFAULT zamiast LAYOUT_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 ustaw window.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ład TopAppBar, BottomAppBar i NavigationBar, 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 parametru windowInsets, aby ręcznie zastosować wstawki BottomAppBar, TopAppBar, BottomNavigation i NavigationRail. Podobnie użyj parametru contentWindowInsets 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 jak BottomNavigationView, BottomAppBar, NavigationRailView lub NavigationView, uchwyty wstawiane i nie wymagają dodatkowej pracy. Musisz jednak dodać android:fitsSystemWindows="true" w przypadku używania funkcji AppBarLayout.
  • 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ą funkcji Scaffold . W przeciwnym razie zastosuj dopełnienie za pomocą jednej z WindowInsets
  • 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 dodaj clipToPadding="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:

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:

AtrybuteleTextHeight ma domyślną wartość true (prawda)

For apps targeting Android 15 (API level 35), the elegantTextHeight TextView attribute becomes true by default, replacing the compact font used by default with some scripts that have large vertical metrics with one that is much more readable. The compact font was introduced to prevent breaking layouts; Android 13 (API level 33) prevents many of these breakages by allowing the text layout to stretch the vertical height utilizing the fallbackLineSpacing attribute.

In Android 15, the compact font still remains in the system, so your app can set elegantTextHeight to false to get the same behavior as before, but it is unlikely to be supported in upcoming releases. So, if your app supports the following scripts: Arabic, Lao, Myanmar, Tamil, Gujarati, Kannada, Malayalam, Odia, Telugu or Thai, test your app by setting elegantTextHeight to true.

elegantTextHeight behavior for apps targeting Android 14 (API level 34) and lower.
elegantTextHeight behavior for apps targeting Android 15.

Zmiany szerokości obiektu TextView w przypadku złożonych kształtów liter

W poprzednich wersjach Androida niektóre czcionki kursywą lub języki, w których złożone kształtowanie może spowodować narysowanie liter w obszarze poprzedniego lub następnego znaku. Zdarzało się, że takie litery były obcinane na początku lub na końcu. Począwszy od Androida 15 TextView określa szerokość, aby zapewnić wystarczającą ilość miejsca dla takich liter i umożliwia aplikacjom żądanie dodatkowego dopełnienia z lewej strony, zapobiegają obcinaniu.

Ta zmiana wpływa na sposób określania szerokości przez element TextView, dlatego TextView domyślnie przypisuje większą szerokość, jeśli aplikacja jest kierowana na Androida 15 (poziom interfejsu API 35) lub wyższe. Możesz włączyć lub wyłączyć tę funkcję, wywołując metodę Interfejs API setUseBoundsForWidth w systemie TextView.

Dodanie dopełnienia z lewej strony może spowodować niedopasowanie istniejących układów, dopełnienie nie jest dodawane domyślnie nawet w przypadku aplikacji kierowanych na Androida 15 lub nowszego. Można jednak dodać dodatkowe dopełnienie, aby zapobiec przycinaniu obrazu przez wywołanie setShiftDrawingOffsetForStartOverhang

Poniższe przykłady pokazują, jak te zmiany mogą poprawić układ tekstu w niektórych z nich czcionki i języki.

Standardowy układ angielskiej czcionki zapisanej kursywą. Niektóre są obcięte. Oto odpowiedni plik XML:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
układ tego samego tekstu w języku angielskim o dodatkowej szerokości i dopełnienie. Oto odpowiedni plik XML:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
Standardowy układ tekstu w języku tajskim. Niektóre litery są obcięte. Oto odpowiedni plik XML:

<TextView
    android:text="คอมพิวเตอร์" />
Układ tego samego tekstu w języku tajskim o dodatkowej szerokości i dopełnienie. Oto odpowiedni plik XML:

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

Domyślna wysokość wiersza z uwzględnieniem języka dla interfejsu EditText

在以前的 Android 版本中,文本布局拉伸了文本的高度,使其适应与当前语言区域匹配的字体的行高。例如,如果内容是日语,由于日语字体的行高比拉丁字体的行高略大,因此文本的高度就略大了。不过,尽管行高存在这些差异,但无论使用何种语言区域,EditText 元素的大小都是一致的,如下图所示:

三个表示 EditText 元素的框,这些框可以包含英语 (en)、日语 (ja) 和缅甸语 (my) 的文本。EditText 的高度相同,即使这两种语言的行高不同。

对于以 Android 15 为目标平台的应用,系统现在会为 EditText 预留最小行高,以匹配指定语言区域的参考字体,如下图所示:

三个表示 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 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.