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

Podobnie jak w poprzednich wersjach Android 15 obejmuje zmiany w działaniu, które mogą mieć wpływ na Twoją aplikację. Poniższe zmiany w działaniu dotyczą tylko aplikacji kierowanych na Androida 15 lub nowszego. Jeśli Twoja aplikacja jest kierowana na Androida 15 lub nowszego, w razie potrzeby zmodyfikuj aplikację, aby prawidłowo obsługiwała te zachowania.

Zapoznaj się też z listą zmian w działaniu, które wpływają na wszystkie aplikacje działające na Androidzie 15, niezależnie od targetSdkVersion w Twojej aplikacji.

Główna funkcja

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

Zmiany w usługach na pierwszym planie

Wprowadzamy następujące zmiany w usługach działających na pierwszym planie w Androidzie 15.

Zachowanie limitu czasu usługi synchronizacji danych na pierwszym planie

Android 15 wprowadza nowy limit czasu w dataSync w przypadku aplikacji kierowanych na Androida 15 lub nowszego. Dotyczy to też nowego typu usługi na pierwszym planie mediaProcessing.

System zezwala na działanie usług dataSync aplikacji przez łącznie 6 godzin w ciągu 24 godzin. Po tym czasie system wywołuje metodę Service.onTimeout(int, int) uruchomionej usługi (wprowadzoną w Androidzie 15). W tej chwili usługa ma kilka sekund na wywołanie Service.stopSelf(). Po wywołaniu Service.onTimeout() usługa nie jest już uznawana za usługę na pierwszym planie. Jeśli usługa nie wywoła Service.stopSelf(), wystąpi błąd i ten komunikat o błędzie: „Usługa na pierwszym planie typu <fgs_type> nie została zatrzymana przed upływem czasu oczekiwania: <component_name>”. W wersji beta 2 komunikat o błędzie jest wyświetlany jako błąd ANR, ale w kolejnej wersji beta ten komunikat o błędzie spowoduje wystąpienie niestandardowego wyjątku.

Aby uniknąć problemów związanych ze zmianą działania, wykonaj co najmniej jedną z tych czynności:

  1. Zadbaj o wdrożenie w swojej usłudze nowej metody Service.onTimeout(int, int). Gdy aplikacja oddzwoni, skontaktuj się z firmą stopSelf() w ciągu kilku sekund. Jeśli nie zatrzymasz aplikacji od razu, system wygeneruje błąd.
  2. Upewnij się, że usługi dataSync Twojej aplikacji nie działają dłużej niż przez 6 godzin w ciągu doby (chyba że użytkownik wejdzie w interakcję z aplikacją i nie zresetuje minutnika).
  3. Usługi działające na pierwszym planie typu dataSync należy uruchamiać tylko w wyniku bezpośredniej interakcji z użytkownikiem, ponieważ aplikacja działa na pierwszym planie po uruchomieniu usługi, dlatego po jej uruchomieniu w tle upłynie pełne 6 godzin.
  4. Zamiast usługi na pierwszym planie dataSync użyj alternatywnego interfejsu API.

Jeśli dataSyncusługa na pierwszym planie Twojej aplikacji działała przez 6 godzin w ciągu ostatnich 24 godzin, nie możesz uruchomić innejdataSyncusługi na pierwszym planiechyba że użytkownik przeniósł Twoją aplikację na pierwszy plan (co spowoduje zresetowanie licznika czasu). Jeśli spróbujesz uruchomić inną usługę dataSync na pierwszym planie, system zgłosi ForegroundServiceStartNotAllowedException z komunikatem o błędzie takim jak „Limit czasu dla typu usługi na pierwszym planie typu dataSync został już wyczerpany”.

Nowy typ usługi na pierwszym planie przetwarzania multimediów

W Androidzie 15 wprowadziliśmy nowy typ usługi na pierwszym planie: mediaProcessing. Ten typ usługi jest odpowiedni do operacji takich jak transkodowanie plików multimedialnych. Na przykład aplikacja do multimediów może pobrać plik audio i przed odtworzeniem go musi przekonwertować go na inny format. Możesz użyć usługi na pierwszym planie mediaProcessing, aby mieć pewność, że konwersja będzie kontynuowana nawet wtedy, gdy aplikacja działa w tle.

