Panoramica delle funzionalità e delle API

Android 15 introduce funzionalità e API fantastiche per gli sviluppatori. Le sezioni seguenti riepilogano queste funzionalità per aiutarti a iniziare a utilizzare le API correlate.

Per un elenco dettagliato delle API aggiunte, modificate e rimosse, leggi il report sulle differenze delle API. Per informazioni dettagliate sulle API aggiunte, consulta il riferimento all'API Android. Per Android 15, cerca le API aggiunte nel livello API 35. Per scoprire le aree in cui le modifiche alla piattaforma potrebbero influire sulle tue app, consulta le modifiche al comportamento di Android 15 per le app che hanno come target Android 15 e per tutte le app.

Fotocamera e contenuti multimediali

Android 15 include una serie di funzionalità che migliorano l'esperienza con la fotocamera e i contenuti multimediali e che ti consentono di accedere a strumenti e hardware per aiutare i creator a dare vita alle loro idee su Android.

Per saperne di più sulle ultime funzionalità e soluzioni per sviluppatori per contenuti multimediali e fotocamera Android, guarda il talk Creare esperienze multimediali e con la fotocamera Android moderne di Google I/O.

Low Light Boost

Android 15 引入了低光增强,这是一种新的自动曝光模式,可供 Camera 2夜间模式相机扩展使用。“低光增强”功能可调整预览视频流在弱光条件下的曝光量。这与夜间模式相机扩展程序创建静态图片的方式不同,因为夜间模式会组合多张照片来制作单张增强图片。虽然夜间模式非常适合创建静态图片,但无法创建连续的帧流,但“低光增强”可以。因此,“低光增强”可以实现新的相机功能,例如:

  • 提供增强的图片预览,以便用户更好地为弱光环境取景
  • 在光线昏暗的环境下扫描二维码

如果您启用“弱光增强”,它会在光线较暗时自动开启,在光线较暗时关闭。

应用可以在光线昏暗的环境下录制预览流,以保存明亮的视频。

有关详情,请参阅弱光增强

Controlli della fotocamera in-app

Android 15 aggiunge una nuova estensione per un maggiore controllo sull'hardware della fotocamera e sui suoi algoritmi sui dispositivi supportati:

  • Regolazioni avanzate dell'intensità del flash che consentono di controllare con precisione l'intensità del flash in entrambe le modalità SINGLE e TORCH durante l'acquisizione delle immagini.

Controllo del headroom HDR

Android 15 会选择适合底层设备功能和面板的位深的 HDR 余量。对于包含大量 SDR 内容的页面(例如显示单个 HDR 缩略图的即时通讯应用),此行为最终可能会对 SDR 内容的感知亮度产生不利影响。Android 15 允许您使用 setDesiredHdrHeadroom 控制 HDR 余量,以在 SDR 和 HDR 内容之间取得平衡。

左侧屏幕上 SDR 界面元素的亮度似乎比右侧屏幕的亮度更均匀,这模拟了混合 HDR 和 SDR 内容时可能出现的余量问题。通过调整 HDR 余量,您可以在 SDR 和 HDR 内容之间更好地平衡。

Controllo della loudness

Android 15 introduce il supporto per Standard per il volume CTA-2075 per aiutarti evitare incoerenze del volume audio e fare in modo che gli utenti non debbano controllare regolare il volume passando da un contenuto all'altro. Il sistema sfrutta le note alle caratteristiche dei dispositivi di uscita (cuffie e altoparlanti) insieme metadati del volume disponibili nei contenuti audio AAC per regolare in modo intelligente il volume audio e livelli di compressione dell'intervallo dinamico.

Per attivare questa funzionalità, devi assicurarti che i metadati relativi all'intensità siano disponibili nei contenuti AAC e attivare la funzionalità della piattaforma nella tua app. Per farlo, devi creare un oggetto LoudnessCodecController chiamando il relativo metodo di fabbrica create con l'ID sessione audio dell'elemento AudioTrack associato. In questo modo, inizieranno automaticamente ad applicarsi gli aggiornamenti audio. Puoi trasmettere un OnLoudnessCodecUpdateListener per modificare o filtrare i parametri di volume prima di essere applicati MediaCodec.

// Media contains metadata of type MPEG_4 OR MPEG_D
val mediaCodec = 
val audioTrack = AudioTrack.Builder()
                                .setSessionId(sessionId)
                                .build()
...
// Create new loudness controller that applies the parameters to the MediaCodec
try {
   val lcController = LoudnessCodecController.create(mSessionId)
   // Starts applying audio updates for each added MediaCodec
}

Anche ExoPlayer di AndroidX media3 verrà aggiornato per utilizzare le API LoudnessCodecController per un'integrazione perfetta delle app.

Dispositivi MIDI 2.0 virtuali

Android 13 ha aggiunto il supporto per la connessione ai dispositivi MIDI 2.0 tramite USB, che comunicano utilizzando Universal MIDI Packets (UMP). Android 15 estende il supporto di UMP alla tecnologia MIDI virtuale app, che consentono alle app di composizione di controllare le app di sintetizzatore come un dispositivo virtuale MIDI 2.0, proprio come farebbero con un dispositivo USB MIDI 2.0.

Decodifica software AV1 più efficiente

Logo dav1d

dav1d, il popolare decodificatore software AV1 di VideoLAN, è ora disponibile per i dispositivi Android che non supportano la decodifica AV1 nell'hardware. dav1d è fino a 3 volte più potente rispetto al decodificatore software AV1 legacy, consentendo la riproduzione HD AV1 per più utenti, inclusi alcuni dispositivi di livello medio e basso.

Per il momento, l'app deve attivare l'utilizzo di dav1d richiamandola per nome "c2.android.av1-dav1d.decoder". dav1d diventerà il decodificatore software predefinito di AV1 in un aggiornamento successivo. Questo supporto è standardizzato e sottoposto a backporting sui dispositivi Android 11 che ricevono aggiornamenti di sistema Google Play.

Produttività e strumenti per gli sviluppatori

Sebbene la maggior parte del nostro lavoro per migliorare la produttività si basi su strumenti come Android Studio, Jetpack Compose e le librerie Android Jetpack, cerchiamo sempre modi per aiutarti a realizzare più facilmente la tua visione.

