API per Android 4.4

Livello API: 19

Android 4.4 (KITKAT) è una nuova release per la piattaforma Android che offre nuove funzionalità a utenti e sviluppatori di app. Questo documento fornisce un'introduzione alle nuove API più importanti.

In qualità di sviluppatore di app, devi scaricare la piattaforma dell'SDK e dell'immagine di sistema Android 4.4 da SDK Manager il prima possibile. Se non hai un dispositivo con Android 4.4 su cui testare la tua app, usa l'immagine di sistema Android 4.4 per testare l'app con l'emulatore Android. Successivamente, crea le tue app sulla piattaforma Android 4.4 per iniziare a utilizzare le API più recenti.

Aggiorna il livello API target

Per ottimizzare meglio l'app per i dispositivi con Android 4.4, devi impostare targetSdkVersion su "19", installarla su un'immagine di sistema Android 4.4, testarla e pubblicare un aggiornamento con questa modifica.

Puoi utilizzare le API in Android 4.4 e supportare le versioni precedenti aggiungendo al codice condizioni che verificano il livello API di sistema prima di eseguire le API non supportate da minSdkVersion. Per scoprire di più su come mantenere la compatibilità con le versioni precedenti, consulta la pagina relativa al supporto di diverse versioni della piattaforma.

Per ulteriori informazioni su come funzionano i livelli API, consulta Che cos'è il livello API?

Importanti cambiamenti di comportamento

Se hai già pubblicato un'app per Android, tieni presente che la tua app potrebbe essere influenzata dalle modifiche in Android 4.4.

Se la tua app legge dall'unità di archiviazione esterna...

La tua app non può leggere i file condivisi nell'unità di archiviazione esterna quando è in esecuzione su Android 4.4, a meno che l'app non disponga dell'autorizzazione READ_EXTERNAL_STORAGE. Ciò significa che i file all'interno della directory restituita da getExternalStoragePublicDirectory() non sono più accessibili senza l'autorizzazione. Se invece devi accedere solo alle directory specifiche dell'app, fornite da getExternalFilesDir(), non hai bisogno dell'autorizzazione READ_EXTERNAL_STORAGE.

Se la tua app utilizza WebView...

La tua app potrebbe comportarsi in modo diverso quando viene eseguita su Android 4.4, soprattutto se aggiorni l'app targetSdkVersion a "19" o versioni successive.

È stato eseguito l'upgrade del codice sottostante alla classe WebView e alle API correlate in modo che si basi su uno snapshot moderno del codice sorgente di Chromium. Questa funzionalità offre una serie di miglioramenti in termini di prestazioni, supporto di nuove funzionalità HTML5 e supporto del debug remoto dei contenuti WebView. L'ambito di questo upgrade indica che se la tua app utilizza WebView, il comportamento potrebbe risentirne in alcuni casi. Anche se le modifiche del comportamento noto sono documentate e interessano principalmente la tua app solo quando aggiorni il valore targetSdkVersion dell'app a "19" o versioni successive, il nuovo WebView opera in "modalità non standard" per fornire alcune funzionalità legacy nelle app destinate al livello API 18 e a livelli precedenti. È possibile che la tua app dipenda da comportamenti sconosciuti della versione precedente di WebView.

Pertanto, se la tua app esistente utilizza WebView, è importante eseguire il test su Android 4.4 il prima possibile e consultare la sezione Migrazione a WebView in Android 4.4 per informazioni su come potrebbe essere interessata la tua app quando aggiorni la versione di targetSdkVersion a "19" o versioni successive.

Se la tua app usa AlarmManager...

Se imposti targetSdkVersion su "19 " o un valore superiore per l'app, le sveglie create utilizzando set() o setRepeating() saranno inesatte.

Per migliorare l'efficienza energetica, Android ora raggruppa le sveglie di tutte le app che si verificano a orari ragionevolmente simili, così il sistema riattiva il dispositivo una volta anziché più volte per gestire ogni sveglia.

Se la sveglia non è associata a un'ora esatta, ma è comunque importante che venga attivata durante un intervallo di tempo specifico (ad esempio, tra le 14:00 e le 16:00), puoi utilizzare il nuovo metodo setWindow(), che accetta l'ora "prima" per la sveglia e una "finestra" di tempo successiva alla prima ora entro la quale il sistema deve attivare la sveglia.

Se la sveglia deve essere fissata a un'ora esatta (ad esempio per il promemoria di un evento nel calendario), puoi utilizzare il nuovo metodo setExact().

Questo comportamento di raggruppamento inesatto si applica solo alle app aggiornate. Se hai impostato targetSdkVersion su "18" o su un valore inferiore, le sveglie continueranno a comportarsi come nelle versioni precedenti su Android 4.4.

Se la tua app sincronizza i dati utilizzando ContentResolver...

Se imposti targetSdkVersion dell'app su "19" o su un valore superiore, la creazione di una sincronizzazione con addPeriodicSync() eseguirà le operazioni di sincronizzazione entro un intervallo flessibile predefinito di circa il 4% del periodo specificato. Ad esempio, se la frequenza del sondaggio è di 24 ore, l'operazione di sincronizzazione potrebbe avvenire ogni giorno all'incirca all'incirca un'ora, invece che ogni giorno alla stessa ora.

