Livello API: 18
Android 4.3 (JELLY_BEAN_MR2
)
è un aggiornamento della release Jelly Bean che offre nuove funzionalità per utenti e app
sviluppatori. Il presente documento fornisce un'introduzione alle
nuove API.
Se sei uno sviluppatore di app, devi scaricare l'immagine di sistema Android 4.3 e SDK di SDK Manager come il prima possibile. Se non hai un dispositivo con Android 4.3 su cui testare l'app, usare il sistema Android 4.3 per testare la tua app nell'emulatore Android. Dopodiché crea le tue app per la piattaforma Android 4.3 per iniziare a utilizzare le API più recenti.
Aggiorna il livello API target
Per ottimizzare meglio la tua app per i dispositivi con Android 4.3,
devi impostare targetSdkVersion
su
"18"
, installarla su un'immagine di sistema Android 4.3,
testarla e poi pubblicare un aggiornamento con questa modifica.
Puoi utilizzare le API in Android 4.3 e supportare contemporaneamente le versioni precedenti aggiungendo al codice condizioni che controllano il livello API di sistema prima di eseguire le API non supportate dal tuo minSdkVersion
.
Per scoprire di più sul mantenimento della compatibilità con le versioni precedenti, consulta l'articolo Supportare diverse
Versioni della piattaforma.
Nella Support Library di Android sono disponibili anche varie API che consentono di implementare nuove funzionalità sulle versioni precedenti della piattaforma.
Per saperne di più sul funzionamento dei livelli API, consulta Che cos'è il livello API?
Importanti cambiamenti del comportamento
Se hai già pubblicato un'app per Android, tieni presente che la tua app potrebbe essere interessata dalle modifiche in Android 4.3.
Se la tua app utilizza intent impliciti...
La tua app potrebbe non funzionare correttamente in un ambiente con profilo limitato.
Gli utenti in un ambiente con profilo con limitazioni potrebbero non avere tutte le app Android standard disponibili. Ad esempio, in un profilo limitato il browser web e l'app della fotocamera potrebbero essere disattivati. Quindi la tua app non deve fare ipotesi su quali app
disponibile perché se chiami startActivity()
senza
verificare se un'app è disponibile per gestire Intent
,
la tua app potrebbe arrestarsi in modo anomalo in un profilo con limitazioni.
Quando utilizzi un'intent implicita, devi sempre verificare che sia disponibile un'app per gestirla chiamando resolveActivity()
o queryIntentActivities()
. Ad esempio:
Kotlin
val intent = Intent(Intent.ACTION_SEND) ... if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show() }
Java
Intent intent = new Intent(Intent.ACTION_SEND); ... if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show(); }
Se la tua app dipende dagli account...
La tua app potrebbe non funzionare correttamente in un ambiente con profilo limitato.
Per impostazione predefinita, gli utenti in un ambiente con profilo limitato non hanno accesso agli account utente.
Se la tua app dipende da un Account
, potrebbe arrestarsi in modo anomalo o comportarsi in modo imprevisto se utilizzata in un profilo con limitazioni.
Se preferisci impedire ai profili con limitazioni di utilizzare completamente la tua app perché
dipende dai dati dell'account sensibili. Specifica l'attributo android:requiredAccountType
nel campo <application>
del file manifest.
.
Se vuoi consentire ai profili con limitazioni di continuare a usare la tua app anche se non possono creare i propri account, quindi disattivare le funzionalità dell'app che richiedono un account o consentire ai profili con limitazioni di accedere agli account creati dall'utente principale. Per ulteriori informazioni, consulta la sezione di seguito relativa all'assistenza per gli account in un profilo con limitazioni.
Se la tua app utilizza VideoView…
Il video potrebbe apparire più piccolo su Android 4.3.
Nelle versioni precedenti di Android, il widget VideoView
calcolava erroneamente il valore "wrap_content"
per layout_height
e layout_width
come uguale a "match_parent"
. Pertanto, se in precedenza utilizzavi "wrap_content"
per l'altezza o la larghezza, potresti aver ottenuto il layout video desiderato, ma ora potresti ottenere un video molto più piccolo su Android 4.3 e versioni successive. Per risolvere il problema, sostituisci
"wrap_content"
con "match_parent"
e verifica che il video venga visualizzato come previsto su
Android 4.3 e sulle versioni precedenti.
Profili con limitazioni
Sui tablet Android, ora gli utenti possono creare profili con limitazioni in base all'utente principale. Quando gli utenti creano un profilo con limitazioni, possono attivare limitazioni come le app disponibili per il profilo. Un nuovo insieme di API in Android 4.3 ti consente inoltre di creare impostazioni di limitazione granulari per le app che sviluppi. Ad esempio, utilizzando le nuove API, puoi consentire agli utenti di controllare il tipo di contenuti disponibili all'interno della tua app quando viene eseguita in un ambiente con profilo limitato.
L'interfaccia utente che consente agli utenti di controllare le limitazioni che hai creato è gestita dall'applicazione Impostazioni del sistema. Per mostrare all'utente le impostazioni relative alle limitazioni dell'app:
devi dichiarare le limitazioni fornite dalla tua app creando un elemento BroadcastReceiver
che riceve l'intent ACTION_GET_RESTRICTION_ENTRIES
. Il sistema richiama questo intento per eseguire query su tutte le app per verificare le restrizioni disponibili, quindi crea l'interfaccia utente per consentire all'utente principale di gestire le restrizioni per ogni profilo con limitazioni.
Nel metodo onReceive()
del tuo BroadcastReceiver
, devi creare un RestrictionEntry
per ogni limitazione fornita dalla tua app. Ogni RestrictionEntry
definisce un titolo, una descrizione e uno dei
i seguenti tipi di dati:
TYPE_BOOLEAN
per una limitazione che è true o false.TYPE_CHOICE
per una limitazione con più opzioni mutuamente esclusive (scelte di pulsanti di opzione).TYPE_MULTI_SELECT
per una limitazione che contiene più opzioni che non si escludono a vicenda (opzioni di casella di controllo).
Quindi inserisci tutti gli oggetti RestrictionEntry
in un ArrayList
e li inserisci nel risultato del broadcast receiver come valore per il parametro
EXTRA_RESTRICTIONS_LIST
extra.
Il sistema crea l'interfaccia utente per le restrizioni della tua app nell'app Impostazioni e salva ogni limitazione con la chiave univoca che hai fornito per ogni oggetto RestrictionEntry
. Quando l'utente apre la tua app, puoi eseguire una query per conoscere eventuali restrizioni attuali
chiamata getApplicationRestrictions()
.
Viene restituito un Bundle
contenente le coppie chiave-valore per ogni limitazione
che hai definito con gli oggetti RestrictionEntry
.
Se vuoi fornire restrizioni più specifiche che non possono essere gestite da valori booleani,
scelta e valori a scelta multipla, puoi creare un'attività in cui l'utente può specificare
restrizioni e consentono agli utenti di aprire questa attività dalle impostazioni delle limitazioni. Nel tuo
broadcast receiver, includi il EXTRA_RESTRICTIONS_INTENT
extra
nel risultato Bundle
. Questo extra deve specificare un Intent
che indica la classe Activity
da avviare (utilizza il
putParcelable()
per trasmettere EXTRA_RESTRICTIONS_INTENT
con l'intent).
Quando l'utente principale accede alla tua attività per impostare limitazioni personalizzate, l'attività deve restituire un risultato contenente i valori delle limitazioni in un extra utilizzando la chiave EXTRA_RESTRICTIONS_LIST
o EXTRA_RESTRICTIONS_BUNDLE
, a seconda che tu specifichi rispettivamente oggetti RestrictionEntry
o coppie chiave-valore.
Account di assistenza in un profilo con limitazioni
Tutti gli account aggiunti all'utente principale sono disponibili per un profilo con limitazioni, ma per impostazione predefinita non sono accessibili dalle API AccountManager
.
Se provi ad aggiungere un account con AccountManager
in un profilo con limitazioni, verrà visualizzato un risultato di errore. A causa di queste limitazioni, puoi usufruire di:
tre opzioni:
Per accedere a un account da un profilo limitato, devi aggiungere l'attributo android:restrictedAccountType
al tag <application>:
<application ... android:restrictedAccountType="com.example.account.type" >
Attenzione: l'attivazione di questo attributo fornisce Accesso delle app agli account dell'utente principale dai profili con limitazioni. Dovresti quindi consentire solo se le informazioni visualizzate dall'app non rivelano l'identificazione personale informazioni (PII) considerate sensibili. Le impostazioni di sistema informeranno l'utente principale che la tua app concede profili con limitazioni ai suoi account, quindi dovrebbe essere chiaro all'utente che l'accesso all'account è importante per la funzionalità della tua app. Se possibile, devi anche Fornire adeguati controlli delle restrizioni per l'utente principale che definiscono il livello di accesso all'account è consentito nella tua app.
Se vuoi utilizzare gli account, ma non li richiedi effettivamente per la funzionalità principale della tua app, puoi verificare la disponibilità degli account e disattivare le funzionalità quando non sono disponibili.
Per prima cosa, controlla se è disponibile un account esistente. In caso contrario, verifica se è possibile creare un nuovo account chiamando getUserRestrictions()
e controlla l'extra DISALLOW_MODIFY_ACCOUNTS
nel risultato. Se è true
,
devi disattivare qualsiasi funzionalità della tua app che richiede l'accesso agli account.
Ad esempio:
Kotlin
val um = context.getSystemService(Context.USER_SERVICE) as UserManager val restrictions: Bundle = um.userRestrictions if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality }
Java
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); Bundle restrictions = um.getUserRestrictions(); if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality }
Nota: in questo scenario, non dichiarare nuovi attributi nel file manifest.
Se invece è importante che la tua app non sia disponibile per i profili con limitazioni perché dipende da informazioni personali sensibili in un account (e perché al momento i profili con limitazioni non possono aggiungere nuovi account), aggiungi l'attributo android:requiredAccountType
al tag <application>:
<application ... android:requiredAccountType="com.example.account.type" >
Ad esempio, l'app Gmail utilizza questo attributo per disattivarsi per i profili con limitazioni, poiché l'email personale del proprietario non deve essere disponibile per i profili con limitazioni.
Wireless e connettività
Bluetooth Low Energy (Smart Ready)
Android ora supporta Bluetooth Low Energy (LE) con nuove API in android.bluetooth
.
Con le nuove API puoi creare app Android che comunicano con Bluetooth Low Energy
periferiche come rilevatori del battito cardiaco e contapassi.
Poiché Bluetooth LE è una funzione hardware che non è disponibile
I dispositivi basati su Android, devi dichiarare nel file manifest un <uses-feature>
elemento per "android.hardware.bluetooth_le"
:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
Se hai già dimestichezza con le API Bluetooth Classic di Android, tieni presente che l'utilizzo delle API Bluetooth LE presenta alcune differenze. La cosa più importante è che ora esiste una classe BluetoothManager
che dovresti utilizzare per alcune operazioni di alto livello
come acquisire un BluetoothAdapter
, ottenere un elenco di
dispositivi e controllare lo stato di un dispositivo. Ad esempio, ecco come dovresti ottenere il
BluetoothAdapter
:
Kotlin
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothAdapter = bluetoothManager.adapter
Java
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter();
Per trovare le periferiche Bluetooth LE, chiama startLeScan()
sul dispositivo BluetoothAdapter
, passandogli un'implementazione
dell'interfaccia BluetoothAdapter.LeScanCallback
. Quando la funzionalità Bluetooth
rileva una periferica Bluetooth LE, la tua implementazione BluetoothAdapter.LeScanCallback
riceve una chiamata al
Metodo onLeScan()
. Questo
fornisce un oggetto BluetoothDevice
che rappresenta
dispositivo rilevato, il valore RSSI relativo al dispositivo e un array di byte contenente
record della pubblicità.
Se vuoi eseguire la scansione solo per tipi specifici di periferiche, puoi invece chiamare startLeScan()
e includere un array di oggetti UUID
che specificano i servizi GATT supportati dalla tua app.
Nota: puoi cercare solo dispositivi Bluetooth LE oppure cerca dispositivi Bluetooth classici utilizzando le API precedenti. Impossibile scansionare contemporaneamente LE e Classic dispositivi Bluetooth contemporaneamente.
Per connetterti a una periferica Bluetooth LE, chiama connectGatt()
sul
BluetoothDevice
, passandogli un'implementazione
BluetoothGattCallback
. La tua implementazione di BluetoothGattCallback
riceve callback relativi alla connettività
lo stato del dispositivo e altri eventi. È durante onConnectionStateChange()
callback che puoi iniziare a comunicare con il dispositivo se il metodo supera STATE_CONNECTED
come nuovo stato.
L'accesso alle funzioni Bluetooth su un dispositivo richiede inoltre che l'app richieda determinati Autorizzazioni utente Bluetooth. Per ulteriori informazioni, consulta la guida all'API Bluetooth Low Energy.
Modalità solo ricerca Wi-Fi
Quando tenta di identificare la posizione dell'utente, Android potrebbe utilizzare il Wi-Fi per contribuire a determinare la posizione mediante la scansione dei punti di accesso nelle vicinanze. Tuttavia, gli utenti spesso mantengono disattivato il Wi-Fi per risparmiare batteria, con conseguente generazione di dati sulla posizione meno precisi. Android ora include un modalità di sola ricerca che consente al Wi-Fi del dispositivo di scansionare i punti di accesso per contribuire a ottenere la posizione senza connettersi a un punto di accesso, riducendo notevolmente l'utilizzo della batteria.
Se vuoi acquisire la posizione dell'utente ma il Wi-Fi è attualmente disattivato, puoi richiedere
all'utente di attivare la modalità di sola ricerca Wi-Fi chiamando startActivity()
con l'azione ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
.
Configurazione Wi-Fi
Le nuove API WifiEnterpriseConfig
consentono ai servizi orientati alle aziende di
automatizzare la configurazione del Wi-Fi per i dispositivi gestiti.
Risposta rapida per le chiamate in arrivo
Da Android 4.0, una funzionalità chiamata "Risposta rapida" consente agli utenti di rispondere alle chiamate in arrivo con un messaggio immediato senza dover rispondere alla chiamata o sbloccare il dispositivo.
Fino a ora, questi messaggi rapidi venivano sempre gestiti dall'app Messaggi predefinita. Ora qualsiasi app può dichiarare la propria capacità di gestire questi messaggi creando un Service
con un filtro intent per ACTION_RESPOND_VIA_MESSAGE
.
Quando l'utente risponde a una chiamata in arrivo con una risposta rapida, l'app Telefono invia
l'intent ACTION_RESPOND_VIA_MESSAGE
con un URI
che descrive il destinatario (il chiamante) e l'extra EXTRA_TEXT
con il messaggio che l'utente vuole inviare. Quando il servizio riceve l'intent, dovrebbe consegnare
il messaggio e si interrompono immediatamente (la tua app non dovrebbe mostrare un'attività).
Per ricevere questo intento, devi dichiarare l'autorizzazione SEND_RESPOND_VIA_MESSAGE
.
Multimediale
Miglioramenti a MediaExtractor e MediaCodec
Ora Android semplifica la scrittura di lettori Dynamic Adaptive Streaming over HTTP (DASH) in conformità allo standard ISO/IEC 23009-1, utilizzando le API esistenti in MediaCodec
e MediaExtractor
. Il framework alla base di queste API è stato aggiornato per supportare
analisi di file MP4 frammentati, ma la tua app è ancora responsabile dell'analisi dei metadati MPD
e passando i singoli stream a MediaExtractor
.
Se vuoi utilizzare DASH con contenuti criptati, tieni presente che il metodo getSampleCryptoInfo()
restituisce i metadati MediaCodec.CryptoInfo
che descrivono la struttura di ogni contenuto multimediale criptato
campione. Inoltre, il metodo getPsshInfo()
è stato aggiunto
MediaExtractor
in modo da poter accedere ai metadati PSSH per i contenuti multimediali DASH.
Questo metodo restituisce una mappa di oggetti UUID
in byte, con il UUID
che specifica lo schema di crittografia e i byte che rappresentano i dati specifici per lo schema.
DRM multimediale
La nuova classe MediaDrm
offre una soluzione modulare per i diritti digitali
(DRM) con i tuoi contenuti multimediali separando i problemi DRM dalla riproduzione di contenuti multimediali. Ad esempio, questa separazione dell'API ti consente di riprodurre contenuti criptati con Widevine senza dover utilizzare il formato multimediale Widevine. Questa soluzione DRM supporta anche la crittografia DASH Common, pertanto puoi utilizzare una serie di schemi DRM con i tuoi contenuti in streaming.
Puoi utilizzare MediaDrm
per ottenere messaggi di richiesta di chiavi opachi ed elaborare messaggi di risposta con chiave dal server per l'acquisizione e il provisioning delle licenze. La tua app è
responsabile della gestione delle comunicazioni di rete con i server; la classe MediaDrm
fornisce solo la possibilità di generare ed elaborare i messaggi.
Le API MediaDrm
sono progettate per essere utilizzate in combinazione con le API MediaCodec
introdotte in Android 4.1 (livello API 16), tra cui MediaCodec
per la codifica e la decodifica dei contenuti, MediaCrypto
per la gestione dei contenuti criptati e MediaExtractor
per l'estrazione e il demuxing dei contenuti.
Devi prima creare gli oggetti MediaExtractor
e
MediaCodec
. Puoi quindi accedere al set di dati
UUID
, che in genere si trovano nei metadati dei contenuti, e li usa per creare un
di un oggetto MediaDrm
con il relativo costruttore.
Codifica video da una piattaforma
Android 4.1 (livello API 16) ha aggiunto la classe MediaCodec
per la codifica e la decodifica di basso livello dei contenuti multimediali. Durante la codifica video, Android 4.1 richiedeva di fornire ai contenuti multimediali un array ByteBuffer
, ma ora Android 4.3 consente di utilizzare un Surface
come input per un codificatore. Ad esempio, ti consente di codificare l'input da un file video esistente o utilizzando frame generati da OpenGL ES.
Per utilizzare un Surface
come input per il codificatore, chiama prima configure()
per il tuo MediaCodec
.
Quindi chiama createInputSurface()
per ricevere il Surface
su cui puoi riprodurre in streaming i tuoi contenuti multimediali.
Ad esempio, puoi utilizzare il valore Surface
specificato come finestra per un report OpenGL
contesto passandolo a eglCreateWindowSurface()
. Poi, durante il rendering della superficie, chiama eglSwapBuffers()
per passare il frame a MediaCodec
.
Per iniziare la codifica, chiama start()
sul MediaCodec
. Al termine, chiama signalEndOfInputStream()
per terminare la codifica e chiama release()
su
Surface
.
Mux dei contenuti multimediali
La nuova classe MediaMuxer
consente il multiplex tra uno stream audio
e uno stream video. Queste API fungono da controparte della classe MediaExtractor
aggiunta in Android 4.2 per il demultiplexing (demuxing) dei contenuti multimediali.
I formati di output supportati sono definiti in MediaMuxer.OutputFormat
. Al momento,
MediaMuxer
supporta solo un solo stream audio e/o un solo stream video alla volta.
MediaMuxer
è progettato principalmente per funzionare con MediaCodec
in modo da poter eseguire l'elaborazione video tramite MediaCodec
e poi salvare il
risultato in un file MP4 tramite MediaMuxer
. Puoi anche utilizzare MediaMuxer
in combinazione con MediaExtractor
per eseguire
l'editing multimediale senza la necessità di codifica o decodifica.
Avanzamento della riproduzione e scrubbing per RemoteControlClient
In Android 4.0 (livello API 14), è stato aggiunto il valore RemoteControlClient
per attivare i controlli di riproduzione dei contenuti multimediali dai client di controllo remoto, ad esempio i controlli disponibili nella schermata di blocco. Android 4.3 ora offre a questi controller la possibilità di visualizzare la posizione di riproduzione e i controlli per la ricerca rapida della riproduzione. Se hai attivato il controllo remoto per il tuo
app multimediale con le API RemoteControlClient
, dopodiché potrai consentire la riproduzione
eseguire lo scrubbing implementando due nuove interfacce.
Innanzitutto, devi attivare il flag FLAG_KEY_MEDIA_POSITION_UPDATE
passandolo a
setTransportControlsFlags()
.
Poi, implementa le due nuove interfacce seguenti:
RemoteControlClient.OnGetPlaybackPositionListener
- Sono inclusi il callout
onGetPlaybackPosition()
, che richiede la posizione corrente dei contenuti multimediali quando il telecomando deve aggiornare l'avanzamento nella sua UI. RemoteControlClient.OnPlaybackPositionUpdateListener
- Sono inclusi i callback
onPlaybackPositionUpdate()
, che indicano alla tua app il nuovo codice di tempo per i contenuti multimediali quando l'utente esegue la scansione della riproduzione con l'interfaccia utente del telecomando.Dopo aver aggiornato la riproduzione con la nuova posizione, chiama
setPlaybackState()
per indicare nuovi stati, posizione e velocità di riproduzione.
Una volta definite queste interfacce, puoi impostarle per RemoteControlClient
chiamando setOnGetPlaybackPositionListener()
e
rispettivamente setPlaybackPositionUpdateListener()
.
Grafica
Supporto per OpenGL ES 3.0
Android 4.3 aggiunge interfacce Java e supporto nativo per OpenGL ES 3.0. Le nuove funzionalità principali fornite in OpenGL ES 3.0 includono:
- Accelerazione degli effetti visivi avanzati
- Compressione delle texture ETC2/EAC di alta qualità come funzionalità standard
- Una nuova versione del linguaggio di ombreggiatura GLSL ES con supporto di numeri interi e in virgola mobile a 32 bit
- Rendering delle texture avanzato
- Standardizzazione più ampia delle dimensioni delle texture e dei formati della memoria di rendering
L'interfaccia Java per OpenGL ES 3.0 su Android è fornita con GLES30
.
Quando utilizzi OpenGL ES 3.0, assicurati di dichiararlo nel file manifest con il tag <uses-feature> e l'attributo android:glEsVersion
. Ad esempio:
<manifest> <uses-feature android:glEsVersion="0x00030000" /> ... </manifest>
E ricorda di specificare il contesto OpenGL ES richiamando setEGLContextClientVersion()
,
passando 3
come versione.
Per ulteriori informazioni sull'utilizzo di OpenGL ES, inclusa la verifica della versione OpenGL ES supportata del dispositivo in fase di esecuzione, consulta la guida all'API OpenGL ES.
Mipmapping per drawables
L'utilizzo di una mipmap come origine per la tua bitmap o il tuo drawable è un modo semplice per fornire un di alta qualità e diverse scale dell'immagine, il che può essere particolarmente utile se si prevede immagine da ridimensionare durante un'animazione.
Android 4.2 (livello API 17) ha aggiunto il supporto delle mipmap in Bitmap
di classe: Android scambia le immagini mip in Bitmap
dopo
hanno fornito un'origine mipmap e hanno abilitato setHasMipMap()
. Ora in Android 4.3 puoi attivare le mipmap anche per un oggetto BitmapDrawable
, fornendo un asset mipmap e
impostando l'attributo android:mipMap
in un file di risorse bitmap o chiamando hasMipMap()
.
Interfaccia utente
Visualizza overlay
La nuova classe ViewOverlay
fornisce un livello trasparente sopra
un View
su cui puoi aggiungere contenuti visivi e che non influiscono
la gerarchia del layout. Puoi ottenere un ViewOverlay
per qualsiasi View
chiamando il numero getOverlay()
. L'overlay
ha sempre le stesse dimensioni e la stessa posizione della vista host (la vista da cui è stata creata),
consentendoti di aggiungere contenuti che appaiono davanti alla vista dell'host ma che non possono estendersi
entro i limiti di quella vista host.
L'utilizzo di un ViewOverlay
è particolarmente utile quando vuoi creare animazioni, ad esempio far scorrere una visualizzazione all'esterno del relativo contenitore o spostare elementi sullo schermo senza influire sulla gerarchia delle visualizzazioni. Tuttavia, poiché l'area utilizzabile di un overlay è
limitato alla stessa area della vista host, se vuoi animare una visualizzazione spostandoti all'esterno
dalla sua posizione nel layout, devi utilizzare un overlay di una vista principale che abbia lo stesso
limiti del layout.
Quando crei un overlay per una visualizzazione widget come Button
,
puoi aggiungere Drawable
oggetti all'overlay chiamando
add(Drawable)
. Se chiami getOverlay()
per una visualizzazione del layout, ad esempio RelativeLayout
,
l'oggetto restituito è un ViewGroupOverlay
. La
La classe ViewGroupOverlay
è una sottoclasse
di ViewOverlay
che ti consente anche di aggiungere View
richiamando add(View)
.
Nota: tutti gli elementi Drawable e le visualizzazioni aggiunti a un overlay sono solo di visualizzazione. Non possono ricevere stato attivo o eventi di input.
Ad esempio, il seguente codice anima una vista che scorre verso destra inserendola nell'overlay della vista principale, quindi esegue un'animazione di traslazione su quella vista:
Kotlin
val view: View? = findViewById(R.id.view_to_remove) val container: ViewGroup? = view?.parent as ViewGroup container?.apply { overlay.add(view) ObjectAnimator.ofFloat(view, "translationX", right.toFloat()) .start() }
Java
View view = findViewById(R.id.view_to_remove); ViewGroup container = (ViewGroup) view.getParent(); container.getOverlay().add(view); ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight()); anim.start();
Layout limiti ottici
Per le visualizzazioni che contengono immagini di sfondo nine-patch, ora puoi specificare che devono essere allineate alle visualizzazioni adiacenti in base ai limiti "ottici" dell'immagine di sfondo anziché ai limiti "clip" della visualizzazione.
Ad esempio, le figure 1 e 2 mostrano ciascuna lo stesso layout, ma la versione nella figura 1 è utilizzando i limiti di clip (comportamento predefinito), mentre la figura 2 utilizza i limiti ottici. Poiché le immagini con nove patch utilizzate per il pulsante e la cornice digitale includono spaziature interne intorno ai bordi, non sembrano allinearsi tra loro o con il testo quando vengono usati i limiti dei clip.
Nota: gli screenshot nelle figure 1 e 2 mostrano la dicitura "Mostra limiti di layout" impostazione sviluppatore attivata. Per ogni vista, le linee rosse indicano il sensore ottico limiti, le linee blu indicano i limiti del clip e il rosa indica quelli.