System zezwala na działanie usług mediaProcessing aplikacji przez łącznie 6 godzin w okresie 24 godzin. Po tym czasie system wywołuje metodę Service.onTimeout(int, int) (wprowadzoną w Androidzie 15). W tej chwili usługa ma kilka sekund na wywołanie metody Service.stopSelf(). Jeśli usługa nie wywoła funkcji Service.stopSelf(), system zgłosi wyjątek wewnętrzny. Wyjątek jest logowany w Logcat z tym komunikatem:

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

Aby uniknąć wyjątku, wykonaj jedną z tych czynności:

  1. Pozwól usłudze wdrożyć nową metodę Service.onTimeout(int, int). Gdy Twoja aplikacja otrzyma wywołanie zwrotne, pamiętaj, aby wywołać funkcję stopSelf() w ciągu kilku sekund. Jeśli nie zatrzymasz aplikacji od razu, system wygeneruje błąd.
  2. Dopilnuj, aby usługi mediaProcessing w Twojej aplikacji nie działały przez łącznie 6 godzin w dowolnym okresie 24 godzin (chyba że użytkownik wejdzie w interakcję z aplikacją, resetując minutnik).
  3. Uruchamiaj mediaProcessing usługi na pierwszym planie wyłącznie w wyniku bezpośredniej interakcji z użytkownikiem. Ponieważ w momencie uruchomienia usługi Twoja aplikacja znajduje się na pierwszym planie, usługa ma pełne 6 godzin od momentu przejścia do działania w tle.
  4. Zamiast usługi na pierwszym planie mediaProcessing użyj alternatywnego interfejsu API, takiego jak WorkManager.

Jeśli usługi na pierwszym planie mediaProcessing w Twojej aplikacji działały przez 6 godzin w ciągu ostatnich 24 godzin, nie możesz uruchomić kolejnej usługi mediaProcessing na pierwszym planie, chyba że użytkownik przeniósł aplikację na pierwszy plan (co spowoduje zresetowanie licznika). Jeśli spróbujesz uruchomić inną usługę na pierwszym planie mediaProcessing, system wygeneruje ForegroundServiceStartNotAllowedException z komunikatem o błędzie, np. „Limit czasu dla usługi działającej na pierwszym planie typu mediaProcessing został już wyczerpany”.

Więcej informacji o typie usługi mediaProcessing znajdziesz w artykule Zmiany w typach usług na pierwszym planie w Androidzie 15: przetwarzanie multimediów.

Testowanie

Aby przetestować działanie aplikacji, możesz włączyć limity czasu przetwarzania multimediów, nawet jeśli aplikacja nie jest kierowana na Androida 15 (o ile działa na urządzeniu z Androidem 15). Aby włączyć limity czasu, uruchom to polecenie adb:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

Możesz też dostosować limit czasu oczekiwania, by łatwiej testować działanie aplikacji po osiągnięciu limitu. Aby ustawić nowy limit czasu, uruchom to polecenie adb:

adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds

Ograniczenia dotyczące BOOT_COMPLETED odbiorników uruchamiających usługi na pierwszym planie

Obowiązują nowe ograniczenia dotyczące odbiorników transmisji (BOOT_COMPLETED) uruchamiających usługi na pierwszym planie. Odbiorniki BOOT_COMPLETED nie mogą uruchamiać tych typów usług działających na pierwszym planie:

Jeśli odbiornik BOOT_COMPLETED spróbuje uruchomić którykolwiek z tych typów usług na pierwszym planie, system zgłosi ForegroundServiceStartNotAllowedException.

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

Wcześniej aplikacja, która miała uprawnienie SYSTEM_ALERT_WINDOW, mogła uruchamiać usługę na pierwszym planie, nawet jeśli działała w tle (co omówiono w sekcji wyjątki z ograniczeń uruchamiania w tle).

Jeśli aplikacja jest kierowana na Androida 15, to wykluczenie jest teraz węższe. Aplikacja musi teraz mieć uprawnienie SYSTEM_ALERT_WINDOW oraz również mieć widoczne nakładki. Oznacza to, że aplikacja musi najpierw uruchomić okno TYPE_APPLICATION_OVERLAY oraz okno musi być widoczne przed uruchomieniem usługi na pierwszym planie.

Jeśli aplikacja próbuje uruchomić usługę na pierwszym planie w tle i nie spełnia tych nowych wymagań (i nie jest objęta innym wyjątkiem), system zgłasza ForegroundServiceStartNotAllowedException.