Per specificare un intervallo flessibile per le operazioni di sincronizzazione, devi iniziare a utilizzare il nuovo metodo requestSync(). Per maggiori dettagli, vedi la sezione Adattatori di sincronizzazione di seguito.

Questo comportamento dell'intervallo flessibile si applica solo alle app aggiornate. Se hai impostato targetSdkVersion su "18" o su un valore inferiore, le richieste di sincronizzazione esistenti continueranno a comportarsi come nelle versioni precedenti su Android 4.4.

Framework per la stampa

Android ora include un framework completo che consente agli utenti di stampare qualsiasi documento utilizzando una stampante connessa tramite Wi-Fi, Bluetooth o altri servizi. Il sistema gestisce la transazione tra un'app che vuole stampare un documento e i servizi che inviano processi di stampa a una stampante. Il framework android.print fornisce tutte le API necessarie per specificare un documento stampato e inviarlo al sistema per la stampa. Le API necessarie per un determinato processo di stampa dipendono dai contenuti.

Stampa di contenuti generici

Se vuoi stampare contenuti della tua UI come documento, devi prima creare una sottoclasse PrintDocumentAdapter. All'interno di questa classe devi implementare alcuni metodi di callback, tra cui onLayout() per definire il layout in base alle proprietà di stampa fornite e onWrite() per serializzare i contenuti stampabili in un ParcelFileDescriptor.

Per scrivere i tuoi contenuti sul ParcelFileDescriptor, devi trasmetterli in formato PDF. Le nuove API PdfDocument offrono un modo pratico per farlo fornendo un elemento Canvas di getCanvas(), sul quale puoi disegnare i tuoi contenuti stampabili. Quindi scrivi il PdfDocument in ParcelFileDescriptor utilizzando il metodo writeTo().

Dopo aver definito l'implementazione per PrintDocumentAdapter, puoi eseguire processi di stampa su richiesta dell'utente utilizzando il metodo PrintManager, print(), che prende PrintDocumentAdapter come uno dei suoi argomenti.

Stampa di immagini

Se vuoi stampare solo una foto o un'altra immagine bitmap, le API helper nella libreria di supporto si occupano di tutto. Crea semplicemente una nuova istanza di PrintHelper, imposta la modalità di scalabilità con setScaleMode() e passa Bitmap a printBitmap(). È tutto. La libreria gestisce tutte le interazioni rimanenti con il sistema per inviare il bitmap alla stampante.

Servizi di stampa per edifici

In qualità di OEM di stampanti, puoi utilizzare il framework android.printservice per offrire l'interoperabilità con le tue stampanti da dispositivi Android. Puoi creare e distribuire servizi di stampa sotto forma di APK, che gli utenti possono installare sui propri dispositivi . Un'app del servizio di stampa funziona principalmente come servizio headless sottoclassendo la classe PrintService, che riceve processi di stampa dal sistema e li comunica alle proprie stampanti utilizzando i protocolli appropriati.

Per ulteriori informazioni su come stampare i contenuti dell'app, leggi l'articolo Stampa di contenuti.

Provider SMS

Il fornitore di contenuti Telephony (il "provider SMS") consente alle app di leggere e scrivere SMS ed MMS sul dispositivo. Include tabelle per SMS ed MMS ricevuti, in bozza, inviati, in attesa e altro ancora.

A partire da Android 4.4, le impostazioni di sistema consentono agli utenti di selezionare un'app per SMS predefinita. Una volta selezionata, solo l'app per SMS predefinita è in grado di scrivere al provider SMS e solo l'app predefinita per SMS riceve la trasmissione SMS_DELIVER_ACTION quando l'utente riceve un SMS o la trasmissione WAP_PUSH_DELIVER_ACTION quando l'utente riceve un MMS. L'app per SMS predefinita è responsabile della scrittura dei dettagli al provider SMS quando riceve o invia un nuovo messaggio.

Altre app che non sono selezionate come app predefinita per gli SMS possono soltanto leggere il provider SMS, ma potrebbero anche ricevere una notifica all'arrivo di un nuovo SMS ascoltando la trasmissione SMS_RECEIVED_ACTION, che è una trasmissione non interrotta che può essere inviata a più app. Questo broadcast è destinato alle app che, pur non essendo selezionate come app predefinita per gli SMS, devono leggere messaggi speciali in arrivo, ad esempio eseguire la verifica del numero di telefono.

Per ulteriori informazioni, leggi il post del blog, Getting Your SMS Apps Ready for Marshmallow.

Wireless e connettività

Emulazione della carta host

Ora le app per Android possono emulare le carte NFC ISO14443-4 (ISO-DEP) che utilizzano APDU per lo scambio di dati (come specificato in ISO7816-4). Ciò consente a un dispositivo con supporto NFC con Android 4.4 di emulare più carte NFC contemporaneamente e consente a un terminale di pagamento NFC o a un altro lettore NFC di avviare una transazione con la carta NFC appropriata in base all'ID applicazione (AID).

Se vuoi emulare una carta NFC che utilizza questi protocolli nella tua app, crea un componente del servizio basato sulla classe HostApduService. Se invece la tua app utilizza un Secure Element per l'emulazione della carta, devi creare un servizio basato sulla classe OffHostApduService, che non sarà direttamente coinvolta nelle transazioni, ma è necessaria per registrare gli AID che dovrebbero essere gestiti dal Secure Element.