Aggiornamenti di OpenJDK 17

Android 15 continua il lavoro di aggiornamento delle librerie di base di Android per allinearsi alle funzionalità delle ultime release di OpenJDK LTS.

Sono inclusi le funzioni e i miglioramenti principali riportati di seguito:

Queste API vengono aggiornate su oltre un miliardo di dispositivi con Android 12 (livello API 31) e versioni successive tramite gli aggiornamenti di sistema di Google Play, in modo da poter scegliere come target le funzionalità di programmazione più recenti.

Miglioramenti ai PDF

Android 15 对 PdfRenderer API 进行了重大改进。应用可以整合呈现等高级功能 受密码保护的文件、注释、表单编辑searching,而 selection 则包含副本。支持线性化 PDF 优化,此功能可加快本地 PDF 查看速度并减少资源使用量。Jetpack PDF 库使用这些 API 来简化 PDF 的添加 查看功能。

<ph type="x-smartling-placeholder">
</ph>
PDF 渲染的最新更新包括 搜索嵌入式 PDF 文件中的内容。

PdfRenderer 已移至一个可使用 Google Play 系统更新独立于平台版本,并且我们支持 将这些变更还原到 Android 11(API 级别 30),方法是创建兼容的 Android 15 之前版本的 API Surface,称为 PdfRendererPreV

Perfezionamenti del passaggio automatico della lingua

Android 14 增加了设备端音频中的多语言识别功能,可在语言之间自动切换,但这可能会导致单词丢失,尤其是在语言切换时,两种话语之间的停顿较少时。Android 15 添加了额外的控件,可帮助应用根据其用例调整此切换。EXTRA_LANGUAGE_SWITCH_INITIAL_ACTIVE_DURATION_TIME_MILLIS 会将自动切换限制为仅在音频会话开始时进行,而 EXTRA_LANGUAGE_SWITCH_MATCH_SWITCHES 则会在指定次数的切换后停用语言切换。如果您希望自动检测到会话期间只讲一种语言,这些选项特别有用。

API OpenType Variable Font migliorata

Android 15 migliora l'usabilità del carattere variabile OpenType. Ora puoi Creare un'istanza FontFamily da un carattere variabile senza specificare degli assi di ponderazione con l'API buildVariableFamily. Il renderer di testo esegue l'override il valore dell'asse wght affinché corrisponda al testo visualizzato.

Se utilizzi la nuova API, questo semplifica il codice per la creazione di una Typeface considerevolmente:

Kotlin

val newTypeface = Typeface.CustomFallbackBuilder(
            FontFamily.Builder(
                Font.Builder(assets, "RobotoFlex.ttf").build())
                    .buildVariableFamily())
    .build()

Java

Typeface newTypeface = Typeface.CustomFallbackBuilder(
            new FontFamily.Builder(
                new Font.Builder(assets, "RobotoFlex.ttf").build())
                    .buildVariableFamily())
    .build();

In precedenza, per creare lo stesso Typeface, era necessario molto più codice:

Kotlin

val oldTypeface = Typeface.CustomFallbackBuilder(
            FontFamily.Builder(
                Font.Builder(assets, "RobotoFlex.ttf")
                    .setFontVariationSettings("'wght' 400")
                    .setWeight(400)
                    .build())
                .addFont(
                    Font.Builder(assets, "RobotoFlex.ttf")
                        .setFontVariationSettings("'wght' 100")
                        .setWeight(100)
                        .build()
                )
                .addFont(
                    Font.Builder(assets, "RobotoFlex.ttf")
                        .setFontVariationSettings("'wght' 200")
                        .setWeight(200)
                        .build()
                )
                .addFont(
                    Font.Builder(assets, "RobotoFlex.ttf")
                        .setFontVariationSettings("'wght' 300")
                        .setWeight(300)
                        .build()
                )
                .addFont(
                    Font.Builder(assets, "RobotoFlex.ttf")
                        .setFontVariationSettings("'wght' 500")
                        .setWeight(500)
                        .build()
                )
                .addFont(
                    Font.Builder(assets, "RobotoFlex.ttf")
                        .setFontVariationSettings("'wght' 600")
                        .setWeight(600)
                        .build()
                )
                .addFont(
                    Font.Builder(assets, "RobotoFlex.ttf")
                        .setFontVariationSettings("'wght' 700")
                        .setWeight(700)
                        .build()
                )
                .addFont(
                    Font.Builder(assets, "RobotoFlex.ttf")
                        .setFontVariationSettings("'wght' 800")
                        .setWeight(800)
                        .build()
                )
                .addFont(
                    Font.Builder(assets, "RobotoFlex.ttf")
                        .setFontVariationSettings("'wght' 900")
                        .setWeight(900)
                        .build()
                ).build()
        ).build()

Java

Typeface oldTypeface = new Typeface.CustomFallbackBuilder(
    new FontFamily.Builder(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 400")
            .setWeight(400)
            .build()
    )
    .addFont(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 100")
            .setWeight(100)
            .build()
    )
    .addFont(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 200")
            .setWeight(200)
            .build()
    )
    .addFont(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 300")
            .setWeight(300)
            .build()
    )
    .addFont(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 500")
            .setWeight(500)
            .build()
    )
    .addFont(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 600")
            .setWeight(600)
            .build()
    )
    .addFont(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 700")
            .setWeight(700)
            .build()
    )
    .addFont(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 800")
            .setWeight(800)
            .build()
    )
    .addFont(
        new Font.Builder(assets, "RobotoFlex.ttf")
            .setFontVariationSettings("'wght' 900")
            .setWeight(900)
            .build()
    )
    .build()
).build();

Ecco un esempio di come è stata creata una risorsa Typeface con sia la vecchia che la nuova API esegue il rendering:

Un esempio di come differisce il rendering dei caratteri tipografici usando i dati vecchi e nuovi
API

In questo esempio, il Typeface creato con l'API precedente non ha il valore capacità di creare spessori di carattere precisi per i modelli 350, 450, 550 e 650 Font, quindi il renderer torna al peso più vicino. Quindi In questo caso, viene eseguito il rendering di 300 anziché 350, di 400 invece di 450 e così via. Al contrario, l'elemento Typeface creato con le nuove API crea in modo dinamico un'istanza Font per un determinato peso, in modo che le ponderazioni siano accurate per 350, 450, 550 e 650.