Jeśli Twoja aplikacja zadeklaruje uprawnienie SYSTEM_ALERT_WINDOW i uruchamia usługi działające na pierwszym planie w tle, ta zmiana może mieć na nią wpływ. Jeśli Twoja aplikacja otrzyma właściwość ForegroundServiceStartNotAllowedException, sprawdź jej kolejność działań i upewnij się, że ma już aktywne okno nakładki, zanim będzie próbowała uruchomić usługę na pierwszym planie z poziomu tła. Aby sprawdzić, czy okno nakładki jest obecnie widoczne, wywołaj View.getWindowVisibility(). Możesz też zastąpić metodę View.onWindowVisibilityChanged(), aby otrzymywać powiadomienia o zmianie widoczności.

Zmiany dotyczące tego, kiedy aplikacje mogą modyfikować globalny stan trybu Nie przeszkadzać

Aplikacje kierowane na Androida 15 nie mogą już zmieniać globalnego stanu ani zasad trybu Nie przeszkadzać na urządzeniu (przez zmianę ustawień użytkownika lub wyłączenie trybu Nie przeszkadzać). Zamiast tego aplikacje muszą przekazywać element AutomaticZenRule, który system łączy w globalną zasadę z dotychczasowym schematem wygrywania zasad o największym ograniczeniu. Wywołania istniejących interfejsów API, które wcześniej wpływały na stan globalny (setInterruptionFilter, setNotificationPolicy), skutkują utworzeniem lub zaktualizowaniem niejawnej klasy AutomaticZenRule, która jest włączana i wyłączana w zależności od cyklu wywołań tych wywołań interfejsu API.

Pamiętaj, że ta zmiana wpływa na obserwowalne zachowanie tylko wtedy, gdy aplikacja wywołuje metodę setInterruptionFilter(INTERRUPTION_FILTER_ALL) i oczekuje, że wywołanie dezaktywacji AutomaticZenRule, która została wcześniej aktywowana przez ich właścicieli.

Zmiany w OpenJDK 17

Android 15 kontynuuje pracę nad odświeżaniem podstawowych bibliotek Androida, aby zapewnić zgodność z funkcjami dostępnymi w najnowszych wersjach OpenJDK LTS.

Jedna z tych zmian może 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().

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 urządzeniami, dodając zmiany, które uniemożliwiają złośliwym aplikacjom działającym w tle przenoszenie innych aplikacji na pierwszy plan, podnoszenie ich uprawnień i nadużywanie interakcji z użytkownikiem. Uruchamianie aktywności w tle jest ograniczone od wersji Androida 10 (poziom API 29).

Blokuj uruchamianie aktywności w aplikacjach, które nie pasują do identyfikatora UID najwyższego poziomu w stosie

Złośliwe aplikacje mogą uruchamiać działania innych aplikacji w ramach tego samego zadania, a potem nakładać się na nie, stwarzając wrażenie, że są tą aplikacją. Ten atak „atak z wykorzystaniem przejęcia zadania” omija obecne ograniczenia uruchamiania w tle, ponieważ wszystko odbywa się w ramach tego samego widocznego zadania. Aby ograniczyć to ryzyko, Android 15 dodaje flagę, która blokuje uruchamianie aktywności przez aplikacje, które nie pasują do identyfikatora użytkownika najwyższego poziomu w stosie. Aby zezwolić na wszystkie aktywności w aplikacji, zaktualizuj atrybut allowCrossUidActivitySwitchFromBelow w pliku AndroidManifest.xml aplikacji:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

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

  • Aplikacja, która ma zostać wprowadzona na rynek, jest kierowana na Androida 15.
  • Aplikacja znajdująca się na stosie zadań jest kierowana na Androida 15.
  • Każda widoczna aktywność ma włączone nowe zabezpieczenia

Gdy zabezpieczenia są włączone, w przypadku, gdy samodzielnie ukończą zadanie, aplikacje mogą wrócić do ekranu głównego, a nie do ostatniej widocznej aplikacji.

Inne zmiany

