Come nelle release precedenti, Android 15 include modifiche del comportamento che potrebbero interessare la tua app. Le seguenti modifiche del comportamento si applicano esclusivamente alle app destinate ad Android 15 o versioni successive. Se la tua app ha come target Android 15 o versioni successive, devi modificare l'app in modo da supportare correttamente questi comportamenti, ove applicabile.
Assicurati di esaminare anche l'elenco delle modifiche del comportamento che interessano tutte le app
in esecuzione su Android 15, indipendentemente dall'targetSdkVersion
dell'app.
Funzionalità di base
Android 15 modifica o espande varie funzionalità di base del sistema Android.
Modifiche ai servizi in primo piano
我们将对 Android 15 中的前台服务做出以下更改。
数据同步前台服务超时行为
Android 15 introduce un nuovo comportamento di timeout in dataSync
per il targeting per app
Android 15 o versioni successive. Questo comportamento vale anche per le nuove mediaProcessing
tipo di servizio in primo piano.
Il sistema consente l'esecuzione dei servizi dataSync
di un'app per un totale di 6 ore
in un periodo di 24 ore, dopodiché il sistema chiama
Metodo Service.onTimeout(int, int)
(introdotto su Android
15). Al momento, il servizio ha alcuni secondi di tempo per chiamare
Service.stopSelf()
. Quando viene chiamato Service.onTimeout()
, il parametro
non è più considerato un servizio in primo piano. Se il servizio non
chiama Service.stopSelf()
, il sistema genera un'eccezione interna. La
viene registrata in Logcat con il seguente messaggio:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"
Per evitare problemi con questa modifica del comportamento, puoi eseguire una o più delle seguenti operazioni seguenti:
- Fai in modo che il tuo servizio implementi il nuovo metodo
Service.onTimeout(int, int)
. Quando la tua app viene richiamata, assicurati di chiamare il numerostopSelf()
entro un per alcuni secondi. Se non interrompi subito l'app, il sistema genera errore). - Assicurati che i servizi
dataSync
della tua app non vengano eseguiti per un totale di più di 6 ore in un periodo di 24 ore (a meno che l'utente non interagisca con l'app, reimpostando il timer). - Avvia
dataSync
servizi in primo piano solo dall'utente diretto interazione; poiché l'app è in primo piano all'avvio del servizio, il servizio ha tutte le sei ore dopo che l'app è passata in background. - Anziché utilizzare un servizio in primo piano
dataSync
, usa un'istanza API alternativa.
Se i servizi in primo piano dataSync
della tua app sono stati eseguiti per 6 ore nelle ultime 6 ore
24, non puoi avviare un altro servizio in primo piano dataSync
a meno che l'utente
ha messo la tua app in primo piano (operazione che reimposta il timer). Se provi a
avviare un altro servizio in primo piano dataSync
, il sistema genera
ForegroundServiceStartNotAllowedException
con un messaggio di errore del tipo "Limite di tempo già esaurito per il servizio in primo piano
digita dataSync".
Test
Per verificare il comportamento della tua app, puoi attivare i timeout per la sincronizzazione dei dati anche se l'app
non abbia come target Android 15 (purché l'app sia installata su un dispositivo Android 15)
dispositivo). Per abilitare i timeout, esegui questo comando adb
:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
Puoi anche regolare il periodo di timeout per verificare più facilmente come
l'app si comporta quando viene raggiunto il limite. Per impostare un nuovo periodo di timeout, esegui il comando
seguente comando adb
:
adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds
新增媒体处理前台服务类型
Android 15 introduce un nuovo tipo di servizio in primo piano, mediaProcessing
. Questo
tipo di servizio è appropriato per operazioni come la transcodifica di file multimediali. Ad
esempio, un'app multimediale potrebbe scaricare un file audio e deve convertirlo in un
formato diverso prima di riprodurlo. Puoi utilizzare un servizio in primo piano mediaProcessing
per assicurarti che la conversione continui anche mentre l'app è in background.
Il sistema consente l'esecuzione dei servizi mediaProcessing
di un'app per un totale di 6 ore in un periodo di 24 ore, dopodiché il sistema chiama il metodo Service.onTimeout(int, int)
del servizio in esecuzione (introdotto in Android 15). Al momento, il servizio ha alcuni secondi di tempo per chiamare
Service.stopSelf()
. Se il servizio non
chiama Service.stopSelf()
, il sistema genera un'eccezione interna. L'eccezione viene registrata in Logcat con il seguente messaggio:
Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"
Per evitare questa eccezione, puoi procedere in uno dei seguenti modi:
- Fai in modo che il tuo servizio implementi il nuovo metodo
Service.onTimeout(int, int)
. Quando la tua app riceve la richiamata, assicurati di chiamare il numerostopSelf()
entro pochi secondi. Se non interrompi subito l'app, il sistema genera un errore. - Assicurati che i servizi
mediaProcessing
dell'app non vengano eseguiti per un totale di 6 ore in un periodo di 24 ore (a meno che l'utente non interagisca con l'app reimpostando il timer). - Avvia
mediaProcessing
servizi in primo piano solo a seguito dell'interazione diretta dell'utente. Poiché la tua app è in primo piano all'avvio del servizio, il tuo servizio ha a disposizione tutte le sei ore dopo il passaggio dell'app in background. - Anziché utilizzare un servizio in primo piano
mediaProcessing
, utilizza un'API alternativa, come WorkManager.
Se i servizi in primo piano mediaProcessing
della tua app sono stati eseguiti per 6 ore
negli ultimi 24, non puoi avviare un altro servizio in primo piano mediaProcessing
a meno che
l'utente non abbia portato la tua app in primo piano (operazione che reimposta il timer). Se provi ad avviare un altro servizio in primo piano mediaProcessing
, il sistema visualizza ForegroundServiceStartNotAllowedException
con un messaggio di errore simile a "Il limite di tempo è già esaurito per il tipo di servizio in primo piano mediaProcessing".
Per ulteriori informazioni sul tipo di servizio mediaProcessing
, consulta l'articolo Modifiche ai tipi di servizi in primo piano per Android 15: elaborazione di contenuti multimediali.
Test
Per testare il comportamento della tua app, puoi attivare i timeout dell'elaborazione dei contenuti multimediali anche se
l'app non ha come target Android 15 (purché l'app sia in esecuzione su
un dispositivo Android 15). Per abilitare i timeout, esegui questo comando adb
:
adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name
Puoi anche modificare il periodo di timeout per testare più facilmente il comportamento
della tua app quando viene raggiunto il limite. Per impostare un nuovo periodo di timeout, esegui questo comando adb
:
adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds
对启动前台服务的 BOOT_COMPLETED
广播接收器的限制
Esistono nuove limitazioni per il lancio di BOOT_COMPLETED
broadcast receiver
e i servizi in primo piano. BOOT_COMPLETED
di destinatari non sono autorizzati ad avviare il
i seguenti tipi di servizi in primo piano:
dataSync
camera
mediaPlayback
phoneCall
mediaProjection
microphone
(questa limitazione è attiva permicrophone
dal giorno Android 14)
Se un ricevitore BOOT_COMPLETED
tenta di avviare uno di questi tipi di oggetti in primo piano
automaticamente, il sistema genera ForegroundServiceStartNotAllowedException
.
Test
Per testare il comportamento della tua app, puoi attivare queste nuove limitazioni anche se le tue
L'app non ha come target Android 15 (purché l'app sia installata su un Android 15)
dispositivo). Esegui questo comando adb
:
adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name
Per inviare un annuncio BOOT_COMPLETED
senza riavviare il dispositivo:
esegui questo comando adb
:
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name
限制在应用拥有 SYSTEM_ALERT_WINDOW
权限的情况下启动前台服务
In precedenza, se un'app aveva l'autorizzazione SYSTEM_ALERT_WINDOW
, poteva avviare un servizio in primo piano anche se l'app era attualmente in background (come spiegato nelle esenzioni dalle limitazioni relative all'avvio in background).
Se un'app ha come target Android 15, l'esenzione è ora più limitata. L'app ora deve avere l'autorizzazione SYSTEM_ALERT_WINDOW
e anche avere una finestra overlay visibile. In altre parole, l'app deve avviare una finestra TYPE_APPLICATION_OVERLAY
e la finestra deve essere visibile prima di avviare un servizio in primo piano.
Se la tua app tenta di avviare un servizio in primo piano in background senza soddisfare questi nuovi requisiti (e non ha altre esenzione), il sistema genera ForegroundServiceStartNotAllowedException
.
Se la tua app dichiara l'autorizzazione SYSTEM_ALERT_WINDOW
e avvia i servizi in primo piano in background, questa modifica potrebbe essere interessata. Se la tua app riceve un ForegroundServiceStartNotAllowedException
, controlla l'ordine delle operazioni dell'app e assicurati che abbia già una finestra di overlay attiva prima che provi ad avviare un servizio in primo piano in background. Puoi verificare se la finestra dell'overlay è attualmente visibile
chiamando il numero View.getWindowVisibility()
oppure
eseguire l'override di View.onWindowVisibilityChanged()
per ricevere una notifica ogni volta che la visibilità cambia.
Modifiche relative a quando le app possono modificare lo stato globale della modalità Non disturbare
Apps that target Android 15 can no longer change the global state or policy of
Do Not Disturb (DND) on a device (either by modifying user settings, or turning
off DND mode). Instead, apps must contribute an AutomaticZenRule
, which
the system combines into a global policy with the existing
most-restrictive-policy-wins scheme. Calls to existing APIs that previously
affected global state (setInterruptionFilter
,
setNotificationPolicy
) result in the creation or update of an
implicit AutomaticZenRule
, which is toggled on and off depending on the
call-cycle of those API calls.
Note that this change only affects observable behavior if the app is calling
setInterruptionFilter(INTERRUPTION_FILTER_ALL)
and expects that call to
deactivate an AutomaticZenRule
that was previously activated by their owners.
Modifiche all'API OpenJDK
Android 15 continues the work of refreshing Android's core libraries to align with the features in the latest OpenJDK LTS releases.
Some of these changes can affect app compatibility for apps targeting Android 15 (API level 35):
Changes to string formatting APIs: Validation of argument index, flags, width, and precision are now more strict when using the following
String.format()
andFormatter.format()
APIs:String.format(String, Object[])
String.format(Locale, String, Object[])
Formatter.format(String, Object[])
Formatter.format(Locale, String, Object[])
For example, the following exception is thrown when an argument index of 0 is used (
%0
in the format string):IllegalFormatArgumentIndexException: Illegal format argument index = 0
In this case, the issue can be fixed by using an argument index of 1 (
%1
in the format string).Changes to component type of
Arrays.asList(...).toArray()
: When usingArrays.asList(...).toArray()
, the component type of the resulting array is now anObject
—not the type of the underlying array's elements. So the following code throws aClassCastException
:String[] elements = (String[]) Arrays.asList("one", "two").toArray();
For this case, to preserve
String
as the component type in the resulting array, you could useCollection.toArray(Object[])
instead:String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
Changes to language code handling: When using the
Locale
API, language codes for Hebrew, Yiddish, and Indonesian are no longer converted to their obsolete forms (Hebrew:iw
, Yiddish:ji
, and Indonesian:in
). When specifying the language code for one of these locales, use the codes from ISO 639-1 instead (Hebrew:he
, Yiddish:yi
, and Indonesian:id
).Changes to random int sequences: Following the changes made in https://bugs.openjdk.org/browse/JDK-8301574, the following
Random.ints()
methods now return a different sequence of numbers than theRandom.nextInt()
methods do:Generally, this change shouldn't result in app-breaking behavior, but your code shouldn't expect the sequence generated from
Random.ints()
methods to matchRandom.nextInt()
.
The new SequencedCollection
API can affect your app's compatibility
after you update compileSdk
in your app's build configuration to use
Android 15 (API level 35):
Collision with
MutableList.removeFirst()
andMutableList.removeLast()
extension functions inkotlin-stdlib
The
List
type in Java is mapped to theMutableList
type in Kotlin. Because theList.removeFirst()
andList.removeLast()
APIs have been introduced in Android 15 (API level 35), the Kotlin compiler resolves function calls, for examplelist.removeFirst()
, statically to the newList
APIs instead of to the extension functions inkotlin-stdlib
.If an app is re-compiled with
compileSdk
set to35
andminSdk
set to34
or lower, and then the app is run on Android 14 and lower, a runtime error is thrown:java.lang.NoSuchMethodError: No virtual method removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
The existing
NewApi
lint option in Android Gradle Plugin can catch these new API usages../gradlew lint
MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi] list.removeFirst()To fix the runtime exception and lint errors, the
removeFirst()
andremoveLast()
function calls can be replaced withremoveAt(0)
andremoveAt(list.lastIndex)
respectively in Kotlin. If you're using Android Studio Ladybug | 2024.1.3 or higher, it also provides a quick fix option for these errors.Consider removing
@SuppressLint("NewApi")
andlintOptions { disable 'NewApi' }
if the lint option has been disabled.Collision with other methods in Java
New methods have been added into the existing types, for example,
List
andDeque
. These new methods might not be compatible with the methods with the same name and argument types in other interfaces and classes. In the case of a method signature collision with incompatibility, thejavac
compiler outputs a build-time error. For example:Example error 1:
javac MyList.java
MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List public void removeLast() { ^ return type void is not compatible with Object where E is a type-variable: E extends Object declared in interface ListExample error 2:
javac MyList.java
MyList.java:7: error: types Deque<Object> and List<Object> are incompatible; public class MyList implements List<Object>, Deque<Object> { both define reversed(), but with unrelated return types 1 errorExample error 3:
javac MyList.java
MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible; public static class MyList implements List<Object>, MyInterface<Object> { class MyList inherits unrelated defaults for getFirst() from types List and MyInterface where E#1,E#2 are type-variables: E#1 extends Object declared in interface List E#2 extends Object declared in interface MyInterface 1 errorTo fix these build errors, the class implementing these interfaces should override the method with a compatible return type. For example:
@Override public Object getFirst() { return List.super.getLast(); }
Sicurezza
Android 15 include modifiche che promuovono la sicurezza del sistema per contribuire a proteggere le app e gli utenti da app dannose.
Lanci di attività in background protette
Android 15 protegge gli utenti dalle app dannose e offre loro un maggiore controllo sui loro dispositivi aggiungendo modifiche che impediscono alle app dannose in background di portare altre app in primo piano, elevando i loro privilegi e abusando dell'interazione dell'utente. I lanci delle attività in background sono stati limitati a partire da Android 10 (livello API 29).
Impedisci alle app che non corrispondono all'UID principale dello stack di avviare attività
Le app dannose possono avviare l'attività di un'altra app nell'ambito della stessa attività per poi sovrapporsi alla parte superiore, creando l'illusione di essere quell'app. Questo attacco di "dirottamento dell'attività" bypassa le attuali limitazioni di avvio in background perché tutto avviene all'interno della stessa attività visibile. Per ridurre questo rischio, Android 15 aggiunge un flag che impedisce alle app che non corrispondono all'UID principale dello stack di avviare le attività. Per attivare tutte le attività della tua app, aggiorna l'attributo allowCrossUidActivitySwitchFromBelow
nel file AndroidManifest.xml
dell'app:
<application android:allowCrossUidActivitySwitchFromBelow="false" >
Le nuove misure di sicurezza sono attive se si verificano tutte le seguenti condizioni:
- L'app che esegue il lancio ha come target Android 15.
- L'app in cima allo stack di attività ha come target Android 15.
- Le nuove protezioni sono state attivate per tutte le attività visibili
Se le misure di sicurezza sono attivate, le app potrebbero tornare alla schermata Home anziché all'ultima app visibile, se completano la propria attività.
Altre modifiche
Oltre alla limitazione per la corrispondenza UID, sono incluse anche queste altre modifiche:
- Modifica
PendingIntent
creator in modo da bloccare il lancio delle attività in background per impostazione predefinita. Ciò contribuisce a impedire che le app creino accidentalmente unPendingIntent
che potrebbe essere utilizzato in modo illecito da malintenzionati. - Non portare un'app in primo piano a meno che il mittente
PendingIntent
non lo consenta. Questa modifica ha lo scopo di impedire ad app dannose di abusare della capacità di avviare attività in background. Per impostazione predefinita, alle app non è consentito portare in primo piano lo stack di attività, a meno che l'autore non autorizzi i privilegi di avvio per le attività in background o il mittente non disponga di privilegi di avvio per attività in background. - Controlla in che modo l'attività principale di una serie di attività può completarne l'attività. Se l'attività principale termina un'attività, Android torna all'attività più recente. Inoltre, se un'attività non principale completa la sua attività, Android torna alla schermata Home senza bloccare il completamento di questa attività non principale.
- Impedisci di avviare attività arbitrarie da altre app nella tua attività. Questa modifica impedisce che le app dannose finiscano di phishing per gli utenti creando attività che sembrano provenire da altre app.
- Impedisci che le finestre non visibili vengano prese in considerazione per l'avvio di attività in background. in modo da impedire che app dannose usino in modo illecito gli avvii delle attività in background per mostrare agli utenti contenuti indesiderati o dannosi.
Intent più sicuri
Android 15 引入了新的安全措施,使 intent 更加安全可靠。这些变更旨在防止潜在漏洞和被恶意应用利用的 intent 滥用。Android 15 中对 intent 的安全性进行了两项主要改进:
- 匹配目标 intent 过滤器:定位特定组件的 intent 必须准确匹配目标的 intent 过滤器规范。如果您通过发送 intent 来启动其他应用的 activity,则目标 intent 组件需要与接收 activity 声明的 intent 过滤器保持一致。
- intent 必须具有操作:没有操作的 intent 将不再与任何 intent 过滤器匹配。这意味着,用于启动 activity 或服务的 intent 必须具有明确定义的操作。
- 待处理 intent:待处理 intent 的创建者被视为封装 intent 的发送者,而非待处理 intent 的发送者
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() .detectUnsafeIntentLaunch() .build() ) }
Java
public void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() .detectUnsafeIntentLaunch() .build()); }
Esperienza utente e UI di sistema
Android 15 include alcune modifiche volte a creare un'esperienza utente più coerente e intuitiva.
Modifiche agli riquadri delle finestre
Esistono due modifiche relative ai riquadri di finestre in Android 15: edge-to-edge è applicato per impostazione predefinita e esistono anche modifiche alla configurazione, ad esempio la configurazione predefinita delle barre di sistema.
全面强制执行
Apps are edge-to-edge by default on devices running Android 15 if the app is targeting Android 15 (API level 35).
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-1.png?authuser=8&hl=it)
This is a breaking change that might negatively impact your app's UI. The changes affect the following UI areas:
- Gesture handle navigation bar
- Transparent by default.
- Bottom offset is disabled so content draws behind the system navigation bar unless insets are applied.
setNavigationBarColor
andR.attr#navigationBarColor
are deprecated and don't affect gesture navigation.setNavigationBarContrastEnforced
andR.attr#navigationBarContrastEnforced
continue to have no effect on gesture navigation.
- 3-button navigation
- Opacity set to 80% by default, with color possibly matching the window background.
- Bottom offset disabled so content draws behind the system navigation bar unless insets are applied.
setNavigationBarColor
andR.attr#navigationBarColor
are set to match the window background by default. The window background must be a color drawable for this default to apply. This API is deprecated but continues to affect 3-button navigation.setNavigationBarContrastEnforced
andR.attr#navigationBarContrastEnforced
is true by default, which adds an 80% opaque background across 3-button navigation.
- Status bar
- Transparent by default.
- The top offset is disabled so content draws behind the status bar unless insets are applied.
setStatusBarColor
andR.attr#statusBarColor
are deprecated and have no effect on Android 15.setStatusBarContrastEnforced
andR.attr#statusBarContrastEnforced
are deprecated but still have an effect on Android 15.
- Display cutout
layoutInDisplayCutoutMode
of non-floating windows must beLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
.SHORT_EDGES
,NEVER
andDEFAULT
are interpreted asALWAYS
so that users don't see a Black bar caused by the display cutout and appear edge-to-edge.
The following example shows an app before and after targeting Android 15 (API level 35), and before and after applying insets.
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-4.png?authuser=8&hl=it)
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-6.png?authuser=8&hl=it)
![](https://developer.android.google.cn/static/about/versions/15/images/edge-to-edge-2.png?authuser=8&hl=it)
What to check if your app is already edge-to-edge
If your app is already edge-to-edge and applies insets, you are mostly unimpacted, except in the following scenarios. However, even if you think you aren't impacted, we recommend you test your app.
- You have a non-floating window, such as an
Activity
that usesSHORT_EDGES
,NEVER
orDEFAULT
instead ofLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
. If your app crashes on launch, this might be due to your splashscreen. You can either upgrade the core splashscreen dependency to 1.2.0-alpha01 or later or setwindow.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
. - There might be lower-traffic screens with occluded UI. Verify these
less-visited screens don't have occluded UI. Lower-traffic screens include:
- Onboarding or sign-in screens
- Settings pages
What to check if your app is not already edge-to-edge
If your app is not already edge-to-edge, you are most likely impacted. In addition to the scenarios for apps that are already edge-to-edge, you should consider the following:
- If your app uses Material 3 Components (
androidx.compose.material3
) in compose, such asTopAppBar
,BottomAppBar
, andNavigationBar
, these components are likely not impacted because they automatically handle insets. - If your app is using Material 2 Components (
androidx.compose.material
) in Compose, these components don't automatically handle insets. However, you can get access to the insets and apply them manually. In androidx.compose.material 1.6.0 and later, use thewindowInsets
parameter to apply the insets manually forBottomAppBar
,TopAppBar
,BottomNavigation
, andNavigationRail
. Likewise, use thecontentWindowInsets
parameter forScaffold
. - If your app uses views and Material Components
(
com.google.android.material
), most views-based Material Components such asBottomNavigationView
,BottomAppBar
,NavigationRailView
, orNavigationView
, handle insets and require no additional work. However, you need to addandroid:fitsSystemWindows="true"
if usingAppBarLayout
. - For custom composables, apply the insets manually as padding. If your
content is within a
Scaffold
, you can consume insets using theScaffold
padding values. Otherwise, apply padding using one of theWindowInsets
. - If your app is using views and
BottomSheet
,SideSheet
or custom containers, apply padding usingViewCompat.setOnApplyWindowInsetsListener
. ForRecyclerView
, apply padding using this listener and also addclipToPadding="false"
.
What to check if your app must offer custom background protection
If your app must offer custom background protection to 3-button navigation or
the status bar, you app should place a composable or view behind the system bar
using WindowInsets.Type#tappableElement()
to get the 3-button
navigation bar height or WindowInsets.Type#statusBars
.
Additional edge-to-edge resources
See the Edge to Edge Views and Edge to Edge Compose guides for additional considerations on applying insets.
Deprecated APIs
The following APIs are now deprecated:
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
稳定配置
If your app targets Android 15 (API level 35) or higher, Configuration
no
longer excludes the system bars. If you use the screen size in the
Configuration
class for layout calculation, you should replace it with better
alternatives like an appropriate ViewGroup
, WindowInsets
, or
WindowMetricsCalculator
depending on your need.
Configuration
has been available since API 1. It is typically obtained from
Activity.onConfigurationChanged
. It provides information like window density,
orientation, and sizes. One important characteristic about the window sizes
returned from Configuration
is that it previously excluded the system bars.
The configuration size is typically used for resource selection, such as
/res/layout-h500dp
, and this is still a valid use case. However, using it for
layout calculation has always been discouraged. If you do so, you should move
away from it now. You should replace the use of Configuration
with something
more suitable depending on your use case.
If you use it to calculate the layout, use an appropriate ViewGroup
, such as
CoordinatorLayout
or ConstraintLayout
. If you use it to determine the height
of the system navbar, use WindowInsets
. If you want to know the current size
of your app window, use computeCurrentWindowMetrics
.
The following list describes the fields affected by this change:
Configuration.screenWidthDp
andscreenHeightDp
sizes no longer exclude the system bars.Configuration.smallestScreenWidthDp
is indirectly affected by changes toscreenWidthDp
andscreenHeightDp
.Configuration.orientation
is indirectly affected by changes toscreenWidthDp
andscreenHeightDp
on close-to-square devices.Display.getSize(Point)
is indirectly affected by the changes inConfiguration
. This was deprecated beginning in API level 30.Display.getMetrics()
has already worked like this since API level 33.
L'attributo eleganteTextHeight è impostato su true per impostazione predefinita
Per le app che hanno come target Android 15, l'attributo elegantTextHeight
TextView
diventa true
per impostazione predefinita, sostituendo il
carattere compatto usato per impostazione predefinita con alcuni script che hanno metriche verticali di grandi dimensioni
con una molto più leggibile. Il carattere compatto è stato introdotto per evitare interruzioni nei layout. Android 13 (livello API 33) impedisce molte di queste interruzioni consentendo al layout del testo di estendere l'altezza verticale utilizzando l'attributo fallbackLineSpacing
.
In Android 15, il carattere compatto rimane ancora nel sistema, pertanto la tua app può impostare elegantTextHeight
su false
per avere lo stesso comportamento di prima, ma è improbabile che sia supportato nelle prossime release. Pertanto, se la tua app supporta i seguenti script: arabo, laotiano, Myanmar, tamil, gujarati, kannada, malayalam, Odia, telugu o thailandese, testa l'app impostando elegantTextHeight
su true
.
![](https://developer.android.google.cn/static/about/versions/15/images/elegant-text-height-before.png?authuser=8&hl=it)
elegantTextHeight
per le app che hanno come target Android 14 (livello API 34) e versioni precedenti.![](https://developer.android.google.cn/static/about/versions/15/images/elegant-text-height-after.png?authuser=8&hl=it)
elegantTextHeight
per le app destinate ad Android 15.Cambia la larghezza di TextView per forme di lettere complesse
在以前的 Android 版本中,一些采用复杂形状的草体字体或语言可能会在上一个或下一个字符区域中绘制字母。在某些情况下,此类字母会在开始或结束位置被截断。从 Android 15 开始,TextView
会分配宽度来为此类字母绘制足够的空间,并允许应用请求左侧添加额外的内边距以防止被裁剪。
由于此变更会影响 TextView
确定宽度的方式,因此如果应用以 Android 15 或更高版本为目标平台,TextView
会默认分配更多宽度。您可以通过对 TextView
调用 setUseBoundsForWidth
API 来启用或停用此行为。
由于添加左侧内边距可能会导致现有布局未对齐,因此默认情况下,系统不会添加内边距,即使对于以 Android 15 或更高版本为目标平台的应用也是如此。不过,您可以通过调用 setShiftDrawingOffsetForStartOverhang
添加额外的内边距以防止裁剪。
以下示例展示了这些更改如何改进某些字体和语言的文本布局。
![](https://developer.android.google.cn/static/about/versions/15/images/cursive-clipped.png?authuser=8&hl=it)
<TextView android:fontFamily="cursive" android:text="java" />
![](https://developer.android.google.cn/static/about/versions/15/images/cursive-noclipping.png?authuser=8&hl=it)
<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=8&hl=it)
<TextView android:text="คอมพิวเตอร์" />
![](https://developer.android.google.cn/static/about/versions/15/images/thai-noclipping.png?authuser=8&hl=it)
<TextView android:text="คอมพิวเตอร์" android:useBoundsForWidth="true" android:shiftDrawingOffsetForStartOverhang="true" />
Altezza della riga predefinita sensibile alle impostazioni internazionali per EditText
Nelle versioni precedenti di Android, il layout del testo estendeva l'altezza del testo per adattarlo all'altezza della riga del carattere corrispondente alle impostazioni internazionali correnti. Ad esempio, se i contenuti erano in giapponese, poiché l'altezza della riga del carattere giapponese è leggermente più grande di quella di un carattere latino, l'altezza del testo è aumentata leggermente. Tuttavia, nonostante queste differenze di altezza delle righe, le dimensioni dell'elemento EditText
sono state uniformi, indipendentemente dall'impostazione internazionale utilizzata, come illustrato nell'immagine seguente:
![](https://developer.android.google.cn/static/about/versions/15/images/locale-aware-line-height-before.png?authuser=8&hl=it)
EditText
che possono contenere testo in inglese (en), giapponese (ja) e birmano (my). L'altezza dell'elemento EditText
è la stessa, anche se queste lingue hanno righe di altezza diverse l'una dall'altra.Per le app che hanno come target Android 15, ora viene riservata un'altezza minima della riga per EditText
affinché corrisponda al carattere di riferimento per le impostazioni internazionali specificate, come mostrato nella seguente immagine:
![](https://developer.android.google.cn/static/about/versions/15/images/locale-aware-line-height-after.png?authuser=8&hl=it)
EditText
che possono contenere testo in inglese (en), giapponese (ja) e birmano (my). L'altezza
di EditText
ora include lo spazio per adattarsi
all'altezza della riga predefinita per i caratteri di queste lingue.Se necessario, la tua app può ripristinare il comportamento precedente specificando l'attributo useLocalePreferredLineHeightForMinimum
su false
e la tua app può impostare metriche verticali minime personalizzate utilizzando l'API setMinimumFontMetrics
in Kotlin e Java.
Fotocamera e contenuti multimediali
Android 15 apporta le seguenti modifiche al comportamento della fotocamera e dei contenuti multimediali per le app destinate ad Android 15 o versioni successive.
Limitazioni relative alla richiesta di focus audio
Le app destinate ad Android 15 devono essere quelle di primo livello o avere un servizio in primo piano per poter richiedere lo stato attivo dell'audio. Se un'app
tenta di richiedere lo stato attivo quando non soddisfa uno di questi requisiti, la
chiamata restituisce AUDIOFOCUS_REQUEST_FAILED
.
Puoi scoprire di più sulla messa a fuoco audio su Gestire il focus audio.
Limitazioni non SDK aggiornate
Android 15 include elenchi aggiornati di elementi non SDK soggetti a restrizioni basate sulla collaborazione con gli sviluppatori Android e le applicazioni per i test interni. Quando possibile, facciamo in modo che le alternative pubbliche siano disponibili prima che vengano limitate le interfacce non SDK.
Se la tua app non ha come target Android 15, alcune di queste modifiche potrebbero non riguardarti immediatamente. Tuttavia, sebbene la tua app possa Accedere ad alcune interfacce non SDK a seconda del livello API target dell'app, utilizzando qualsiasi SDK metodo o campo comporta sempre un rischio elevato di danneggiare l'app.
Se non hai la certezza che la tua app utilizzi interfacce non SDK, puoi testa la tua app per scoprirlo. Se la tua app si basa su modelli non SDK dovresti iniziare a pianificare una migrazione alle alternative SDK. Tuttavia, sappiamo che alcune app hanno casi d'uso validi per l'utilizzo interfacce non SDK. Se non riesci a trovare un'alternativa all'utilizzo di una versione non SDK per una funzionalità dell'app, devi richiedere una nuova API pubblica.
Per scoprire di più sulle modifiche in questa release di Android, consulta Aggiornamenti alle limitazioni relative alle interfacce non SDK in Android 15. Per scoprire di più sulle interfacce non SDK in generale, consulta Restrizioni sulle interfacce non SDK.