Controlli granulari delle interruzioni di riga

A partire da Android 15, un TextView e l'interruzione di riga sottostante possono conservare la parte di testo specificata nella stessa riga per migliorare la leggibilità. Puoi sfruttare questa personalizzazione dell'interruzione di riga utilizzando il tag <nobreak> nelle risorse stringa o createNoBreakSpan. Analogamente, puoi impedire la suddivisione delle parole in sillabe utilizzando il tag <nohyphen> o createNoHyphenationSpan.

Ad esempio, la seguente risorsa stringa non include un a capo e viene visualizzata con il testo "Pixel 8 Pro" interrotto in un punto indesiderato:

<resources>
    <string name="pixel8pro">The power and brains behind Pixel 8 Pro.</string>
</resources>

Al contrario, questa risorsa stringa include il tag <nobreak>, che inserisce un a capo nella frase "Pixel 8 Pro" e impedisce gli a capo:

<resources>
    <string name="pixel8pro">The power and brains behind <nobreak>Pixel 8 Pro.</nobreak></string>
</resources>

La differenza nel modo in cui queste stringhe vengono visualizzate è mostrata nelle seguenti immagini:

Layout di una riga di testo in cui la frase "Pixel 8 Pro" non è a capo utilizzando un tag <nobreak>.
Layout per la stessa riga di testo in cui la frase "Pixel 8 Pro" è a capo utilizzando un tag <nobreak>.

Archiviazione delle app

L'anno scorso Android e Google Play hanno annunciato il supporto dell'archiviazione delle app, consentendo agli utenti di liberare spazio rimuovendo parzialmente dal dispositivo le app utilizzate di rado che sono state pubblicate utilizzando Android App Bundle su Google Play. Android 15 include il supporto a livello di sistema operativo per l'archiviazione delle app e l'annullamento dell'archiviazione, semplificando l'implementazione da parte di tutti gli store.

Le app con l'autorizzazione REQUEST_DELETE_PACKAGES possono chiamare il PackageInstaller metodo requestArchive per richiedere l'archiviazione di un pacchetto di app installato, che rimuove l'APK e gli eventuali file memorizzati nella cache, ma persiste dati utente. Le app archiviate vengono restituite come app visualizzabili tramite la API di LauncherApps; gli utenti vedranno un'interfaccia utente per evidenziare che tali utenti vengono archiviate. Se un utente tocca un'app archiviata, l'utente che ha eseguito l'installazione responsabile riceverà una richiesta di annullamento dell'archiviazione del file e il processo di ripristino può monitorate dalla trasmissione ACTION_PACKAGE_ADDED.

Attivare la modalità a 16 KB su un dispositivo utilizzando le opzioni sviluppatore

Attiva/disattiva l'opzione per sviluppatori Avvia con dimensione pagina 16 kB per avviare un dispositivo in modalità a 16 KB.

A partire da Android 15 QPR1, puoi utilizzare l'opzione per gli sviluppatori disponibile su alcuni dispositivi per avviare il dispositivo in modalità 16 KB ed eseguire test sul dispositivo.

Questa opzione per gli sviluppatori è disponibile sui seguenti dispositivi:

  • Pixel 8 e 8 Pro (con Android 15 QPR1 o versioni successive)
  • Pixel 8a (con Android 15 QPR1 o versioni successive)

Grafica

Android 15 offre i più recenti miglioramenti della grafica, tra cui ANGLE e aggiunte al sistema grafico Canvas.

Modernizzazione dell'accesso alla GPU di Android

Logo Vulkan

L'hardware Android si è evoluto molto sin dall'inizio, quando il sistema operativo principale veniva eseguito su una singola CPU e le GPU erano accessibili utilizzando API basate su pipeline a funzione fissa. L'API Vulkan® Graphic è disponibile nell'NDK a partire da Android 7.0 (livello API 24) con un'astrazione di livello inferiore che riflette meglio l'hardware GPU moderno, offre una migliore scalabilità per supportare più core CPU e offre un overhead di driver ridotto per la CPU, migliorando le prestazioni dell'app. Vulkan è supportato da tutti i moderni motori di gioco.

Vulkan è l'interfaccia preferita di Android per la GPU. Pertanto, Android 15 include ANGLE come livello facoltativo per l'esecuzione di OpenGL® ES su Vulkan. Il passaggio ad ANGLE standardizza l'implementazione di OpenGL per Android per migliorare la compatibilità e, in alcuni casi, le prestazioni. Puoi testare la stabilità e le prestazioni dell'app OpenGL ES con ANGLE attivando l'opzione sviluppatore in Impostazioni -> Sistema -> Opzioni sviluppatore -> Sperimentale: attiva ANGLE su Android 15.

Roadmap di Android ANGLE su Vulkan

Roadmap delle prossime modifiche alle API GPU Android.

Nell'ambito della semplificazione del nostro stack di GPU, d'ora in poi forniremo ANGLE come driver di sistema GL su un numero maggiore di nuovi dispositivi, con l'aspettativa futura che OpenID/ES sarà disponibile solo tramite ANGLE. Detto questo, prevediamo di continuare a supportare OpenGL ES su tutti i dispositivi.

Passi successivi consigliati

Utilizza le opzioni sviluppatore per selezionare il driver ANGLE per OpenGL ES e testare l'app. Per i nuovi progetti, consigliamo vivamente di utilizzare Vulkan per C/C++.

Miglioramenti per Canvas

Android 15 continua la nostra modernizzazione del sistema grafico Canvas di Android con nuove funzionalità:

  • Matrix44 fornisce una matrice 4 x 4 per la trasformazione delle coordinate che deve essere utilizzata quando vuoi manipolare il canvas in 3D.
  • clipShader interseca il clip corrente con lo Shader specificato, mentre clipOutShader imposta il clip in base alla differenza tra il clip corrente e lo Shader, ciascuno trattando lo Shader come una maschera alfa. In questo modo è possibile disegnare forme complesse in modo efficiente.

Prestazioni e batteria

Android continua a impegnarsi per aiutarti a migliorare il rendimento e la qualità delle tue app. Android 15 introduce API che consentono di eseguire le attività nell'app in modo più efficiente, ottimizzare il rendimento delle app e raccogliere informazioni sulle tue app.