Oprócz ograniczenia związanego z dopasowywaniem identyfikatorów UID zmiany obejmą też te inne zmiany:

  • Zmień twórców PendingIntent, aby domyślnie blokowały uruchamianie aktywności w tle. Pomaga to zapobiegać przypadkowemu tworzeniu przez aplikacje elementów PendingIntent, które mogłyby zostać wykorzystane przez hakerów.
  • Nie umieszczaj aplikacji na pierwszym planie, chyba że zezwala na to nadawca PendingIntent. Ta zmiana ma zapobiec nadużywaniu możliwości uruchamiania działań w tle przez złośliwe aplikacje. Domyślnie aplikacje nie mogą umieszczać stosu zadań na pierwszym planie, chyba że twórca zezwala na uruchamianie aktywności w tle lub nadawca ma uprawnienia do uruchamiania aktywności w tle.
  • Określ, w jaki sposób najbardziej wartościowa aktywność na stosie zadań może dokończyć zadanie. Jeśli największe działanie zakończy zadanie, Android powróci do tego, które było ostatnio aktywne. Co więcej, jeśli aktywność spoza najwyższego poziomu dokończy swoje zadanie, Android wróci na ekran główny. Nie zablokuje dokończenia tej aktywności.
  • Zapobieganie uruchamianiu dowolnych działań z innych aplikacji w Twoim zadaniu Ta zmiana zapobiega wyłudzeniu informacji przez złośliwe aplikacje przez tworzenie działań, które wyglądają jak pochodzące z innych aplikacji.
  • Blokuj niewidoczne okna nie uwzględniania przy uruchamianiu aktywności w tle. Pomaga to zapobiegać nadużywaniu przez złośliwe aplikacje aktywności w tle do wyświetlania użytkownikom niechcianych lub szkodliwych treści.

Bezpieczniejsze intencje

Android 15 wprowadza nowe zabezpieczenia, które zwiększają bezpieczeństwo intencji. Te zmiany mają zapobiegać potencjalnym lukom w zabezpieczeniach i niewłaściwemu wykorzystaniu intencji, które mogą być wykorzystywane przez złośliwe aplikacje. W Androidzie 15 występują 2 główne ulepszenia w zakresie bezpieczeństwa intencji:

  • Dopasuj do filtrów intencji: intencje kierowane na określone komponenty muszą dokładnie odpowiadać specyfikacji filtra intencji. Jeśli wyślesz zamiar uruchomienia innej aplikacji, komponent intencji docelowej musi być zgodny z zadeklarowanymi filtrami intencji odbierającej.
  • Intencje muszą zawierać działania: intencje bez działania nie będą już pasować do żadnych filtrów intencji. Oznacza to, że intencje służące do rozpoczynania działań lub świadczenia usług muszą mieć jasno określone działanie.
  • Intencje oczekujące: twórca intencji oczekującej jest traktowany jako nadawca intencji zamykającej, a nie jako nadawca oczekującej intencji

Kotlin


fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

Java


public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

Wygoda użytkowania i interfejs systemu

W Androidzie 15 wprowadzono kilka zmian, które mają zapewnić użytkownikom bardziej spójne i intuicyjne wrażenia.

Zmiany wstawienia okien

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

Egzekwowanie zasad od krawędzi do krawędzi

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

Aplikacja, która jest kierowana na Androida 14 i nie obsługuje sieci brzegowej 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. 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)

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.

Zachowanie elegantTextHeight w przypadku aplikacji kierowanych na Androida 14 (poziom API 34) i starsze.
elegantTextHeight w przypadku aplikacji kierowanych na Androida 15.

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

W poprzednich wersjach Androida niektóre czcionki kursywy lub języki ze złożonym kształtem mogły powodować rysowanie liter w obszarze poprzedniego lub następnego znaku. W niektórych przypadkach takie litery były przycinane na pozycji początkowej lub końcowej. Począwszy od Androida 15 parametr TextView przydziela szerokość dostatecznie dużo miejsca na takie litery i pozwala aplikacjom żądać dodatkowego dopełnienia z lewej strony, by zapobiec przycinaniu.

Ta zmiana wpływa na sposób, w jaki TextView określa szerokość, dlatego TextView domyślnie przydziela większą szerokość, jeśli aplikacja jest kierowana na Androida 15 lub nowszego. Możesz włączyć lub wyłączyć tę funkcję, wywołując interfejs API setUseBoundsForWidth w usłudze TextView.

Dodanie lewego dopełnienia może spowodować niewłaściwe wyrównanie elementów w istniejących układach, dlatego nie jest ono dodawane domyślnie nawet w aplikacjach kierowanych na Androida 15 lub nowszego. Możesz jednak dodać dodatkowe dopełnienie, wywołując metodę setShiftDrawingOffsetForStartOverhang, aby zapobiec przycinaniu.

