Livello API: 17
Android 4.2 (JELLY_BEAN_MR1
)
è un aggiornamento della release Jelly Bean che offre nuove funzionalità per utenti e app
sviluppatori. Questo documento fornisce un'introduzione alle
nuove e utili API per gli sviluppatori.
In qualità di sviluppatore di app, devi scaricare l'immagine di sistema Android 4.2 e la piattaforma SDK dalla pagina SDK Manager il prima possibile. Se Se non disponi di un dispositivo con Android 4.2 su cui testare la tua app, utilizza il sistema Android 4.2 per testare la tua app nell'emulatore Android. Quindi crea le tue app sulla base della piattaforma Android 4.2 per iniziare a utilizzare le API più recenti.
Per ottimizzare meglio la tua app per i dispositivi con Android 4.2,
devi impostare targetSdkVersion
su
"17"
, installalo su un'immagine di sistema Android 4.2,
testarlo, quindi pubblicare un aggiornamento con questa modifica.
Tu
possono utilizzare le API in Android 4.2 supportando al contempo le versioni precedenti aggiungendo
condizioni al codice che controllano il livello API di sistema prima di eseguirlo
API non supportate dal tuo minSdkVersion
.
Per scoprire di più su
mantenendo la compatibilità con le versioni precedenti, leggi l'articolo Creazione di una compatibilità con le versioni precedenti
UI.
Ulteriori informazioni su come funzionano i livelli API sono disponibili nella pagina Che cos'è l'API Livello?
Importanti cambiamenti del comportamento
Se hai già pubblicato un'app per Android, tieni presente quanto segue modifiche che potrebbero influire sul comportamento della tua app:
- I fornitori di contenuti non vengono più esportati per impostazione predefinita. Vale a dire, il valore predefinito
dell'attributo
android:exported
ora è“false"
. Se è importante che altre app siano in grado di accedere al tuo fornitore di contenuti, devi impostare esplicitamenteandroid:exported="true"
.Questa modifica ha effetto solo se imposti
android:targetSdkVersion
oandroid:minSdkVersion
su 17 o superiore. In caso contrario, il valore predefinito è sempre“true"
anche con Android 4.2 e versioni successive. - Rispetto alle versioni precedenti di Android, i risultati relativi alla posizione dell'utente potrebbero essere meno precisi
se la tua app richiede l'autorizzazione
ACCESS_COARSE_LOCATION
, ma non richiede l'autorizzazioneACCESS_FINE_LOCATION
.Per soddisfare le aspettative in materia di privacy degli utenti quando la tua app richiede l'autorizzazione per posizione approssimativa (e non precisa), il sistema non fornirà una stima della posizione dell'utente. è più precisa rispetto a un isolato.
- Alcune impostazioni del dispositivo definite da
Settings.System
sono ora di sola lettura. Se la tua app tenta di scrivere modifiche alle impostazioni definite inSettings.System
che sono state spostate inSettings.Global
, l'operazione di scrittura non riuscirà in modo invisibile su Android 4.2 e versioni successive.Anche se il valore di
android:targetSdkVersion
eandroid:minSdkVersion
è inferiore a 17, la tua app non può modificare le impostazioni con spostato inSettings.Global
con Android 4.2 e versioni successive. - Se la tua app utilizza
WebView
, Android 4.2 aggiunge un ulteriore livello di in modo da poter associare più sicuro JavaScript al tuo Codice Android. Se impostitargetSdkVersion
a 17 o superiore, devi aggiungere l'annotazione@JavascriptInterface
a qualsiasi metodo disponibile per il codice JavaScript (anche il metodo deve essere pubblico). Se non fornisci il il metodo non è accessibile da una pagina web inWebView
con Android 4.2 o versioni successive. Se imposti il parametrotargetSdkVersion
alla 16 o a una versione precedente, l'annotazione non è obbligatoria, ma ti consigliamo di aggiornare la versione di destinazione e aggiungi l'annotazione per maggiore sicurezza.Scopri di più sull'associazione da codice JavaScript a codice Android.
Daydream
Daydream è una nuova modalità salvaschermo interattiva per dispositivi Android. Si attiva automaticamente quando il dispositivo è inserito in un dock o quando rimane inattivo mentre è collegato a una base caricabatteria (invece di spegnere lo schermo). Daydream mostra un sogno alla volta e questo potrebbe essere un display passivo e puramente visivo che si spegne al tocco o che può essere interattivo e reattivo all'intera suite di eventi di input. I tuoi sogni vengono inseriti nel processo della tua app e hanno accesso completo il toolkit per la UI di Android, che comprende visualizzazioni, layout e animazioni, in modo da essere più flessibili potente degli sfondi animati o dei widget di app.
Puoi creare un sogno per Daydream implementando una sottoclasse DreamService
. Le API di DreamService
sono
progettati per essere simili a quelli di Activity
. Per specificare l'UI per
Inoltre, passa un ID risorsa di layout o View
a setContentView()
in qualsiasi momento, dopo aver
una finestra, ad esempio da onAttachedToWindow()
di Google.
Il corso DreamService
fornisce altri importanti callback del ciclo di vita
basati sulle API Service
di base, come onDreamingStarted()
, onDreamingStopped()
e onDetachedFromWindow()
.
Non puoi avviare una richiesta DreamService
dal tuo
viene avviata automaticamente dal sistema.
Se il tuo sogno è interattivo, puoi avviare un'attività da quel sogno per indirizzare l'utente
all'UI completa dell'app per maggiori dettagli o controlli. Puoi usare finish()
per terminare il tuo sogno in modo che l'utente possa vedere
nuova attività.
Per rendere disponibile daydream al sistema, dichiara il tuo DreamService
con un elemento <service>
nel file manifest. Devi quindi includere un filtro per intent con l'azione "android.service.dreams.DreamService"
. Ad esempio:
<service android:name=".MyDream" android:exported="true" android:icon="@drawable/dream_icon" android:label="@string/dream_label" > <intent-filter> <action android:name="android.service.dreams.DreamService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
Esistono altri metodi utili in DreamService
tieni presente:
setInteractive(boolean)
stabilisce se il sogno riceve eventi di input o uscite immediatamente dopo l'input dell'utente. Se il tuo sogno interattivo, l'utente può utilizzare i pulsanti Indietro o Home per uscire dalla modalità sogno oppure puoi chiamarefinish()
per fermare il tuo sogno.- Se vuoi un display completamente immersivo, puoi chiamare
setFullscreen()
per nascondere la barra di stato. - Prima dell'avvio di Daydream, la luminosità del display si attenua per segnalare all'utente che il timeout per inattività
si sta avvicinando. Se chiami
setScreenBright(true)
puoi invece impostare il display alla luminosità abituale.
Per saperne di più, consulta la documentazione di DreamService
.
Display secondari
Android ora consente alla tua app di mostrare contenuti esclusivi su schermate aggiuntive collegate
al dispositivo dell'utente tramite una connessione cablata o Wi-Fi.
Per creare contenuti unici per un display secondario, estendi le Presentation
e implementare il callback onCreate()
. Entro
onCreate()
, specifica la tua UI per il display secondario
chiamando il numero setContentView()
.
Essendo un'estensione della classe Dialog
, la classe Presentation
fornisce la regione in cui l'app può visualizzare una UI unica sul
display secondario.
Per rilevare display secondari dove puoi mostrare il tuo Presentation
:
usa DisplayManager
o MediaRouter
su quelle di livello inferiore. Sebbene le API DisplayManager
ti consentano di enumerare
più display che possono essere collegati contemporaneamente, di solito dovresti usare MediaRouter
per accedere rapidamente alla visualizzazione predefinita del sistema per
presentazioni.
Per ottenere la visualizzazione predefinita per la tua presentazione, chiama MediaRouter.getSelectedRoute()
e superala
ROUTE_TYPE_LIVE_VIDEO
. Restituisce un oggetto MediaRouter.RouteInfo
che descrive la route attualmente selezionata dal sistema
per le presentazioni video. Se MediaRouter.RouteInfo
non è null, richiama
getPresentationDisplay()
per visualizzare il Display
che rappresenta il display connesso.
Potrai quindi visualizzare la presentazione passando l'oggetto Display
a un costruttore per il corso Presentation
. La presentazione ora
vengono visualizzati sul display secondario.
Per rilevare in fase di esecuzione la connessione di un nuovo display, crea un'istanza di MediaRouter.SimpleCallback
in cui implementi il metodo di callback onRoutePresentationDisplayChanged()
, che il sistema chiamerà quando un nuovo
è collegato il display della presentazione. Poi registra il valore MediaRouter.SimpleCallback
passandolo a MediaRouter.addCallback()
insieme al tipo di percorso ROUTE_TYPE_LIVE_VIDEO
. Quando ricevi una chiamata a
onRoutePresentationDisplayChanged()
, chiama MediaRouter.getSelectedRoute()
come indicato sopra.
Per ottimizzare ulteriormente l'UI in Presentation
per
schermate secondarie, puoi applicare
un tema diverso specificando l'attributo android:presentationTheme
in <style>
che hai
applicati alla tua applicazione o alla tua attività.
Tieni presente che gli schermi collegati al dispositivo dell'utente spesso hanno schermi di dimensioni maggiori e
potrebbe avere una densità dello schermo diversa. Poiché le caratteristiche dello schermo possono essere diverse,
offrono risorse ottimizzate specificatamente per questi schermi più grandi. Se hai bisogno
per richiedere risorse aggiuntive da Presentation
, chiama getContext()
.getResources()
per ottenere l'oggetto Resources
corrispondente al display. Ciò fornisce
le risorse della tua app più adatte
dimensioni e densità dello schermo secondario.
Per ulteriori informazioni e alcuni esempi di codice, consulta la Presentation
documentazione del corso.
Widget schermata di blocco
Android ora consente agli utenti di aggiungere widget delle app alla schermata di blocco. Per rendere disponibile l'App Widget per l'utilizzo nella
schermata di blocco, aggiungi l'attributo android:widgetCategory
al tuo file XML che specifica AppWidgetProviderInfo
. Questo attributo supporta due valori: home_screen
e keyguard
. Per impostazione predefinita, l'attributo è impostato su home_screen
, quindi gli utenti possono aggiungere il tuo
widget dell'app alla schermata Home. Se vuoi che il widget dell'app sia disponibile anche sulla serratura
schermata, aggiungi il valore keyguard
:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" ... android:widgetCategory="keyguard|home_screen"> </appwidget-provider>
Devi anche specificare un layout iniziale per il widget dell'app quando ti trovi nella schermata di blocco con
l'attributo android:initialKeyguardLayout
. Funziona allo stesso modo di android:initialLayout
, in quanto fornisce
un layout che possa essere visualizzato immediatamente fino a quando il widget dell'app non viene inizializzato e può aggiornare il
layout.
Per ulteriori informazioni sulla creazione di widget di app per la schermata di blocco, incluse le istruzioni per Dimensioni del widget dell'app quando ti trovi nella schermata di blocco, consulta la guida Widget app.
Più utenti
Android ora consente più spazi utente su dispositivi condivisibili come i tablet. Ogni utente su dispositivo dispone di un proprio insieme di account, app, impostazioni di sistema, file e dati associati all'utente.
In qualità di sviluppatore di app, non devi fare nulla per far funzionare la tua app in modo adeguato con più utenti su un unico dispositivo. Indipendentemente dal numero di utenti che possono esistere dispositivo, i dati salvati dall'app per un determinato utente vengono mantenuti separati da quelli salvati dall'app per altri utenti. Il sistema tiene traccia di quali dati utente appartengono al processo utente in cui che l'app sia in esecuzione, che fornisce l'accesso all'app solo ai dati di quell'utente e non consente l'accesso ai dati di altri utenti.
Salvataggio dei dati in un ambiente multiutente
Ogni volta che l'app salva le preferenze dell'utente, crea un database o scrive un file di archiviazione interna o esterna, i dati sono accessibili solo mentre l'utente è in esecuzione.
Per assicurarti che l'app funzioni correttamente in un ambiente multiutente, non fare riferimento alle la directory interna dell'app o la posizione di archiviazione esterna usando percorsi hardcoded e usa sempre le API appropriate:
- Per accedere alla memoria interna, usa
getFilesDir()
,getCacheDir()
oopenFileOutput()
. - Per accedere alla memoria esterna, usa
getExternalFilesDir()
ogetExternalStoragePublicDirectory()
.
Indipendentemente dall'API che utilizzi per salvare i dati di un determinato utente, i dati non verranno accessibili durante l'esecuzione come altro utente. Dal punto di vista della tua app, ogni utente è in esecuzione su un dispositivo completamente separato.
Identificare gli utenti in un ambiente multiutente
Se la tua app vuole identificare utenti unici, ad esempio per raccogliere dati e analisi o creare un altro account
associazioni, devi seguire le pratiche consigliate per identificare
per le installazioni uniche. Creando una nuova UUID
all'avvio dell'app per
la prima volta, avrai la certezza di ottenere un ID univoco per il monitoraggio di ogni utente, indipendentemente dal numero
Gli utenti installano la tua app su un singolo dispositivo. In alternativa, puoi salvare un token locale recuperato da
il tuo server o utilizza l'ID di registrazione fornito da Google Cloud Messaging.
Tieni presente che se la tua app richiede uno degli identificatori del dispositivo hardware (ad esempio l'indirizzo MAC Wi-Fi)
indirizzo IP o il numero di SERIAL
), forniscono lo stesso valore per ogni
perché questi identificatori sono legati all'hardware e non all'utente. Per non parlare dell'altro
i problemi presentati da questi identificatori, come discusso nel documento
Post del blog sulle installazioni di app.
Nuove impostazioni globali
Le impostazioni di sistema sono state aggiornate per supportare più utenti con l'aggiunta di Settings.Global
. Questa raccolta di impostazioni è simile alle impostazioni di Settings.Secure
perché sono di sola lettura, ma viene applicata a livello globale in
tutti gli spazi utente sul dispositivo.
Diverse impostazioni esistenti sono state spostate qui da Settings.System
o Settings.Secure
. Se la tua app è
al momento apporta modifiche alle impostazioni definite in precedenza in Settings.System
(ad es. AIRPLANE_MODE_ON
), dovresti aspettarti che
questa operazione non funzionerà più su un dispositivo con Android 4.2 o versioni successive se tali impostazioni sono
spostato in Settings.Global
. Puoi continuare a leggere le impostazioni in
Settings.Global
, ma poiché le impostazioni non sono più considerate sicure
di modificare le app, se provi a farlo non riuscirai in automatico e il sistema scriverà un avviso
Il log di sistema quando esegui l'app su Android 4.2 o versioni successive.
Supporto layout RTL
Android ora offre diverse API che ti consentono di creare interfacce utente con trasformare l'orientamento del layout per supportare le lingue che utilizzano interfacce utente da destra a sinistra (RTL) e per la lettura come l'arabo e l'ebraico.
Per iniziare a supportare i layout RTL nella tua app, imposta l'attributo android:supportsRtl
sull'elemento <application>
nel file manifest
e imposta il valore “true"
. Una volta abilitata, il sistema abiliterà varie API RTL per
visualizzare la tua app con i layout RTL. Ad esempio, la barra delle azioni mostrerà l'icona e il titolo
sul lato destro e i pulsanti di azione a sinistra ed eventuali layout creati con il
verranno invertiti anche i corsi View
forniti dal framework.
Se hai bisogno di ottimizzare ulteriormente l'aspetto della tua app quando viene visualizzata con un layout RTL, esistono due livelli base di ottimizzazione:
- Conversione delle proprietà di layout orientate a sinistra e a destra in layout orientati all'inizio e alla fine
proprietà.
Ad esempio, usa
android:layout_marginStart
invece diandroid:layout_marginLeft
eandroid:layout_marginEnd
al posto diandroid:layout_marginRight
.La classe
RelativeLayout
fornisce anche il layout corrispondente per sostituire le posizioni sinistra/destra, ad esempioandroid:layout_alignParentStart
a sostituisciandroid:layout_alignParentLeft
eandroid:layout_toStartOf
anzichéandroid:layout_toLeftOf
. - In alternativa, per ottimizzare completamente i layout RTL, puoi fornire dati
file di layout utilizzando il qualificatore di risorse
ldrtl
(ldrtl
è l'acronimo di direzione-layout-da-destra a sinistra}). Ad esempio, puoi salvare i file di layout predefinitires/layout/
e i tuoi layout ottimizzati per RTL inres/layout-ldrtl/
.Il qualificatore
ldrtl
è ottimo per le risorse disabili, in modo che tu possa fornire grafici che sono orientati nella direzione corrispondente alla direzione di lettura.
Nel framework sono disponibili varie altre API per supportare i layout RTL, ad esempio in
la classe View
in modo che tu possa implementare i comportamenti corretti per
viste e in Configuration
per eseguire query sulla direzione del layout corrente.
Nota:se utilizzi SQlite e i nomi di tabelle o colonne sono
"solo numero" essere
attenzione: l'utilizzo di String.format(String, Object...)
può causare errori in cui i numeri
sono state convertite nella lingua araba se il dispositivo è stato impostato sulla lingua araba.
Devi utilizzare String.format(Locale,String,Object...)
per assicurarti che i numeri vengano
e mantenuto come ASCII. Usa anche String.format("%d", int)
anziché usare
String.valueOf(int)
per
formattare i numeri.
Frammenti nidificati
Ora puoi incorporare frammenti all'interno di altri. Ciò è utile per diverse situazioni
inserire componenti dell'interfaccia utente dinamici e riutilizzabili in un componente dell'interfaccia utente stesso
dinamiche e riutilizzabili. Ad esempio, se utilizzi ViewPager
per
creare frammenti che scorrono verso sinistra e destra e occupano gran parte dello spazio sullo schermo,
ora inserisci i frammenti in ogni pagina dei frammenti.
Per nidificare un frammento, richiama semplicemente getChildFragmentManager()
su
Fragment
in cui vuoi aggiungere un frammento. Viene restituito un FragmentManager
che puoi utilizzare come fai normalmente dall'attività di primo livello
per creare transazioni di frammento. Ad esempio, ecco del codice che aggiunge un frammento dall'interno
un corso Fragment
esistente:
Kotlin
val videoFragment = VideoPlayerFragment() childFragmentManager.beginTransaction().apply { add(R.id.video_fragment, videoFragment) commit() }
Java
Fragment videoFragment = new VideoPlayerFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.add(R.id.video_fragment, videoFragment).commit();
Dall'interno di un frammento nidificato, puoi ottenere un riferimento al frammento padre richiamando
getParentFragment()
.
Android Support Library ora supporta anche i frammenti nidificati, in modo da poter implementare progetti di frammenti su Android 1.6 e versioni successive.
Nota: non puoi gonfiare un layout in un frammento quando tale layout
include un <fragment>
. I frammenti nidificati sono supportati solo se aggiunti a
in modo dinamico.
Script di rendering
La funzionalità di calcolo di Renderscript è stata migliorata con le seguenti funzionalità:
- Funzionalità intrinseche dello script
Puoi usare le funzionalità intrinseche degli script integrati di Renderscript che implementano operazioni comuni per te, ad esempio:
Blends
Blur
Color matrix
3x3 convolve
5x5 convolve
Per-channel lookup table
Converting an Android YUV buffer to RGB
Per utilizzare uno script intrinseco, chiama il metodo
create()
statico di ogni per creare un'istanza dello script. Quindi chiamerai ilset()
disponibile metodi di ogni script intrinseco per impostare gli input e le opzioni necessari. Infine, chiamaforEach()
per eseguire lo script.- Gruppi di script
-
Gli
ScriptGroup
ti consentono di collegare il Renderscript correlato script ed eseguirli con una sola chiamata.Utilizza un
ScriptGroup.Builder
per aggiungere tutti gli script al gruppo chiamando il numeroaddKernel()
. Una volta aggiungere tutti gli script, creare le connessioni tra script chiamandoaddConnection()
. Quando hai finito di aggiungere i collegamenti, chiamacreate()
per creare il gruppo di script. Prima di eseguire il gruppo di script, specifica l'inputAllocation
e script iniziale da eseguire consetInput(Script.KernelID, Allocation)
e fornirà l'outputAllocation
in cui verrà scritto il risultato e lo script finale in eseguito consetOutput()
. Infine, richiamaexecute()
per eseguire il gruppo di script. - Script filtro
-
Filtro Script definisce i vincoli sulle API Renderscript esistenti che consentono l'esecuzione del codice risultante su una gamma più ampia di processori (CPU, GPU e DSP). Per creare fileFilterscript, crea
.fs
anziché.rs
e specifica#pragma rs_fp_relaxed
per indicare al runtime di Renderscript che i tuoi script non richiedono una precisione rigorosa in virgola mobile IEEE 754-2008. Questa precisione consente il flush-to-zero dei denormi e l'arrotondamento verso lo zero. Inoltre, il Filtro Script gli script non devono utilizzare tipi integrati a 32 bit e devono specificare una funzione root personalizzata mediante il metodo Attributo__attribute__((kernel))
perché non supporta i cursori, che non sono supportati definita dalla firma predefinita della funzioneroot()
.
Nota. Sebbene il supporto di Filtroscript sia disponibile solo sulla piattaforma, gli sviluppatori sarà disponibile nella versione 21.0.1 di SDK Tools.
Per una visualizzazione dettagliata di tutte le modifiche API in Android 4.2, vedi Report Differenze API.