Per le best practice per il risparmio energetico, il debug dell'utilizzo di rete e di energia e dettagli su come stiamo migliorando l'efficienza energetica del lavoro in background in Android 15 e nelle versioni recenti di Android, consulta la presentazione Migliorare l'efficienza energetica del lavoro in background su Android del Google I/O.

API ApplicationStartInfo

Nelle versioni precedenti di Android, l'avvio delle app era un po' un mistero. Era difficile determinare all'interno dell'app se fosse avviata da uno stato freddo, caldo o caldo. Era anche difficile sapere quanto tempo trascorreva l'app durante le varie fasi di lancio: fork del processo, chiamata a onCreate, disegno del primo frame e altro ancora. Quando è stata creata un'istanza della classe Application, non avevi modo di sapere se l'app veniva avviata da una trasmissione, un fornitore di contenuti, un job, un backup, un avvio completato, una sveglia o una Activity.

L'API ApplicationStartInfo su Android 15 offre tutto questo e molto altro. Puoi anche aggiungere timestamp personalizzati al flusso per raccogliere più facilmente i dati delle tempistiche in un unico posto. Oltre a raccogliere metriche, puoi usare ApplicationStartInfo per ottimizzare direttamente l'avvio dell'app; ad esempio, puoi eliminare la costosa creazione di istanze di librerie relative all'interfaccia utente all'interno della tua classe Application all'avvio della tua app a causa di una trasmissione.

Informazioni dettagliate sulle dimensioni dell'app

A partire da Android 8.0 (livello API 26), Android ha incluso l'API StorageStats.getAppBytes che riassume le dimensioni installate di un'app come un singolo numero di byte, ovvero una somma delle dimensioni dell'APK, delle dimensioni dei file estratti dall'APK e dei file generati sul dispositivo, come il codice compilato in anticipo (AOT). Questo numero non è molto interessante in termini di come la tua app utilizza lo spazio di archiviazione.

Android 15 aggiunge l'API StorageStats.getAppBytesByDataType([type]), che ti consente di ottenere informazioni dettagliate sull'utilizzo di tutto questo spazio da parte della tua app, tra cui suddivisioni dei file APK, codice AOT e velocità di velocità, metadati dex, librerie e profili guidati.

Profilazione gestita dall'app

Android 15 包含 ProfilingManager 类,可让您从应用内部收集性能分析信息,例如堆转储、堆分析报告、堆栈采样等。它使用提供的标记为您的应用提供回调,以标识输出文件,该文件将传递给应用的文件目录。该 API 会进行速率限制,以尽可能降低对性能的影响。

为了简化在应用中构建性能分析请求的过程,我们建议您使用 Core 1.15.0-rc01 或更高版本中的相应 Profiling AndroidX API。

Miglioramenti al database SQLite

Android 15 introduce le API SQLite che espongono funzionalità avanzate motore SQLite sottostante che ha come target specifici problemi di prestazioni che possono manifest nelle app. Queste API sono incluse nell'aggiornamento di SQLite alla versione 3.44.3.

Gli sviluppatori devono consultare le best practice per le prestazioni di SQLite per ottenere il massimo dal proprio database SQLite, in particolare quando si lavora con database di grandi dimensioni o quando si eseguono query sensibili alla latenza.

  • Transazioni differite di sola lettura: quando emetti transazioni di sola lettura (non includono istruzioni di scrittura), utilizza beginTransactionReadOnly() e beginTransactionWithListenerReadOnly(SQLiteTransactionListener) per emettere transazioni DEFERRED di sola lettura. Queste transazioni possono essere eseguite in contemporanea e, se il database è in modalità WAL, eseguita in concomitanza con IMMEDIATE o EXCLUSIVE transazioni.
  • Conteggi e ID righe: sono state aggiunte API per recuperare il conteggio righe o l'ultimo ID riga inserito senza inviare un'ulteriore query. getLastChangedRowCount() restituisce il numero di righe che sono stati inseriti, aggiornati o eliminati dall'istruzione SQL più recente all'interno la transazione corrente e getTotalChangedRowCount() restituisce il conteggio della connessione corrente. getLastInsertRowId() restituisce rowid dell'ultima riga da inserire nella connessione corrente.
  • Istruzioni non elaborate: invia un'istruzione SQlite non elaborata, aggirando la convenienza e l'eventuale overhead di elaborazione aggiuntivo che potrebbe subire.

Aggiornamenti del framework Android Dynamic Performance

Android 15 继续投资开发 Android 动态性能框架 (ADPF),这是一组 API,可让游戏和性能密集型应用更直接地与 Android 设备的电源和散热系统进行互动。在受支持的设备上,Android 15 将添加新的 ADPF 功能:

  • 适用于提示会话的节能模式,用于指明其关联的线程应该优先考虑节能而非性能,非常适合长时间运行的后台工作负载。
  • 可以在提示会话中报告 GPU 和 CPU 的运行时长,从而使系统能够同时调整 CPU 和 GPU 频率,以便更好地满足工作负载需求。
  • 热余量阈值,用于根据余量预测来解释可能的热节流状态。

如需详细了解如何在应用和游戏中使用 ADPF,请参阅相关文档

Privacy

Android 15 include una serie di funzionalità che aiutano gli sviluppatori di app a proteggere la privacy degli utenti.

Rilevamento di registrazioni dello schermo

Android 15 aggiunge il supporto delle app per rilevare che vengono registrate. Un callback viene invocato ogni volta che l'app passa da visibile a invisibile all'interno di una registrazione dello schermo. Un'app è considerata visibile se vengono registrate attività di proprietà dell'UID della procedura di registrazione. In questo modo, se la tua app esegue un'operazione sensibile, puoi informare l'utente che è in corso una registrazione.

val mCallback = Consumer<Int> { state ->
  if (state == SCREEN_RECORDING_STATE_VISIBLE) {
    // We're being recorded
  } else {
    // We're not being recorded
  }
}

override fun onStart() {
   super.onStart()
   val initialState =
      windowManager.addScreenRecordingCallback(mainExecutor, mCallback)
   mCallback.accept(initialState)
}

override fun onStop() {
    super.onStop()
    windowManager.removeScreenRecordingCallback(mCallback)
}