Poniższe przykłady pokazują, jak te zmiany mogą poprawić układ tekstu w przypadku niektórych czcionek i języków.

Standardowy układ tekstu w języku angielskim z kursywą. Niektóre litery są obcięte. Oto odpowiedni kod XML:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
Układ tego samego tekstu w języku angielskim z dodatkową szerokością i dopełnieniem. Oto odpowiedni kod 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 kod XML:

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

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

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

W poprzednich wersjach Androida układ tekstu rozciągnął wysokość tekstu, aby dopasować ją do wysokości czcionki w bieżącym języku. Jeśli na przykład treść była w języku japońskim, ponieważ wysokość wiersza czcionki japońskiej jest nieco większa niż czcionki łacińskiej, wysokość tekstu znacznie się zwiększyła. Pomimo tych różnic w wysokości wierszy, rozmiar elementu EditText był jednak taki sam niezależnie od używanego regionu, jak na tym przykładzie:

3 pola reprezentujące elementy EditText, które mogą zawierać tekst w języku angielskim (en), japońskim (ja) i birmańskim (my). Wysokość wiersza EditText jest taka sama, mimo że te języki różnią się wysokością wierszy.

W przypadku aplikacji kierowanych na Androida 15 minimalna wysokość wiersza jest teraz zarezerwowana dla EditText, aby pasowała do czcionki referencyjnej dla określonego języka, jak widać na tym obrazie:

3 pola reprezentujące elementy EditText, które mogą zawierać tekst w języku angielskim (en), japońskim (ja) i birmańskim (my). Wysokość elementu EditText obejmuje teraz miejsce na domyślną wysokość wiersza dla czcionek w tych językach.

W razie potrzeby aplikacja może przywrócić poprzednie działanie, określając atrybut useLocalePreferredLineHeightForMinimum jako false, a aplikacja może ustawiać niestandardowe minimalne wskaźniki branżowe za pomocą interfejsu API setMinimumFontMetrics w Kotlin i Javie.

Aparat i multimedia

Android 15 wprowadza te zmiany w działaniu aparatu i multimediów w aplikacjach kierowanych na Androida 15 lub nowszego.

Ograniczenia dotyczące żądania skupienia się na dźwięku

Aplikacje kierowane na Androida 15 muszą być najlepszą aplikacją lub obsługiwać usługę na pierwszym planie, aby żądać aktywności audio. Jeśli aplikacja próbuje poprosić o koncentrację, gdy nie spełnia jednego z tych wymagań, wywołanie zwraca AUDIOFOCUS_REQUEST_FAILED.

Więcej informacji o aktywności audio znajdziesz w artykule Zarządzanie aktywnością audio.

Zaktualizowano ograniczenia spoza pakietu SDK

Android 15 zawiera zaktualizowane listy ograniczonych list aplikacji spoza pakietu SDK oparte na współpracy z deweloperami aplikacji na Androida oraz do testów wewnętrznych. Gdy tylko jest to możliwe, dbamy o to, by alternatywne rozwiązania były dostępne publicznie, zanim wprowadzimy ograniczenia dotyczące interfejsów spoza SDK.

Jeśli Twoja aplikacja nie jest kierowana na Androida 15, niektóre z tych zmian mogą nie być od razu widoczne. Mimo że aplikacja może dostęp do niektórych interfejsów spoza SDK w zależności od docelowego poziomu interfejsu API aplikacji, używając dowolnego innego zawsze wiąże się z dużym ryzykiem uszkodzenia aplikacji.

Jeśli nie wiesz, czy Twoja aplikacja korzysta z interfejsów innych niż SDK, przetestować aplikację. Jeśli Twoja aplikacja korzysta z innego pakietu SDK należy planować migrację na alternatywne wersje SDK. Zdajemy sobie jednak sprawę, że niektóre aplikacje mogą mieć z interfejsami innymi niż SDK. Jeśli nie możesz znaleźć alternatywy dla pakietu SDK interfejsu funkcji aplikacji, żądanie nowego publicznego interfejsu API.

Więcej informacji o zmianach w tej wersji Androida znajdziesz w artykule Aktualizacje ograniczeń interfejsu innego niż SDK na Androidzie 15. Więcej informacji o interfejsach innych niż SDK znajdziesz w tym artykule.