Per ulteriori informazioni, leggi la guida all'emulazione delle carte NFC.

Modalità lettore NFC

Una nuova modalità lettore NFC consente a un'attività di limitare tutte le attività NFC alla lettura solo dei tipi di tag a cui l'attività è interessata mentre è in primo piano. Puoi attivare la modalità lettore per la tua attività con enableReaderMode(), fornendo un'implementazione di NfcAdapter.ReaderCallback che riceve un callback quando vengono rilevati nuovi tag.

Questa nuova funzionalità, in combinazione con l'emulazione della carta host, consente ad Android di operare su entrambe le estremità di un'interfaccia di pagamento mobile: un dispositivo funge da terminale di pagamento (un dispositivo che esegue un'attività in modalità lettore) e un altro dispositivo da client di pagamento (un dispositivo che emula una carta NFC).

Trasmettitori a infrarossi

Quando utilizzi un dispositivo che include un trasmettitore a infrarossi (IR), ora puoi trasmettere i segnali IR utilizzando le API di ConsumerIrManager. Per ottenere un'istanza di ConsumerIrManager, chiama getSystemService() con CONSUMER_IR_SERVICE come argomento. Puoi quindi eseguire query sulle frequenze IR supportate del dispositivo con getCarrierFrequencies() e trasmettere i segnali passando la frequenza e lo schema di segnale desiderati con transmit().

Prima di tutto dovresti controllare sempre se un dispositivo include un trasmettitore IR chiamando hasIrEmitter(); tuttavia, se la tua app è compatibile soltanto con i dispositivi che ne hanno uno, devi includere un elemento <uses-feature> nel file manifest per "android.hardware.consumerir" (FEATURE_CONSUMER_IR).

Multimediale

Riproduzione adattiva

Il supporto della riproduzione video adattiva è ora disponibile con le API di MediaCodec, il che consente una modifica perfetta della risoluzione durante la riproduzione su un Surface: puoi alimentare i frame di input del decoder con una nuova risoluzione e la risoluzione dei buffer di output cambia senza un divario significativo.

Puoi attivare la riproduzione adattiva aggiungendo due tasti in MediaFormat che specificano la risoluzione massima che la tua app richiede dal codec: KEY_MAX_WIDTH e KEY_MAX_HEIGHT. Dopo aver aggiunto questi elementi a MediaFormat, passa MediaFormat alla tua istanza MediaCodec con configure().

Il codec eseguirà la transizione tra risoluzioni uguali o minori di questi valori in modo fluido. Il codec potrebbe anche supportare risoluzioni superiori ai valori massimi specificati (purché rientri nei limiti dei profili supportati), ma le transizioni a risoluzioni più grandi potrebbero non essere fluide.

Per modificare la risoluzione durante la decodifica del video H.264, continua a mettere in coda i frame utilizzando MediaCodec.queueInputBuffer(), ma assicurati di fornire i nuovi valori SPS (Sequenza Parameter Set) e Picture Parameter Set (PPS) insieme al frame IDR (Instantaneous Decoder refresh) in un unico buffer.

Tuttavia, prima di tentare di configurare il codec per la riproduzione adattiva, devi verificare che il dispositivo supporti la riproduzione adattiva chiamando isFeatureSupported(String) con FEATURE_AdaptivePlayback.

Nota:il supporto per la riproduzione adattiva è specifico del fornitore. Alcuni codec potrebbero richiedere più memoria per suggerimenti di risoluzione più grandi. Pertanto, devi impostare i valori massimi di risoluzione in base al materiale di origine che stai decodificando.

Timestamp dell'audio on demand

Per facilitare la sincronizzazione audio-video, la nuova classe AudioTimestamp fornisce dettagli della sequenza temporale su un "frame" specifico in uno stream audio gestito da AudioTrack. Per ottenere il timestamp più recente disponibile, crea un'istanza di un oggetto AudioTimestamp e trasmettilo a getTimestamp(). Se la richiesta del timestamp ha esito positivo, l'istanza AudioTrack viene compilata con una posizione in unità di frame, insieme all'ora stimata in cui il frame è stato presentato o si è impegnato a presentarlo.

Puoi utilizzare il valore nanoTime in AudioTimestamp (che è monotonico) per trovare il frame video associato più vicino rispetto a framePosition, in modo da poter rilasciare, duplicare o interpolare i frame video in modo che corrispondano all'audio. In alternativa, puoi determinare il tempo delta tra il valore di nanoTime e il tempo previsto per un frame video futuro (tenendo conto della frequenza di campionamento) per prevedere quale frame audio è previsto nello stesso momento di un frame video.

Lettore di immagini Surface

La nuova API ImageReader fornisce accesso diretto ai buffer delle immagini quando vengono visualizzati in un elemento Surface. Puoi acquisire un ImageReader con il metodo statico newInstance(). Dopodiché chiama getSurface() per creare un nuovo Surface e consegna i dati delle immagini con un producer, ad esempio MediaPlayer o MediaCodec. Per ricevere una notifica quando sono disponibili nuove immagini dalla piattaforma, implementa l'interfaccia ImageReader.OnImageAvailableListener e registrala con setOnImageAvailableListener().

Ora, man mano che tracci contenuti sul tuo Surface, il tuo ImageReader.OnImageAvailableListener riceve una chiamata a onImageAvailable() man mano che diventa disponibile ogni nuovo frame immagine, fornendoti il valore ImageReader corrispondente. Puoi usare l'ImageReader per acquisire i dati dell'immagine del frame come un oggetto Image chiamando acquireLatestImage() o acquireNextImage().

L'oggetto Image fornisce accesso diretto a timestamp, formato, dimensioni e dati relativi ai pixel dell'immagine in un ByteBuffer. Tuttavia, affinché la classe Image possa interpretare le tue immagini, queste devono essere formattate in base a uno dei tipi definiti dalle costanti in ImageFormat o PixelFormat.

Misurazione dei picchi e dell'RMS

Ora puoi eseguire una query sul picco e sull'RMS dello stream audio corrente da Visualizer creando una nuova istanza di Visualizer.MeasurementPeakRms e passandola a getMeasurementPeakRms(). Quando chiami questo metodo, i valori di picco e RMS di un determinato Visualizer.MeasurementPeakRms vengono impostati sugli ultimi valori misurati.

Potenziatore del volume

LoudnessEnhancer è una nuova sottoclasse di AudioEffect che ti consente di aumentare il volume udibile di MediaPlayer o AudioTrack. Questa funzionalità può essere particolarmente utile in combinazione con il nuovo metodo getMeasurementPeakRms() menzionato sopra, per aumentare il volume delle tracce audio parlate mentre sono in corso la riproduzione di altri contenuti multimediali.

Telecomandi

Android 4.0 (livello API 14) ha introdotto le API RemoteControlClient che consentono alle app multimediali di utilizzare gli eventi del controller multimediale da client remoti, ad esempio i controlli multimediali nella schermata di blocco. Ora le nuove API di RemoteController ti consentono di creare il tuo telecomando, consentendo la creazione di nuove app e periferiche innovative in grado di controllare la riproduzione di qualsiasi app multimediale che si integra con RemoteControlClient.

Per creare un controller remoto, puoi implementare l'interfaccia utente come preferisci, ma per inviare gli eventi del pulsante multimediale all'app multimediale dell'utente devi creare un servizio che estenda la classe NotificationListenerService e implementi l'interfaccia RemoteController.OnClientUpdateListener. È importante utilizzare NotificationListenerService come base perché fornisce le adeguate limitazioni della privacy, che richiedono agli utenti di attivare la tua app come listener di notifiche nelle impostazioni di sicurezza del sistema.

La classe NotificationListenerService include un paio di metodi astratti che devi implementare, ma se ti interessano solo gli eventi del controller multimediale per la gestione della riproduzione di contenuti multimediali, puoi lasciare l'implementazione vuota e concentrarti sui metodi RemoteController.OnClientUpdateListener.

Valutazioni dei telecomandi

Android 4.4 si basa sulle funzionalità esistenti per i client di controllo remoto (app che ricevono eventi di controllo dei contenuti multimediali con l'RemoteControlClient) aggiungendo la possibilità per gli utenti di valutare la traccia corrente dal controller remoto.

La nuova classe Rating contiene informazioni sulla valutazione di un utente. Una valutazione viene definita dal relativo stile di valutazione (RATING_HEART, RATING_THUMB_UP_DOWN, RATING_3_STARS, RATING_4_STARS, RATING_5_STARS o RATING_PERCENTAGE) e dal valore di valutazione appropriato per quello stile.

Per consentire agli utenti di valutare le rotte da un telecomando:

Per ricevere un callback quando l'utente modifica la valutazione dal telecomando, implementa la nuova interfaccia di RemoteControlClient.OnMetadataUpdateListener e trasmetti un'istanza a setMetadataUpdateListener(). Quando l'utente modifica la valutazione, il tuo RemoteControlClient.OnMetadataUpdateListener riceve una chiamata a onMetadataUpdate(), passando RATING_KEY_BY_USER come chiave e un oggetto Rating come valore.

Sottotitoli codificati

VideoView ora supporta le tracce di sottotitoli WebVTT durante la riproduzione di video HLS (HTTP Live Stream) e la traccia dei sottotitoli viene visualizzata in base alle preferenze per i sottotitoli codificati definite dall'utente nelle impostazioni di sistema.

Puoi anche fornire VideoView con le tue tracce di sottotitoli WebVTT utilizzando il metodo addSubtitleSource(). Questo metodo accetta un InputStream che trasporta i dati dei sottotitoli e un oggetto MediaFormat che specifica il formato dei dati dei sottotitoli, che puoi specificare utilizzando createSubtitleFormat(). Inoltre, questi sottotitoli appaiono sopra il video in base alle preferenze dell'utente.

Se non utilizzi VideoView per visualizzare i contenuti video, l'overlay dei sottotitoli deve corrispondere il più fedelmente possibile alla preferenza dell'utente per i sottotitoli. Una nuova API CaptioningManager ti consente di eseguire query sulle preferenze di sottotitolaggio dell'utente, inclusi gli stili definiti da CaptioningManager.CaptionStyle, come il tipo di carattere e il colore. Nel caso in cui l'utente modifichi alcune preferenze una volta avviato il video, devi ascoltare le modifiche alle preferenze registrando un'istanza di CaptioningManager.CaptioningChangeListener per ricevere una richiamata quando una qualsiasi delle preferenze cambia, quindi aggiornare i sottotitoli in base alle necessità.

Animazione e grafica

Scene e transizioni

Il nuovo framework android.transition fornisce API che facilitano le animazioni tra diversi stati dell'interfaccia utente. Una funzionalità chiave è la possibilità di definire stati distinti dell'interfaccia utente, noti come "scene", creando un layout separato per ciascuno. Se vuoi animare da una scena a un'altra, esegui una "transizione", che calcola l'animazione necessaria per cambiare il layout dalla scena corrente alla scena successiva.

Per passare da una scena all'altra, generalmente è necessario eseguire le seguenti operazioni:

  1. Specifica il ViewGroup contenente i componenti dell'interfaccia utente che vuoi modificare.
  2. Specifica il layout che rappresenta il risultato finale della modifica (la scena successiva).
  3. Specifica il tipo di transizione che deve animare la modifica del layout.
  4. Esegui la transizione.

Puoi utilizzare un oggetto Scene per completare i passaggi 1 e 2. Un elemento Scene contiene i metadati che descrivono le proprietà di un layout necessarie per eseguire una transizione, tra cui la vista principale della scena e il suo layout. Puoi creare un elemento Scene utilizzando un costruttore di classe o il metodo statico getSceneForLayout().

Devi quindi utilizzare l'TransitionManager per completare i passaggi 3 e 4. Un modo è passare Scene al metodo statico go(). Questa opzione trova la vista principale della scena nel layout corrente ed esegue una transizione nelle viste secondarie per ottenere il layout definito da Scene.

In alternativa, non è necessario creare affatto un oggetto Scene, ma puoi chiamare beginDelayedTransition(), specificando un ViewGroup che contiene le viste da modificare. quindi aggiungi, rimuovi o riconfigura le viste di destinazione. Una volta che il sistema ha definito le modifiche necessarie, inizia una transizione per animare tutte le viste interessate.

Per un controllo aggiuntivo, puoi definire gli insiemi di transizioni che devono verificarsi tra scene predefinite utilizzando un file XML nella directory res/transition/ del progetto. All'interno di un elemento <transitionManager>, specifica uno o più tag <transition> in cui ciascuno specifica una scena (un riferimento a un file di layout) e la transizione da applicare quando entri e/o esci dalla scena. Quindi, gonfia questo insieme di transizioni utilizzando inflateTransitionManager(). Utilizza il valore TransitionManager restituito per eseguire ogni transizione con transitionTo(), trasmettendo un valore Scene rappresentato da uno dei tag <transition>. Puoi anche definire gli insiemi di transizioni in modo programmatico con le API TransitionManager.

Quando specifichi una transizione, puoi utilizzare diversi tipi predefiniti definiti dalle sottoclassi Transition, come Fade e ChangeBounds. Se non specifichi un tipo di transizione, per impostazione predefinita il sistema utilizza AutoTransition, che applica la dissolvenza, lo spostamento e il ridimensionamento delle visualizzazioni secondo necessità. Inoltre, puoi creare transizioni personalizzate estendendo una di queste classi per eseguire le animazioni come preferisci. Una transizione personalizzata può monitorare tutte le modifiche apportate alle proprietà e creare qualsiasi animazione in base a queste modifiche. Ad esempio, puoi fornire una sottoclasse Transition che ascolti le modifiche apportate alla proprietà "rotazione" di una vista e poi anima le modifiche.

Per saperne di più, consulta la documentazione di TransitionManager.

Animatore in pausa

Le API Animator ora consentono di mettere in pausa e riprendere un'animazione in corso con i metodi pause() e resume().

Per monitorare lo stato di un'animazione, puoi implementare l'interfaccia Animator.AnimatorPauseListener, che fornisce i callback quando un'animazione viene messa in pausa e ripresa: pause() e resume(). Quindi aggiungi il listener a un oggetto Animator con addPauseListener().

In alternativa, puoi sottoclassare la classe astratta AnimatorListenerAdapter, che ora include implementazioni vuote per i callback di pausa e ripresa definiti da Animator.AnimatorPauseListener.

Bitmap riutilizzabili

Ora puoi riutilizzare qualsiasi bitmap mutabile in BitmapFactory per decodificare qualsiasi altra bitmap, anche se la nuova bitmap ha dimensioni diverse, purché il conteggio dei byte risultanti della bitmap decodificata (disponibile da getByteCount()) sia inferiore o uguale al conteggio dei byte allocati della bitmap riutilizzata (disponibile a partire dal giorno getAllocationByteCount()). Per ulteriori informazioni, vedi inBitmap.

Le nuove API per Bitmap consentono una riconfigurazione simile per il riutilizzo al di fuori di BitmapFactory (per la generazione manuale di bitmap o per una logica di decodifica personalizzata). Ora puoi impostare le dimensioni di una bitmap con i metodi setHeight() e setWidth() e specificare un nuovo Bitmap.Config con setConfig() senza influire sull'allocazione della bitmap sottostante. Il metodo reconfigure() offre inoltre un modo pratico per combinare queste modifiche con un'unica chiamata.

Tuttavia, non devi riconfigurare una bitmap attualmente utilizzata dal sistema di visualizzazione, poiché il buffer di pixel sottostante non verrà rimappato in modo prevedibile.

Contenuti generati dagli utenti

Framework di accesso allo spazio di archiviazione

Nelle versioni precedenti di Android, se vuoi che la tua app recuperi un tipo specifico di file da un'altra app, deve richiamare un intent con l'azione ACTION_GET_CONTENT. Questa azione è comunque il modo appropriato per richiedere un file da importare nella tua app. Tuttavia, Android 4.4 introduce l'azione ACTION_OPEN_DOCUMENT, che consente all'utente di selezionare un file di un tipo specifico e concedere alla tua app l'accesso in lettura a lungo termine al file (possibilmente con accesso in scrittura) senza importare il file nella tua app.

Se stai sviluppando un'app che fornisce servizi di archiviazione per i file (ad esempio, un servizio di salvataggio sul cloud), puoi partecipare a questa UI unificata per la selezione dei file implementando un fornitore di contenuti come sottoclasse della nuova classe DocumentsProvider. La tua sottoclasse DocumentsProvider deve includere un filtro per intent che accetti l'azione PROVIDER_INTERFACE ("android.content.action.DOCUMENTS_PROVIDER"). Devi implementare i quattro metodi astratti in DocumentsProvider:

queryRoots()
Deve restituire un Cursor che descriva tutte le directory principali dello spazio di archiviazione dei documenti, utilizzando le colonne definite in DocumentsContract.Root.
queryChildDocuments()
Deve restituire un Cursor che descriva tutti i file nella directory specificata, utilizzando le colonne definite in DocumentsContract.Document.
queryDocument()
Deve restituire un Cursor che descriva il file specificato, utilizzando le colonne definite in DocumentsContract.Document.
openDocument()
Deve restituire un ParcelFileDescriptor che rappresenta il file specificato. Il sistema chiama questo metodo dopo che l'utente seleziona un file e l'app client richiede l'accesso chiamando openFileDescriptor().

Per ulteriori informazioni, consulta la guida di Storage Access Framework.

Accesso all'unità di archiviazione esterna

Ora puoi leggere e scrivere file specifici dell'app su supporti di archiviazione esterni secondari, ad esempio quando un dispositivo fornisce sia spazio di archiviazione emulato sia una scheda SD. Il nuovo metodo getExternalFilesDirs() funziona come il metodo getExternalFilesDir() esistente, ad eccezione del fatto che restituisce un array di oggetti File. Prima di leggere o scrivere in uno qualsiasi dei percorsi restituiti da questo metodo, passa l'oggetto File al nuovo metodo getStorageState() per verificare che lo spazio di archiviazione sia attualmente disponibile.

Anche altri metodi per accedere alla directory della cache specifica per l'app e alla directory OBB hanno ora versioni corrispondenti che forniscono l'accesso a dispositivi di archiviazione secondari: getExternalCacheDirs() e getObbDirs(), rispettivamente.

La prima voce nell'array File restituito è considerata la memoria esterna principale del dispositivo, che equivale alla File restituita da metodi esistenti come getExternalFilesDir().

Nota: a partire da Android 4.4, la piattaforma non richiede più che la tua app acquisisca WRITE_EXTERNAL_STORAGE o READ_EXTERNAL_STORAGE quando devi accedere solo alle regioni specifiche dell'app dello spazio di archiviazione esterno utilizzando i metodi descritti sopra. Tuttavia, le autorizzazioni sono necessarie per accedere alle regioni condivisibili dell'unità di archiviazione esterna fornite da getExternalStoragePublicDirectory().

Adattatori di sincronizzazione

Il nuovo metodo requestSync() in ContentResolver semplifica alcune procedure per definire una richiesta di sincronizzazione per ContentProvider incapsulando le richieste nel nuovo oggetto SyncRequest, che puoi creare con SyncRequest.Builder. Le proprietà in SyncRequest forniscono la stessa funzionalità delle chiamate di sincronizzazione ContentProvider esistenti, ma aggiunge la possibilità di specificare che la sincronizzazione deve essere interrotta se la rete è a consumo, attivando setDisallowMetered().

Input utente

Nuovi tipi di sensori

Il nuovo sensore TYPE_GEOMAGNETIC_ROTATION_VECTOR fornisce dati vettoriali di rotazione basati su un magnetometro, che è un'utile alternativa al sensore TYPE_ROTATION_VECTOR quando non è disponibile un giroscopio o quando viene utilizzato con eventi del sensore raggruppati per registrare l'orientamento del dispositivo mentre il telefono è in modalità di sospensione. Questo sensore richiede meno energia rispetto a TYPE_ROTATION_VECTOR, ma potrebbe essere soggetto a dati sugli eventi rumorosi ed è più efficace quando l'utente è all'aperto.

Android ora supporta anche i sensori di passi integrati nell'hardware:

TYPE_STEP_DETECTOR
Questo sensore attiva un evento ogni volta che l'utente effettua un passo. A ogni passaggio dell'utente, questo sensore invia un evento con valore pari a 1,0 e un timestamp che indica quando si è verificato il passaggio.
TYPE_STEP_COUNTER
Questo sensore attiva anche un evento per ogni passaggio rilevato, ma fornisce il numero totale di passaggi accumulati da quando il sensore è stato registrato per la prima volta da un'app.

Tieni presente che questi sensori a due fasi non sempre producono gli stessi risultati. Gli eventi TYPE_STEP_COUNTER si verificano con una latenza più elevata rispetto a quelli di TYPE_STEP_DETECTOR, ma questo perché l'algoritmo TYPE_STEP_COUNTER esegue un'elaborazione maggiore per eliminare i falsi positivi. Di conseguenza, TYPE_STEP_COUNTER potrebbe essere più lento nell'offrire eventi, ma i suoi risultati dovrebbero essere più precisi.

Entrambi i sensori di passi dipendono dall'hardware (il Nexus 5 è il primo dispositivo a supportarli), pertanto dovresti verificare la disponibilità con hasSystemFeature() utilizzando le costanti FEATURE_SENSOR_STEP_DETECTOR e FEATURE_SENSOR_STEP_COUNTER.

Eventi dei sensori raggruppati

Per gestire meglio l'alimentazione dei dispositivi, le API SensorManager ora consentono di specificare la frequenza con cui vuoi che il sistema invii batch di eventi dei sensori alla tua app. In questo modo, il numero di eventi effettivi dei sensori disponibili per la tua app non viene ridotto per un determinato periodo di tempo, ma viene ridotta la frequenza con cui il sistema chiama il tuo SensorEventListener con gli aggiornamenti del sensore. Ciò significa che, invece di pubblicare ogni evento nella tua app nel momento in cui si verifica, il sistema salva tutti gli eventi che si verificano in un determinato periodo di tempo e li pubblica tutti contemporaneamente nella tua app.

Per fornire il raggruppamento, la classe SensorManager aggiunge due nuove versioni del metodo registerListener() che consentono di specificare la "massima latenza dei report". Questo nuovo parametro specifica il ritardo massimo tollerato da SensorEventListener per la pubblicazione di nuovi eventi del sensore. Ad esempio, se specifichi una latenza batch di un minuto, il sistema pubblicherà l'insieme recente di eventi raggruppati a intervalli non più lunghi di un minuto effettuando chiamate consecutive al metodo onSensorChanged(), una volta per ogni evento raggruppati. Gli eventi dei sensori non subiranno mai ritardi superiori al valore di latenza massimo del report, ma potrebbero arrivare prima se altre app hanno richiesto una latenza più breve per lo stesso sensore.

Tuttavia, tieni presente che il sensore invierà alla tua app gli eventi raggruppati in base alla latenza del report solo quando la CPU è attiva. Anche se un sensore hardware che supporta il raggruppamento continuerà a raccogliere eventi del sensore mentre la CPU è in sospensione, non riattiva la CPU per fornire alla tua app gli eventi raggruppati. Quando il sensore esaurisce la memoria per gli eventi, inizia a eliminare gli eventi meno recenti per salvare quelli più recenti. Puoi evitare di perdere eventi riattivando il dispositivo prima che il sensore esaurisca la memoria, quindi chiama flush() per acquisire l'ultimo gruppo di eventi. Per stimare quando la memoria sarà piena e deve essere svuotata, chiama getFifoMaxEventCount() per ottenere il numero massimo di eventi del sensore che può salvare e dividi questo numero per la velocità con cui la tua app desidera ciascun evento. Usa questo calcolo per impostare sveglie di riattivazione con AlarmManager che richiamano il tuo Service (che implementa il SensorEventListener) per scaricare il sensore.

Nota:non tutti i dispositivi supportano la raggruppamento degli eventi del sensore poiché è necessario il supporto del sensore hardware. Tuttavia, a partire da Android 4.4, dovresti usare sempre i nuovi metodi registerListener(). Se il dispositivo non supporta il raggruppamento, il sistema ignora agevolmente l'argomento della latenza batch e invia gli eventi del sensore in tempo reale.

Identità controller

Android identifica ogni controller collegato con un numero intero univoco su cui puoi eseguire una query con getControllerNumber(), in modo da associare più facilmente ogni controller a un diverso giocatore di un gioco. Il numero relativo a ciascun controller può cambiare perché i controller vengono scollegati, collegati o riconfigurati dall'utente, quindi dovresti tenere traccia di quale numero di controller corrisponde a ciascun dispositivo di input registrando un'istanza di InputManager.InputDeviceListener. Quindi chiama getControllerNumber() per ogni InputDevice quando si verifica una modifica.

I dispositivi connessi ora forniscono anche gli ID prodotto e fornitore disponibili su getProductId() e getVendorId(). Se devi modificare le mappature delle chiavi in base al set di chiavi disponibile su un dispositivo, puoi inviare una query al dispositivo per verificare se determinate chiavi sono disponibili con hasKeys(int...).

Interfaccia utente

Modalità immersiva a schermo intero

Per offrire alla tua app un layout che riempia l'intero schermo, il nuovo flag SYSTEM_UI_FLAG_IMMERSIVE per setSystemUiVisibility() (se combinato con SYSTEM_UI_FLAG_HIDE_NAVIGATION) attiva una nuova modalità a schermo intero coinvolgente. Quando la modalità immersiva a schermo intero è attiva, la tua attività continua a ricevere tutti gli eventi touch. L'utente può visualizzare le barre di sistema scorrendo verso l'interno lungo l'area in cui solitamente appaiono le barre di sistema. Il flag SYSTEM_UI_FLAG_HIDE_NAVIGATION (e il flag SYSTEM_UI_FLAG_FULLSCREEN, se applicato) vengono cancellati in modo che le barre di sistema rimangano visibili. Tuttavia, se vuoi che le barre di sistema si nascondano di nuovo dopo qualche istante, puoi utilizzare il flag SYSTEM_UI_FLAG_IMMERSIVE_STICKY.

Barre di sistema traslucide

Ora puoi rendere le barre di sistema parzialmente traslucide con i nuovi temi Theme.Holo.NoActionBar.TranslucentDecor e Theme.Holo.Light.NoActionBar.TranslucentDecor. Se attivi le barre di sistema traslucide, il layout riempirà l'area dietro le barre di sistema, quindi devi attivare anche fitsSystemWindows per la parte del layout che non deve essere coperta dalle barre di sistema.

Se stai creando un tema personalizzato, impostane uno come tema principale oppure includi le proprietà di stile windowTranslucentNavigation e windowTranslucentStatus nel tuo tema.

Listener di notifica avanzato

Android 4.3 ha aggiunto le API NotificationListenerService, consentendo alle app di ricevere informazioni sulle nuove notifiche non appena vengono pubblicate dal sistema. In Android 4.4, i listener delle notifiche possono recuperare ulteriori metadati per la notifica e completare i dettagli sulle azioni della notifica:

Il nuovo campo Notification.extras include un Bundle per fornire metadati aggiuntivi al generatore di notifiche, come EXTRA_TITLE e EXTRA_PICTURE. La nuova classe Notification.Action definisce le caratteristiche di un'azione allegata alla notifica, che puoi recuperare dal nuovo campo actions.

Mirroring disegnabile per layout RTL

Nelle versioni precedenti di Android, se la tua app include immagini che devono invertire l'orientamento orizzontale per i layout da destra a sinistra, devi includere l'immagine speculare in una directory di risorse drawables-ldrtl/. Ora il sistema può eseguire automaticamente il mirroring delle immagini abilitando l'attributo autoMirrored su una risorsa disegnabile o chiamando setAutoMirrored(). Quando l'opzione è attiva, viene eseguito automaticamente il mirroring di Drawable quando la direzione del layout è da destra a sinistra.

Accessibilità

La classe View ora ti consente di dichiarare "regioni attive" per parti della tua UI che vengono aggiornate dinamicamente con nuovi contenuti di testo, aggiungendo il nuovo attributo accessibilityLiveRegion al layout XML o chiamando setAccessibilityLiveRegion(). Ad esempio, una schermata di accesso con un campo di testo che mostra la notifica "Password errata" deve essere contrassegnata come regione attiva, in modo che lo screen reader reciti il messaggio quando cambia.

Le app che offrono un servizio di accessibilità ora possono anche migliorare le loro funzionalità con nuove API che forniscono informazioni sulle raccolte di visualizzazioni, ad esempio le visualizzazioni a elenco o griglia utilizzando AccessibilityNodeInfo.CollectionInfo e AccessibilityNodeInfo.CollectionItemInfo.

Autorizzazioni app

Di seguito sono riportate le nuove autorizzazioni che la tua app deve richiedere con il tag <uses-permission> per poter utilizzare determinate nuove API:

INSTALL_SHORTCUT
Consente a un'applicazione di installare una scorciatoia in Avvio app
UNINSTALL_SHORTCUT
Consente a un'applicazione di disinstallare una scorciatoia in Avvio app
TRANSMIT_IR
Consente a un'applicazione di utilizzare il trasmettitore IR del dispositivo, se disponibile

Nota:a partire da Android 4.4, la piattaforma non richiede più che la tua app acquisisca WRITE_EXTERNAL_STORAGE o READ_EXTERNAL_STORAGE quando vuoi accedere alle regioni specifiche dell'app dello spazio di archiviazione esterno utilizzando metodi come getExternalFilesDir(). Tuttavia, sono comunque necessarie le autorizzazioni se vuoi accedere alle regioni condivisibili dello spazio di archiviazione esterno, fornite da getExternalStoragePublicDirectory().

Funzionalità dispositivo

Di seguito sono riportate le nuove funzionalità dei dispositivi che puoi dichiarare con il tag <uses-feature> per dichiarare i requisiti della tua app e attivare i filtri su Google Play o controllare in fase di runtime:

FEATURE_CONSUMER_IR
Il dispositivo è in grado di comunicare con i dispositivi IR dei consumatori.
FEATURE_DEVICE_ADMIN
Il dispositivo supporta l'applicazione forzata dei criteri relativi ai dispositivi tramite gli amministratori dei dispositivi.
FEATURE_NFC_HOST_CARD_EMULATION
Il dispositivo supporta l'emulazione di carte NFC basate sull'host.
FEATURE_SENSOR_STEP_COUNTER
Il dispositivo include un contapassi hardware.
FEATURE_SENSOR_STEP_DETECTOR
Il dispositivo include un rilevatore di passi hardware.

Per una visualizzazione dettagliata di tutte le modifiche all'API in Android 4.4, consulta il report Differenze API.