Funzionalità IntentFilter espanse

Android 15 supporta la risoluzione Intent più precisa tramite UriRelativeFilterGroup, che contiene un insieme di UriRelativeFilter oggetti che formano un insieme di Intent regole di corrispondenza che devono essere soddisfatte, inclusi i parametri di query dell'URL, i frammenti di URL e le regole di blocco o esclusione.

Queste regole possono essere definite nel file XML AndroidManifest con il tag <uri-relative-filter-group>, che può includere facoltativamente un tag android:allow. Questi tag possono contenere tag <data> che utilizzano attributi di tag dati esistenti, nonché gli attributi android:query e android:fragment.

Ecco un esempio di sintassi di AndroidManifest:

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.BROWSABLE" />
  <category android:name="android.intent.category.DEFAULT" />
  <data android:scheme="http" />
  <data android:scheme="https" />
  <data android:domain="astore.com" />
  <uri-relative-filter-group>
    <data android:pathPrefix="/auth" />
    <data android:query="region=na" />
  </uri-relative-filter-group>
  <uri-relative-filter-group android:allow="false">
    <data android:pathPrefix="/auth" />
    <data android:query="mobileoptout=true" />
  </uri-relative-filter-group>
  <uri-relative-filter-group android:allow="false">
    <data android:pathPrefix="/auth" />
    <data android:fragmentPrefix="faq" />
  </uri-relative-filter-group>
</intent-filter>

Spazio privato

Lo spazio privato può essere sbloccato e bloccato per mostrarlo o nasconderlo app sensibili su un dispositivo.

Lo spazio privato consente agli utenti di creare uno spazio separato sul proprio dispositivo in cui possono Tenere le app sensibili lontano da occhi indiscreti, sotto un ulteriore strato di autenticazione. Lo spazio privato utilizza un profilo utente separato. L'utente può scegli di usare il blocco dispositivo o un fattore di blocco separato per lo spazio privato.

Le app nello spazio privato vengono visualizzate in un contenitore separato in Avvio app e sono nascosti dalla visualizzazione Recenti, dalle notifiche, dalle impostazioni e dalle altre app quando lo spazio privato è bloccato. I contenuti generati e scaricati dagli utenti (ad esempio contenuti multimediali o file) e gli account siano separati tra lo spazio privato e nello spazio principale. Sharesheet del sistema e è possibile usare il selettore di foto per consentire alle app di accedere ai contenuti se lo spazio privato è sbloccato.

Gli utenti non possono spostare le app esistenti e i loro dati nello spazio privato. Invece, gli utenti selezionano un'opzione di installazione nello spazio privato per installare un'app utilizzando lo store che preferiscono. Le app nello spazio privato vengono installate come copie separate da eventuali app nello spazio principale (nuove copie della stessa app).

Quando un utente blocca lo spazio privato, il profilo viene interrotto. Mentre il profilo viene interrotto, le app nello spazio privato non sono più attive e non possono Attività in primo piano o in background, inclusa la visualizzazione di notifiche.

Ti consigliamo di testare l'app con spazio privato per assicurarti che funziona come previsto, soprattutto se la tua app rientra in una delle seguenti categorie categorie:

Esegui una query sulla selezione utente più recente per l'accesso alle foto selezionate

现在,如果应用获得了部分访问权限,则只能突出显示最近选择的照片和视频。此功能可以改善频繁请求访问照片和视频的应用的用户体验。如需在应用中使用此功能,请在通过 ContentResolver 查询 MediaStore 时启用 QUERY_ARG_LATEST_SELECTION_ONLY 参数。

Kotlin

val externalContentUri = MediaStore.Files.getContentUri("external")

val mediaColumns = arrayOf(
   FileColumns._ID,
   FileColumns.DISPLAY_NAME,
   FileColumns.MIME_TYPE,
)

val queryArgs = bundleOf(
   // Return only items from the last selection (selected photos access)
   QUERY_ARG_LATEST_SELECTION_ONLY to true,
   // Sort returned items chronologically based on when they were added to the device's storage
   QUERY_ARG_SQL_SORT_ORDER to "${FileColumns.DATE_ADDED} DESC",
   QUERY_ARG_SQL_SELECTION to "${FileColumns.MEDIA_TYPE} = ? OR ${FileColumns.MEDIA_TYPE} = ?",
   QUERY_ARG_SQL_SELECTION_ARGS to arrayOf(
       FileColumns.MEDIA_TYPE_IMAGE.toString(),
       FileColumns.MEDIA_TYPE_VIDEO.toString()
   )
)

Java

Uri externalContentUri = MediaStore.Files.getContentUri("external");

String[] mediaColumns = {
    FileColumns._ID,
    FileColumns.DISPLAY_NAME,
    FileColumns.MIME_TYPE
};

Bundle queryArgs = new Bundle();
queryArgs.putBoolean(MediaStore.QUERY_ARG_LATEST_SELECTION_ONLY, true);
queryArgs.putString(MediaStore.QUERY_ARG_SQL_SORT_ORDER, FileColumns.DATE_ADDED + " DESC");
queryArgs.putString(MediaStore.QUERY_ARG_SQL_SELECTION, FileColumns.MEDIA_TYPE + " = ? OR " + FileColumns.MEDIA_TYPE + " = ?");
queryArgs.putStringArray(MediaStore.QUERY_ARG_SQL_SELECTION_ARGS, new String[] {
    String.valueOf(FileColumns.MEDIA_TYPE_IMAGE),
    String.valueOf(FileColumns.MEDIA_TYPE_VIDEO)
});

Privacy Sandbox su Android

Android 15 include le ultime estensioni dei servizi pubblicitari Android, che incorporano la versione più recente di Privacy Sandbox su Android. Questa aggiunta fa parte del nostro lavoro di sviluppo di nuove tecnologie che migliorino la privacy degli utenti e consentano esperienze pubblicitarie efficaci e personalizzate per le app mobile. La nostra pagina Privacy Sandbox contiene ulteriori informazioni sui programmi Anteprima e beta di Privacy Sandbox su Android per aiutarti a iniziare.

Connessione Salute

Android 15 integra le ultime estensioni Connessione Salute di Android, un servizio sicuro e centralizzato per gestire e condividere i dati relativi a salute e fitness raccolti da app. Questo aggiornamento aggiunge il supporto per tipi di dati aggiuntivi in fitness, alimentazione, temperatura cutanea, piani di allenamento e altro ancora.