Figura 1. Layout con limiti di clip (impostazione predefinita).

Figura 2. Layout con limiti ottici.
Per allineare le visualizzazioni in base ai relativi limiti ottici, imposta l'attributo android:layoutMode
su "opticalBounds"
in uno dei layout principali. Ad esempio:
<LinearLayout android:layoutMode="opticalBounds" ... >

Figura 3. Visualizzazione ingrandita del nine-patch del pulsante Holo con limiti ottici.
Affinché questo comando funzioni, le nove immagini con patch applicate allo sfondo delle viste devono specificare i limiti ottici utilizzando le linee rosse lungo la parte inferiore e il lato destro del file con nove patch (come come mostrato nella figura 3). Le linee rosse indicano la regione da sottrarre i limiti del clip, lasciando i margini ottici dell'immagine.
Quando attivi i limiti ottici per un elemento ViewGroup
nel layout,
le viste discendenti ereditano la modalità di layout dei limiti ottici a meno che non la sostituisci per un gruppo
impostazione di android:layoutMode
su "clipBounds"
. Tutti gli elementi di layout rispettano inoltre
limiti ottici delle visualizzazioni del figlio, adattando i propri limiti in base ai limiti ottici
le viste al loro interno. Tuttavia, gli elementi di layout (sottoclassi di ViewGroup
)
al momento non supportano i limiti ottici per le immagini nine-patch applicate al proprio sfondo.
Se crei una vista personalizzata assegnando sottoclassi View
, ViewGroup
o una delle sue sottoclassi, la vista erediterà questi comportamenti dei collegamenti ottici.
Nota: tutti i widget supportati dal tema Holo sono stati aggiornati
con limiti ottici, tra cui Button
, Spinner
,
EditText
e altri. Di conseguenza, puoi trarre subito vantaggio impostando l'attributo android:layoutMode
su "opticalBounds"
se la tua app applica un tema Holo (Theme.Holo
, Theme.Holo.Light
e così via).
Per specificare i limiti ottici per le tue immagini nine-patch con lo strumento Disegna 9-patch, tieni premuto Ctrl quando fai clic sui pixel del bordo.
Animazione per i valori Rect
Ora puoi animare due valori Rect
con il nuovo RectEvaluator
. Questa nuova classe è un'implementazione di TypeEvaluator
che puoi passare a ValueAnimator.setEvaluator()
.
Listener di aggancio della finestra e di messa a fuoco
In precedenza, se volevi ascoltare quando la visualizzazione era collegata/scollegata dalla finestra oppure
quando l'elemento attivo è stato modificato, devi eseguire l'override della classe View
per
implementare onAttachedToWindow()
e onDetachedFromWindow()
o onWindowFocusChanged()
, rispettivamente.
Ora, per ricevere eventi di collegamento e scollegamento, puoi implementare ViewTreeObserver.OnWindowAttachListener
e impostarlo in una vista con
addOnWindowAttachListener()
.
Per ricevere eventi di concentrazione, puoi implementare ViewTreeObserver.OnWindowFocusChangeListener
e impostarlo in una visualizzazione con
addOnWindowFocusChangeListener()
.
Supporto dell'overscan della TV
Per assicurarti che la tua app riempia l'intero schermo su ogni TV, ora puoi attivare l'overscan per il layout dell'app. La modalità di overscan viene determinata dal flag FLAG_LAYOUT_IN_OVERSCAN
, che puoi attivare con temi della piattaforma come
Theme_DeviceDefault_NoActionBar_Overscan
o attivando il metodo
Stile windowOverscan
in un tema personalizzato.
Orientamento dello schermo
La <activity>
screenOrientation
del tag
ora supporta valori aggiuntivi per rispettare la preferenza dell'utente per la rotazione automatica:
"userLandscape"
- Si comporta come
"sensorLandscape"
, tranne per il fatto che se l'utente disattiva la rotazione automatica, si blocca nell'orientamento orizzontale normale e non si capovolge. "userPortrait"
- Ha lo stesso comportamento di
"sensorPortrait"
, tranne se l'utente disattiva la rotazione automatica e poi si blocca nel normale orientamento verticale e non si capovolge. "fullUser"
- Si comporta come
"fullSensor"
e consente la rotazione in tutte e quattro le direzioni, tranne se l'utente disattiva la rotazione automatica, in tal caso l'orientamento preferito dell'utente viene bloccato.
Inoltre, ora puoi anche dichiarare "locked"
per bloccare l'orientamento dell'app
all'orientamento corrente dello schermo.
Animazioni di rotazione
Il nuovo campo rotationAnimation
in
WindowManager
ti consente di scegliere tra una delle tre animazioni seguenti
quando il sistema cambia l'orientamento dello schermo. Le tre animazioni sono:
Nota: queste animazioni sono disponibili solo se hai impostato la tua attività in modo che utilizzi la modalità "schermo intero", che puoi attivare con temi come Theme.Holo.NoActionBar.Fullscreen
.
Ad esempio, ecco come attivare l'animazione "dissolvenza incrociata":
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val params: WindowManager.LayoutParams = window.attributes params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE window.attributes = params ... }
Java
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WindowManager.LayoutParams params = getWindow().getAttributes(); params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; getWindow().setAttributes(params); ... }
Input utente
Nuovi tipi di sensori
Il nuovo sensore TYPE_GAME_ROTATION_VECTOR
ti consente di rilevare le rotazioni del dispositivo senza preoccuparti delle interferenze magnetiche. A differenza del sensore TYPE_ROTATION_VECTOR
, TYPE_GAME_ROTATION_VECTOR
non si basa sul nord magnetico.
I nuovi sensori TYPE_GYROSCOPE_UNCALIBRATED
e TYPE_MAGNETIC_FIELD_UNCALIBRATED
forniscono dati non elaborati senza tenere conto delle stime di bias. Vale a dire, gli attuali TYPE_GYROSCOPE
e TYPE_MAGNETIC_FIELD
I sensori forniscono dati dei sensori che tengono conto delle distorsioni stimate della deriva giroscopica e del ferro duro
nel dispositivo. mentre il nuovo valore "non calibrato" di questi sensori forniscono
dati non elaborati dei sensori e offre i valori di bias stimati separatamente. Questi sensori ti consentono
fornire una calibrazione personalizzata per i dati dei sensori migliorando il bias stimato con
dati esterni.
Listener di notifica
Android 4.3 aggiunge una nuova classe di servizio, NotificationListenerService
, che consente alla tua app di ricevere informazioni sulle nuove notifiche man mano che vengono pubblicate dal sistema.
Se al momento la tua app utilizza le API di servizi di accessibilità per accedere alle notifiche di sistema, devi aggiornarla in modo che utilizzi queste API.
Provider di contatti
Query per "contactables"
La nuova query del fornitore di contatti, Contactables.CONTENT_URI
, fornisce un modo efficiente per ottenere un Cursor
contenente tutti gli indirizzi email e i numeri di telefono appartenenti a tutti i contatti corrispondenti alla query specificata.
Esegui query sui delta dei contatti
Al provider di contatti sono state aggiunte nuove API che ti consentono di eseguire query efficaci sulle modifiche recenti ai dati dei contatti. In precedenza, la tua app poteva ricevere una notifica quando qualcosa nei dati dei contatti cambiava, ma non sapevi esattamente cosa era cambiato e dovevi recuperare tutti i contatti ed esaminarli per scoprire la modifica.
Per tenere traccia delle modifiche apportate a inserimenti e aggiornamenti, ora puoi includere il parametro CONTACT_LAST_UPDATED_TIMESTAMP
con la tua selezione per eseguire query solo sui contatti che sono cambiati dall'ultima volta che hai eseguito una query sul provider.
Per monitorare i contatti eliminati, la nuova tabella ContactsContract.DeletedContacts
fornisce un log dei contatti eliminati (ma ogni contatto eliminato viene conservato in questa tabella per un periodo di tempo limitato). Analogamente a CONTACT_LAST_UPDATED_TIMESTAMP
, puoi utilizzare il nuovo parametro di selezione, CONTACT_DELETED_TIMESTAMP
, per controllare quali contatti sono stati eliminati dall'ultima volta che hai eseguito una query sul provider. La tabella contiene anche la costante DAYS_KEPT_MILLISECONDS
contenente il numero di giorni (in millisecondi) per i quali verrà conservato il log.
Inoltre, il provider di contatti ora trasmette l'azione CONTACTS_DATABASE_CREATED
quando l'utente
cancella l'archivio dei contatti dal menu delle impostazioni di sistema, ricreando in modo efficace
Database del provider di contatti. Ha lo scopo di segnalare alle app che devono eliminare tutte le informazioni sui contatti memorizzate e ricaricarle con una nuova query.
Per un esempio di codice che utilizza queste API per verificare le modifiche ai contatti, cerca in ApiDemos campione disponibile nel download degli esempi di SDK.
Localizzazione
Supporto migliorato per il testo bidirezionale
Le versioni precedenti di Android supportano le lingue e il layout da destra a sinistra (RTL).
ma a volte non gestiscono correttamente il testo nelle direzioni miste. Pertanto, Android 4.3 aggiunge le API BidiFormatter
che ti aiutano a formattare correttamente il testo con contenuti in direzione opposta senza alterarne alcuna parte.
Ad esempio, quando vuoi creare una frase con una variabile stringa come "Forse cercavi
15 Bay Street, Laurel, CA?", di solito passi una risorsa stringa localizzata e la variabile a
String.format()
:
Kotlin
val suggestion = String.format(resources.getString(R.string.did_you_mean), address)
Java
Resources res = getResources(); String suggestion = String.format(res.getString(R.string.did_you_mean), address);
Tuttavia, se le impostazioni internazionali sono in ebraico, la stringa formattata sarà la seguente:
엄 엄 비 엄 엄 엄 엄
Non è corretto perché il numero "15" deve trovarsi a sinistra di "Bay Street". La soluzione è utilizzare BidiFormatter
e il relativo metodo unicodeWrap()
. Ad esempio, il codice riportato sopra diventa:
Kotlin
val bidiFormatter = BidiFormatter.getInstance() val suggestion = String.format( resources.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address) )
Java
Resources res = getResources(); BidiFormatter bidiFormatter = BidiFormatter.getInstance(); String suggestion = String.format(res.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address));
Per impostazione predefinita, unicodeWrap()
utilizza
una forte euristica della stima della direzionalità, che può sbagliare se la prima
per la direzione del testo non rappresenta la direzione appropriata per i contenuti nel complesso.
Se necessario, puoi specificare un'euristica diversa passando una delle costanti TextDirectionHeuristic
da TextDirectionHeuristics
a unicodeWrap()
.
Nota: queste nuove API sono disponibili anche per le versioni precedenti di Android tramite la libreria di supporto di Android, con la classe BidiFormatter
e le API correlate.
Servizi di accessibilità
Gestire gli eventi chiave
Ora un AccessibilityService
può ricevere una richiamata per
eventi di input chiave con il metodo di callback onKeyEvent()
. Ciò consente al tuo servizio di accessibilità di gestire l'input per
i dispositivi di input basati su tasti come le tastiere e traducono questi eventi in azioni speciali che
in precedenza era possibile solo con l'input tocco o il d-pad del dispositivo.
Seleziona il testo e copia/incolla
AccessibilityNodeInfo
ora fornisce API che consentono a un AccessibilityService
di selezionare, tagliare, copiare e incollare il testo in un nodo.
Per specificare la selezione del testo da tagliare o copiare, il servizio di accessibilità può utilizzare il nuovo
azione, ACTION_SET_SELECTION
, superato
e la posizione di inizio e fine della selezione con ACTION_ARGUMENT_SELECTION_START_INT
e ACTION_ARGUMENT_SELECTION_END_INT
.
In alternativa, puoi selezionare il testo modificando la posizione del cursore utilizzando l'azione esistente ACTION_NEXT_AT_MOVEMENT_GRANULARITY
(in precedenza solo per spostare la posizione del cursore) e aggiungendo l'argomento ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
.
Puoi quindi tagliare o copiare con ACTION_CUT
,
ACTION_COPY
, poi incolla con
ACTION_PASTE
.
Nota: queste nuove API sono disponibili anche per le versioni precedenti di Android tramite la libreria di supporto di Android, con la classe AccessibilityNodeInfoCompat
.
Dichiara le funzioni di accessibilità
A partire da Android 4.3, un servizio di accessibilità deve dichiarare le funzionalità di accessibilità
nel file di metadati per usare alcune funzioni di accessibilità. Se la funzionalità non viene richiesta nel file di metadati, non verrà eseguita alcuna operazione. Per dichiarare le funzionalità di accessibilità del servizio, devi utilizzare gli attributi XML corrispondenti alle varie costanti "capability" nella classe AccessibilityServiceInfo
.
Ad esempio, se un servizio non richiede la funzionalità flagRequestFilterKeyEvents
,
non riceverà gli eventi chiave.
Test e debug
Test dell'interfaccia utente automatizzati
La nuova classe UiAutomation
fornisce API che ti consentono di simulare gli utenti
azioni per l'automazione dei test. L'utilizzo delle API AccessibilityService
della piattaforma consente di ispezionare i contenuti dello schermo e di iniettare eventi di tastiera e tocco arbitrari.
Per ottenere un'istanza di UiAutomation
, chiama Instrumentation.getUiAutomation()
. Affinché
questa operazione funzioni, devi fornire l'opzione -w
con il comando instrument
quando esegui InstrumentationTestCase
da adb shell
.
Con l'istanza UiAutomation
, puoi eseguire eventi arbitrari per testare la tua app chiamando executeAndWaitForEvent()
, passando un Runnable
da eseguire, un periodo di timeout per l'operazione e un'implementazione dell'interfaccia UiAutomation.AccessibilityEventFilter
. Nell'implementazione di UiAutomation.AccessibilityEventFilter
riceverai una chiamata che ti consente di filtrare gli eventi che ti interessano e determinare il successo o il fallimento di un determinato test case.
Per osservare tutti gli eventi durante un test, crea un'implementazione di UiAutomation.OnAccessibilityEventListener
e passala a setOnAccessibilityEventListener()
.
L'interfaccia di listener riceve quindi una chiamata a onAccessibilityEvent()
ogni volta che si verifica un evento, ricevendo un oggetto AccessibilityEvent
che descrive l'evento.
Esistono una serie di altre operazioni esposte dalle API UiAutomation
a un livello molto basso per incoraggiare lo sviluppo di strumenti di test dell'interfaccia utente come uiautomator. Ad esempio,
UiAutomation
può anche:
- Iniettare eventi di input
- Modificare l'orientamento dello schermo
- Acquisisci screenshot
E, cosa più importante per gli strumenti di test dell'interfaccia utente, le API UiAutomation
funzionano
al di là dei confini dell'applicazione, a differenza di quelle in Instrumentation
.
Eventi Systrace per le app
Android 4.3 aggiunge la classe Trace
con due metodi statici,
beginSection()
e endSection()
,
che consentono di definire blocchi di codice da includere nel report systrace. Creando sezioni di codice tracciabile nella tua app, i log di systrace forniscono un'analisi molto più dettagliata del punto in cui si verificano i rallentamenti all'interno dell'app.
Per informazioni sull'utilizzo dello strumento Systrace, leggi l'articolo Analisi di visualizzazione e prestazioni con Systrace.
Sicurezza
Archivio chiavi Android per le chiavi private delle app
Android ora offre un provider di sicurezza Java personalizzato nel KeyStore
Android Key Store, che consente di generare e salvare chiavi private
possono essere visti e utilizzati solo dalla tua app. Per caricare l'archivio chiavi Android,
"AndroidKeyStore"
a KeyStore.getInstance()
.
Per gestire le credenziali private della tua app nell'Android Key Store, genera una nuova chiave con
KeyPairGenerator
con KeyPairGeneratorSpec
. Per prima cosa,
recupera un'istanza di KeyPairGenerator
chiamando getInstance()
. Quindi chiama
initialize()
, passandogli un'istanza
KeyPairGeneratorSpec
, che puoi usare usando
KeyPairGeneratorSpec.Builder
.
Infine, ricevi KeyPair
chiamando il numero generateKeyPair()
.
Archiviazione delle credenziali hardware
Ora Android supporta anche lo spazio di archiviazione basato sull'hardware per le tue KeyChain
credenziali, offrendo una maggiore sicurezza rendendo le chiavi non disponibili per l'estrazione. Vale a dire che, una volta
le chiavi si trovano in un archivio chiavi supportato da hardware (Secure Element, TPM o TrustZone) e possono essere utilizzate
operazioni crittografiche, ma non è possibile esportare il materiale della chiave privata. Anche il kernel del sistema operativo
non può accedere a questo materiale della chiave. Sebbene non tutti i dispositivi Android supportino lo spazio di archiviazione sull'hardware, puoi verificare in fase di esecuzione se è disponibile lo spazio di archiviazione basato sull'hardware chiamando KeyChain.IsBoundKeyAlgorithm()
.
Dichiarazioni manifest
Funzionalità obbligatorie dichiarabili
Ora nell'elemento <uses-feature>
sono supportati i seguenti valori, per consentirti di assicurarti che la tua app venga installata solo sui dispositivi che forniscono le funzionalità di cui ha bisogno.
FEATURE_APP_WIDGETS
- Dichiara che l'app offre un widget dell'app e deve essere installata solo su dispositivi con
includere una schermata Home o un'area simile in cui gli utenti possono incorporare widget delle app.
Esempio:
<uses-feature android:name="android.software.app_widgets" android:required="true" />
FEATURE_HOME_SCREEN
- Dichiara che l'app funziona come una sostituzione della schermata Home e deve essere installata soltanto su
dispositivi che supportano app di terze parti nella schermata Home.
Esempio:
<uses-feature android:name="android.software.home_screen" android:required="true" />
FEATURE_INPUT_METHODS
- Dichiara che l'app offre un metodo di immissione personalizzato (una tastiera creata con
InputMethodService
) e deve essere installata soltanto su dispositivi con supportano metodi di immissione di terze parti. Esempio:<uses-feature android:name="android.software.input_methods" android:required="true" />
FEATURE_BLUETOOTH_LE
- Dichiara che la tua app utilizza le API Bluetooth Low Energy e deve essere installata solo su dispositivi in grado di comunicare con altri dispositivi tramite Bluetooth Low Energy.
Esempio:
<uses-feature android:name="android.software.bluetooth_le" android:required="true" />
Autorizzazioni utente
Ora in <uses-permission>
sono supportati i seguenti valori per dichiarare le autorizzazioni richieste dalla tua app per accedere a determinate API.
BIND_NOTIFICATION_LISTENER_SERVICE
- Necessari per utilizzare le nuove API
NotificationListenerService
. SEND_RESPOND_VIA_MESSAGE
- Necessari per ricevere i
ACTION_RESPOND_VIA_MESSAGE
l'intento.
Per una visualizzazione dettagliata di tutte le modifiche API in Android 4.3, vedi Report Differenze API.