Il monitoraggio della temperatura cutanea consente agli utenti di memorizzare e condividere dati sulla temperatura più precisi da un dispositivo indossabile o da un altro dispositivo di monitoraggio.

I piani di allenamento sono programmi di allenamento strutturati per aiutare un utente a raggiungere i suoi obiettivi di fitness. Il supporto dei piani di allenamento include una serie di obiettivi di completamento e rendimento:

Scopri di più sugli ultimi aggiornamenti di Connessione Salute su Android nel Creare esperienze adattabili con Android Discussione sulla salute di Google I/O.

Condivisione schermo dell'app

Android 15 supporta la condivisione dello schermo delle app, quindi gli utenti possono condividere o registrare solo una finestra dell'app anziché l'intero schermo del dispositivo. Questa funzionalità, attivata per la prima volta in Android 14 QPR2, include callback di MediaProjection che consentono alla tua app di personalizzare l'esperienza di condivisione schermo dell'app. Tieni presente che per le app che hanno come target Android 14 (livello API 34) o versioni successive, il consenso dell'utente è obbligatorio per ogni sessione di acquisizione MediaProjection.

Esperienza utente e interfaccia utente di sistema

Android 15 offre agli sviluppatori di app e agli utenti maggiore controllo e flessibilità per configurare il proprio dispositivo in base alle proprie esigenze.

Per scoprire di più su come utilizzare i più recenti miglioramenti di Android 15 per migliorare l'esperienza utente della tua app, guarda la presentazione Migliorare l'esperienza utente della tua app Android del Google I/O.

Anteprime dei widget più ricche con l'API Generated Previews

Prima di Android 15, l'unico modo per fornire anteprime del selettore widget era specificare una risorsa immagine o layout statica. Queste anteprime spesso sono diverse molto dall'aspetto del widget reale quando è posizionato sulla home page schermo. Inoltre, non è possibile creare risorse statiche con Jetpack Glance, quindi Riepilogo uno sviluppatore ha dovuto fare uno screenshot del widget o creare un layout XML l'anteprima del widget.

Android 15 aggiunge il supporto per le anteprime generate. Ciò significa che il widget dell'app i provider possono generare RemoteViews da usare come anteprima del selettore, di una risorsa statica.

Le app possono fornire visualizzazioni remote al selettore di widget, in modo da poter aggiornare i contenuti nel selettore in modo che siano più rappresentativi di ciò che vedrà l'utente.

API Push

Le app possono fornire anteprime generate tramite un'API push. Le app possono fornire anteprime in qualsiasi momento del loro ciclo di vita e non ricevono una richiesta esplicita dall'host per fornire anteprime. Le anteprime vengono conservate in AppWidgetService e gli autori possono richiederle on demand. L'esempio seguente carica una risorsa di layout del widget XML e la imposta come anteprima:

AppWidgetManager.getInstance(appContext).setWidgetPreview(
   ComponentName(
       appContext,
       SociaLiteAppWidgetReceiver::class.java
   ),
   AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
   RemoteViews("com.example", R.layout.widget_preview)
)

Il flusso previsto è:

  1. In qualsiasi momento, il fornitore del widget chiama setWidgetPreview. Le anteprime fornite vengono conservate in AppWidgetService insieme ad altre informazioni del fornitore.
  2. setWidgetPreview invia una notifica agli host di un'anteprima aggiornata tramite il callback AppWidgetHost.onProvidersChanged. In risposta, l'host del widget ricarica tutte le informazioni del fornitore.
  3. Quando viene visualizzata un'anteprima del widget, l'host controlla AppWidgetProviderInfo.generatedPreviewCategories e, se la categoria scelta è disponibile, chiama AppWidgetManager.getWidgetPreview per restituire l'anteprima salvata per questo fornitore.

Quando chiamare setWidgetPreview

Poiché non è necessario richiamare le anteprime, le app possono scegliere di inviare vengono visualizzate in qualsiasi momento quando sono in esecuzione. La frequenza con cui aggiornare l'anteprima dipende dal caso d'uso del widget.

L'elenco seguente descrive le due categorie principali di casi d'uso di anteprima:

  • Fornitori che mostrano dati reali nelle anteprime dei widget, ad esempio informazioni personalizzate o recenti. Questi fornitori possono impostare l'anteprima dopo che l'utente ha eseguito l'accesso o ha completato la configurazione iniziale nella propria app. Dopodiché, possono configurare un'attività periodica per aggiornare le anteprime con la cadenza scelta. Esempi di questo tipo di widget possono essere foto, calendario, meteo o notizie.
  • Fornitori che mostrano informazioni statiche nelle anteprime o nei widget di azioni rapide che non mostrano dati. Questi fornitori possono impostare le anteprime una sola volta, quando viene avviata per la prima volta. Alcuni esempi di questo tipo di widget includono una guida rapida widget azioni o widget scorciatoie di Chrome.

Alcuni fornitori potrebbero mostrare anteprime statiche nel selettore della modalità Hub, ma informazioni reali nel selettore della schermata Home. Questi fornitori devono seguire le indicazioni per entrambi i casi d'uso per impostare le anteprime.

Picture in picture

Android 15 introduce modifiche alla modalità Picture in picture (PIP) per garantire una transizione ancora più fluida quando si accede a questa modalità. Ciò è utile per le app con elementi UI sovrapposti alla UI principale, che passa in PIP.

Gli sviluppatori utilizzano il callback onPictureInPictureModeChanged per definire la logica che attiva/disattiva la visibilità degli elementi dell'interfaccia utente sovrapposti. Questo callback viene attivato al termine dell'animazione di entrata o uscita in PiP. A partire da Android 15, la classe PictureInPictureUiState include un altro stato.

Con questo stato dell'interfaccia utente, le app che hanno come target Android 15 (livello API 35) osserveranno il callback Activity#onPictureInPictureUiStateChanged invocato con isTransitioningToPip() non appena inizia l'animazione PiP. Esistono molti elementi dell'interfaccia utente che non sono pertinenti per l'app quando è in modalità PiP, ad esempio visualizzazioni o layout che includono informazioni come suggerimenti, video in programma, valutazioni e titoli. Quando l'app passa in modalità PIP, utilizza il callback onPictureInPictureUiStateChanged per nascondere questi elementi UI. Quando l'app passa alla modalità a schermo intero dalla finestra PiP, utilizza il callback onPictureInPictureModeChanged per mostrare nuovamente questi elementi, come mostrato nei seguenti esempi:

override fun onPictureInPictureUiStateChanged(pipState: PictureInPictureUiState) {
        if (pipState.isTransitioningToPip()) {
          // Hide UI elements
        }
    }
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
        if (isInPictureInPictureMode) {
          // Unhide UI elements
        }
    }

Questa rapida attivazione/disattivazione della visibilità degli elementi dell'interfaccia utente irrilevanti (per una finestra PiP) contribuisce a garantire un'animazione di entrata PiP più fluida e senza sfarfallio.

Regole Non disturbare migliorate

AutomaticZenRule 允许应用自定义注意力机制 管理(勿扰)规则,并确定何时启用或停用 。Android 15 极大地增强了这些规则,旨在提高 用户体验。其中包含以下增强功能:

  • AutomaticZenRule 添加类型,让系统能够应用特殊类型 对某些规则的处理
  • AutomaticZenRule 添加图标,使模式更加丰富 易于识别。
  • triggerDescription 字符串添加到 AutomaticZenRule,用于描述 规则应当对用户生效的条件。
  • 已添加 ZenDeviceEffects 更改为AutomaticZenRule,从而允许规则触发灰度等操作 显示、夜间模式或调暗壁纸。

Impostare VibrationEffect per i canali di notifica

Android 15 supporta l'impostazione di vibrazioni intense per le notifiche in arrivo tramite canale utilizzando NotificationChannel.setVibrationEffect, i tuoi utenti possano distinguere tra diversi tipi di notifiche senza dover guardare il proprio dispositivo.

Chip della barra di stato della proiezione di contenuti multimediali e arresto automatico

La proiezione di contenuti multimediali può esporre informazioni private degli utenti. Un nuovo chip della barra di stato in evidenza informa gli utenti di eventuali proiezioni dello schermo in corso. Gli utenti possono toccare il chip per interrompere la trasmissione, la condivisione o la registrazione dello schermo. Inoltre, per un'esperienza utente più intuitiva, qualsiasi proiezione dello schermo in corso ora si interrompe automaticamente quando lo schermo del dispositivo è bloccato.

Chip barra delle app per condivisione schermo, trasmissione e registrazione.

Schermi e fattori di forma di grandi dimensioni

Android 15 offre alle tue app il supporto necessario per sfruttare al meglio i fattori di forma di Android, inclusi schermi di grandi dimensioni, dispositivi con cerniera e pieghevoli.

Multitasking migliore su schermo grande

Android 15 offre agli utenti modi migliori per svolgere più attività contemporaneamente su dispositivi con schermi grandi. Ad esempio, gli utenti possono salvare le combinazioni di app con schermo diviso preferite per accedervi rapidamente e fissare la barra delle app sullo schermo per passare rapidamente da un'app all'altra. Ciò significa rendere l'app adattiva più importante che mai.

Google I/O offre sessioni su Creazione di app Android adattabili e Creazione di UI con la libreria adattabile Material 3 che possono essere utili. La nostra documentazione contiene ulteriori informazioni per aiutarti a creare design per schermi di grandi dimensioni.

Supporto della schermata del coperchio

La tua app può dichiarare una proprietà utilizzata da Android 15 per consentire la visualizzazione di Application o Activity sulle piccole schermate di copertina dei dispositivi ribaltabili supportati. Queste schermate sono troppo piccole per essere considerate target compatibili per l'esecuzione delle app per Android, ma la tua app può attivarne il supporto, rendendo l'app disponibile in più luoghi.

Connettività

Android 15 aggiorna la piattaforma per consentire alla tua app di accedere agli ultimi progressi nelle tecnologie di comunicazione e wireless.

Assistenza satellitare

Android 15 continua a estendere il supporto delle piattaforme per la connettività satellitare e include alcuni elementi dell'interfaccia utente per garantire un'esperienza utente coerente panorama della connettività satellitare.

Le app possono utilizzare ServiceState.isUsingNonTerrestrialNetwork() per rilevare quando un dispositivo è connesso a un satellite, in modo da avere una maggiore consapevolezza del motivo per cui i servizi di rete completi potrebbero non essere disponibili. Inoltre, Android 15 supporta le app SMS e MMS, nonché le app RCS precaricate, per utilizzare la connettività satellitare per l'invio e la ricezione di messaggi.

Quando il dispositivo si connette a un satellite, viene visualizzata una notifica.

Esperienze NFC più fluide

Android 15 致力于打造更顺畅、更可靠的感应式付款体验,同时继续支持 Android 强大的 NFC 应用生态系统。在受支持的设备上,应用可以请求 NfcAdapter 进入观察模式。在该模式下,设备会监听 NFC 读取器但不会响应 NFC 读取器,从而将应用的 NFC 服务 PollingFrame 对象发送给系统进行处理。PollingFrame 对象可用于在与 NFC 读取器首次通信之前进行身份验证,以便在许多情况下实现一键交易。

此外,应用现在可以在受支持的设备上注册过滤器,以便接收轮询循环 activity 的通知,从而与多个 NFC 感知应用顺畅运行。

Ruolo del portafoglio

Android 15 introduce un nuovo ruolo Wallet che consente una maggiore integrazione con l'app Wallet preferita dell'utente. Questo ruolo sostituisce l'impostazione di pagamento contactless predefinita NFC. Gli utenti possono gestire il titolare del ruolo Wallet andando a Impostazioni > App > App predefinite.

Il ruolo Wallet viene utilizzato per il routing dei tocchi NFC per gli AID registrati nella categoria di pagamento. I tocchi vanno sempre al titolare del ruolo di Wallet, a meno che in primo piano non sia in esecuzione un'altra app registrata per lo stesso AID.

Questo ruolo viene utilizzato anche per determinare dove deve essere inserito il riquadro QuickAccess di Wallet quando viene attivato. Se il ruolo è impostato su "Nessuno", il riquadro QuickAccess non è disponibile e i tocchi NFC della categoria di pagamento vengono inviati solo all'app in primo piano.

Sicurezza

Android 15 ti aiuta a migliorare la sicurezza della tua app, a proteggere i dati della tua app e offre agli utenti maggiore trasparenza e controllo sui propri dati. Guarda la presentazione Safeguarding user security on Android di Google I/O per scoprire di più su cosa stiamo facendo per migliorare le misure di protezione degli utenti e difendere la tua app da nuove minacce.

Integrare Gestore delle credenziali con la compilazione automatica

Starting with Android 15, developers can link specific views like username or password fields with Credential Manager requests, making it easier to provide a tailored user experience during the sign-in process. When the user focuses on one of these views, a corresponding request is sent to Credential Manager. The resulting credentials are aggregated across providers and displayed in autofill fallback UIs, such as inline suggestions or drop-down suggestions. The Jetpack androidx.credentials library is the preferred endpoint for developers to use and will soon be available to further enhance this feature in Android 15 and higher.

Integrare la registrazione e l'accesso con un solo tocco con le richieste biometriche

Gestore delle credenziali integra i prompt biometrici nella creazione delle credenziali e i processi di accesso, eliminando così la necessità da parte dei provider di gestire di prompt biometrici. Di conseguenza, i fornitori di credenziali devono concentrarsi solo i risultati dei flussi create e get, aumentati con il risultato del flusso biometrico. Questo processo semplificato crea credenziali più efficienti e semplificate processo di creazione e recupero.

Gestione delle chiavi per la crittografia end-to-end

Stiamo introducendo E2eeContactKeysManager in Android 15, che semplifica la crittografia end-to-end (E2EE) nelle tue app Android fornendo un'API a livello di sistema operativo per l'archiviazione di chiavi pubbliche crittografiche.

E2eeContactKeysManager è progettato per integrarsi con l'app dei contatti della piattaforma per offrire agli utenti un modo centralizzato per gestire e verificare le chiavi pubbliche dei loro contatti.

Controlli delle autorizzazioni sugli URI dei contenuti

Android 15 introduce un nuovo insieme di API che eseguono controlli delle autorizzazioni sugli URI dei contenuti:

Accessibilità

Android 15 aggiunge funzionalità che migliorano l'accessibilità per gli utenti.

Braille migliore

In Android 15, abbiamo consentito a TalkBack di supportare i display braille che utilizzano lo standard HID sia tramite USB che tramite Bluetooth sicuro.

Questo standard, simile a quello utilizzato per mouse e tastiere, consentirà ad Android di supportare una gamma più ampia di display braille con il passare del tempo.

Internazionalizzazione

Android 15 aggiunge funzionalità che completano l'esperienza utente quando un dispositivo viene utilizzato in lingue diverse.

Carattere variabile CJK

从 Android 15 开始,中文、日语和韩语 (CJK) 语言的字体文件 NotoSansCJK 现已成为可变字体。可变字体为 CJK 语言的广告素材排版开辟了新的可能性。设计师可以探索更广泛的样式,并创建以前难以或无法实现的具有视觉冲击力的布局。

中文、日语和韩语 (CJK) 语言的可变字体在不同字体宽度下的显示效果。

Giustificazione tra caratteri

A partire da Android 15, il testo può essere giustificato utilizzando la spaziatura tra le lettere utilizzando JUSTIFICATION_MODE_INTER_CHARACTER. La giustificazione tra parole era introdotto per la prima volta in Android 8.0 (livello API 26) e giustificazione offre funzionalità simili per i linguaggi che utilizzano spazio vuoto per la segmentazione, ad esempio cinese, giapponese e altri.

Layout del testo in giapponese con JUSTIFICATION_MODE_NONE.
Layout per il testo in inglese utilizzando JUSTIFICATION_MODE_NONE.


Layout per il testo giapponese che utilizza JUSTIFICATION_MODE_INTER_WORD.
Layout per il testo in inglese utilizzando JUSTIFICATION_MODE_INTER_WORD.


Layout del testo in giapponese che utilizza JUSTIFICATION_MODE_INTER_CHARACTER.
Layout per il testo in inglese che utilizza JUSTIFICATION_MODE_INTER_CHARACTER.

Configurazione dell'interruzione di riga automatica

Android 从以下语言开始支持基于短语的日语和韩语换行: Android 13(API 级别 33)。不过,虽然基于短语的行分隔符可以提高短文本行的可读性,但对于长文本行,效果并不理想。在 Android 15 中,应用只能使用 LINE_BREAK_WORD_STYLE_AUTO 选项,针对短文本行应用基于短语的行分隔符。此选项会为文本选择最佳字词样式选项。

对于短文本行,则使用基于短语的换行符,功能相同 为 LINE_BREAK_WORD_STYLE_PHRASE,如 以下图片:

对于短文本行,LINE_BREAK_WORD_STYLE_AUTO 应用基于短语的换行符,以提高文本的可读性。 这与应用 LINE_BREAK_WORD_STYLE_PHRASE

对于较长的文本行,LINE_BREAK_WORD_STYLE_AUTO 会使用 no 换行字词样式, LINE_BREAK_WORD_STYLE_NONE,如 以下图片:

对于较长的文本,LINE_BREAK_WORD_STYLE_AUTO 应用不换行的字词样式,以提高文本的可读性。 这与应用 LINE_BREAK_WORD_STYLE_NONE

Carattere hentaigana giapponese aggiuntivo

In Android 15, un file del carattere per l'hiragana giapponese antico (noto come hentaigana) è incluso per impostazione predefinita. Le forme uniche dei caratteri hentaigana possono aggiungere un tocco distintivo all'artwork o al design, contribuendo al contempo a preservare la trasmissione e la comprensione accurate dei documenti giapponesi antichi.

Carattere e stile del testo dell'hentaigana giapponese .

VideoLAN 锥形版权所有 (c) 1996-2010 VideoLAN。任何人都可以使用或修改此徽标或修改版本来指代 VideoLAN 项目或 VideoLAN 团队开发的任何产品,但不表示该项目的认可。

Vulkan 和 Vulkan 徽标是 Khronos Group Inc.的注册商标。

OpenGL 是注册商标,OpenGL ES 徽标是 Khronos 许可使用的 Hewlett Packard Enterprise 商标。