API per Android 4.4

Livello API: 19

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

In qualità di sviluppatore di app, dovresti scaricare l'immagine di sistema e la piattaforma SDK di Android 4.4 da SDK Manager il prima possibile. Se non hai un dispositivo con Android 4.4 su cui testare la tua app, utilizza l'immagine di sistema Android 4.4 per testare l'app nell'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 la tua 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 supportando anche le versioni precedenti aggiungendo al codice condizioni che controllano il livello API di sistema prima di eseguire API non supportate da minSdkVersion. Per saperne 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 modifiche del comportamento

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

Se la tua app legge contenuti dalla memoria 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. Questo significa che i file all'interno della directory restituita da getExternalStoragePublicDirectory() non sono più accessibili senza l'autorizzazione. Tuttavia, se 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 se viene eseguita su Android 4.4, soprattutto se aggiorni l'app targetSdkVersion a "19" o versioni successive.

È stato eseguito l'upgrade del codice sottostante la classe WebView e le API correlate perché si basano 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 significa che se la tua app utilizza WebView, in alcuni casi il suo comportamento potrebbe risentirne. Anche se le modifiche al comportamento noto sono documentate e interessano principalmente la tua app soltanto quando aggiorni l'impostazione targetSdkVersion dell'app a"19 " o una versione successiva, la nuova WebView opera in"modalità non standard" per fornire alcune funzionalità precedenti nelle app che hanno come target il livello API 18 e 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 la tua app potrebbe essere interessata dall'aggiornamento di targetSdkVersion a "19" o versione successiva.

Se la tua app usa AlarmManager...

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

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

Se la sveglia non è associata a un'ora esatta, ma è comunque importante che venga richiamata durante un intervallo di tempo specifico (ad esempio, tra le 14:00 e le 16:00), puoi utilizzare il nuovo metodo setWindow(), che accetta un'ora "prima" per la sveglia e una "finestra" di tempo successiva al primo in cui il sistema deve richiamare 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 un valore superiore, la creazione di una sincronizzazione con addPeriodicSync() esegue le operazioni di sincronizzazione entro un intervallo flessibile predefinito pari a circa il 4% del periodo specificato. Ad esempio, se la frequenza di sondaggio è di 24 ore, l'operazione di sincronizzazione potrebbe avvenire ogni giorno all'incirca alla stessa ora, anziché sempre alla stessa ora.

Per specificare un intervallo flessibile per le operazioni di sincronizzazione, devi iniziare a utilizzare il nuovo metodo requestSync(). Per ulteriori dettagli, consulta la sezione Schede di sincronizzazione più avanti.

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 quando vengono eseguite su Android 4.4.

Framework di 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 forniscono 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 effettivamente 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 di PrintDocumentAdapter. All'interno di questa classe devi implementare alcuni metodi di callback, tra cui onLayout() per stabilire il layout in base alle proprietà di stampa fornite e onWrite() per serializzare i contenuti stampabili in un file ParcelFileDescriptor.

Per poter scrivere i tuoi contenuti su ParcelFileDescriptor, devi inviare un PDF. Le nuove API PdfDocument offrono un modo pratico per farlo, fornendo un Canvas di getCanvas(), su cui puoi disegnare i tuoi contenuti stampabili. Quindi scrivi 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 bitmap, le API helper nella libreria di supporto fanno tutto il lavoro per te. È sufficiente creare una nuova istanza di PrintHelper, impostare la modalità di scalabilità con setScaleMode() e trasmettere Bitmap a printBitmap(). È tutto. La libreria gestisce tutte le interazioni rimanenti con il sistema per inviare le bitmap alla stampante.

Servizi di stampa degli edifici

In qualità di OEM di stampanti, puoi utilizzare il framework android.printservice per fornire l'interoperabilità con le tue stampanti di dispositivi Android. Puoi creare e distribuire servizi di stampa sotto forma di APK, che gli utenti possono installare sui propri dispositivi . Un'app di servizio di stampa funziona principalmente come servizio headless mediante la sottoclassificazione della classe PrintService, che riceve i 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 "Fornitore SMS") consente alle app di leggere e scrivere messaggi SMS ed MMS sul dispositivo. Include tabelle per i messaggi SMS e 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 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 fornitore di SMS, ma potrebbero anche ricevere una notifica quando arriva un nuovo SMS ascoltando la trasmissione SMS_RECEIVED_ACTION, che è una trasmissione non interrotta che potrebbe essere recapitata a più app. Questa trasmissione è destinata alle app che, sebbene non siano selezionate come app per SMS predefinita, devono leggere messaggi in arrivo speciali, ad esempio per eseguire la verifica del numero di telefono.

Per ulteriori informazioni, leggi il post del blog, Preparare le app per SMS pronte per Lollipop.

Wireless e connettività

Emulazione della scheda host

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

Se vuoi emulare una scheda 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 verrà coinvolta direttamente nelle transazioni, ma è necessario per registrare gli AID che devono essere gestiti da Secure Element.

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

Modalità lettore NFC

La nuova modalità lettore NFC consente a un'attività di limitare tutta l'attività NFC alla sola lettura dei tipi di tag a cui è interessata l'attività 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 funzionare su entrambe le estremità di un'interfaccia di pagamento mobile: un dispositivo funziona come terminale di pagamento (un dispositivo che esegue un'attività in modalità lettore) e un altro dispositivo come 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 segnali passando la frequenza e il modello del segnale desiderati con transmit().

Dovresti sempre verificare innanzitutto se un dispositivo include un trasmettitore IR chiamando hasIrEmitter(); tuttavia, se la tua app è compatibile solo con i dispositivi che ne hanno uno, dovresti 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, che consente un cambiamento continuo della risoluzione durante la riproduzione su un Surface: puoi inviare ai frame di input del decodificatore una nuova risoluzione e la risoluzione dei buffer di output cambia senza un divario significativo.

Puoi attivare la riproduzione adattiva aggiungendo due tasti a 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 passerà tra le risoluzioni uguali o inferiori a questi valori senza interruzioni. Il codec può anche supportare risoluzioni superiori ai valori massimi specificati (purché rientri nei limiti dei profili supportati), ma le transizioni a risoluzioni maggiori 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 Update) in un unico buffer.

Tuttavia, prima di provare a 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 maggiori. Pertanto, devi impostare i valori di risoluzione massimi in base al materiale di origine che stai decodificando.

Timestamp audio on demand

Per facilitare la sincronizzazione audio-video, la nuova classe AudioTimestamp fornisce dettagli sulla sequenza temporale di 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 passalo a getTimestamp(). Se la richiesta per il timestamp ha esito positivo, l'istanza AudioTrack viene compilata con una posizione in unità di frame, insieme al tempo stimato in cui il frame è stato presentato o si impegna a essere presentato.

Puoi utilizzare il valore nanoTime in AudioTimestamp (che è monotonico) per trovare il fotogramma 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 (prendendo in considerazione la frequenza di campionamento) per prevedere quale fotogramma audio è previsto nello stesso momento di un frame video.

Mostra il lettore di immagini della superficie

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(). Quindi chiama getSurface() per creare un nuovo Surface e inviare i tuoi dati di immagine con un produttore come MediaPlayer o MediaCodec. Per ricevere una notifica quando sono disponibili nuove immagini dalla superficie, implementa l'interfaccia ImageReader.OnImageAvailableListener e registrala con setOnImageAvailableListener().

Ora, mentre disegni contenuti sul tuo Surface, il tuo ImageReader.OnImageAvailableListener riceve una chiamata a onImageAvailable() ogni volta che ogni nuovo frame immagine diventa disponibile, fornendoti il corrispondente ImageReader. Puoi utilizzare ImageReader per acquisire i dati dell'immagine del frame come oggetto Image chiamando acquireLatestImage() o acquireNextImage().

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

Misurazione di picchi e RMS

Ora puoi eseguire 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 Visualizer.MeasurementPeakRms specificato vengono impostati sui valori misurati più recenti.

Potenziatore di volume

LoudnessEnhancer è una nuova sottoclasse di AudioEffect che consente di aumentare il volume udibile di MediaPlayer o AudioTrack. Questa opzione può essere particolarmente utile insieme al nuovo metodo getMeasurementPeakRms() menzionato sopra, per aumentare il volume delle tracce audio vocali mentre altri contenuti multimediali sono attualmente in riproduzione.

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 RemoteController ti consentono di creare il tuo controller remoto, 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 limitazioni della privacy appropriate, 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 vuota la tua implementazione 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 RemoteControlClient) aggiungendo la possibilità per gli utenti di valutare la traccia corrente dal controller remoto.

La nuova classe Rating contiene informazioni su una valutazione degli utenti. Una valutazione è 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 lo stile.

Per consentire agli utenti di valutare le tue rotte da un controller remoto:

Per ricevere un callback quando l'utente cambia la valutazione dal controller remoto, implementa la nuova interfaccia RemoteControlClient.OnMetadataUpdateListener e passa un'istanza a setMetadataUpdateListener(). Quando l'utente cambia la valutazione, il tuo RemoteControlClient.OnMetadataUpdateListener riceve una chiamata a onMetadataUpdate(), trasmettendo 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 dei sottotitoli 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 oggetto InputStream che trasporta i dati dei sottotitoli e un oggetto MediaFormat che specifica il formato dei dati dei sottotitoli, che puoi specificare usando createSubtitleFormat(). Inoltre, questi sottotitoli vengono visualizzati sul video in base alle preferenze dell'utente.

Se non utilizzi VideoView per visualizzare i contenuti video, fai in modo che l'overlay dei sottotitoli corrisponda il più possibile alle preferenze dell'utente relative ai sottotitoli. Una nuova API CaptioningManager consente di eseguire query sulle preferenze dei sottotitoli dell'utente, inclusi gli stili definiti da CaptioningManager.CaptionStyle, come tipo di carattere e 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 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 i 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 all'altra, esegui una "transizione", che calcola l'animazione necessaria per cambiare il layout dalla scena corrente a quella successiva.

Per passare da una scena all'altra, in genere devi eseguire le seguenti operazioni:

  1. Specifica il campo ViewGroup contenente i componenti dell'interfaccia utente da 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 eseguire i passaggi 1 e 2. Un elemento Scene contiene metadati che descrivono le proprietà di un layout necessarie per eseguire una transizione, tra cui la vista principale e il layout della scena. Puoi creare un elemento Scene utilizzando un costruttore della classe o il metodo statico getSceneForLayout().

Dovrai quindi utilizzare l'TransitionManager per eseguire i passaggi 3 e 4. Un modo è passare Scene al metodo statico go(). In questo modo viene trovata la vista principale della scena nel layout corrente ed esegue una transizione nelle viste secondarie per raggiungere il layout definito da Scene.

In alternativa, non è necessario creare un oggetto Scene, ma puoi chiamare beginDelayedTransition(), specificando un ViewGroup contenente le viste da modificare. Quindi, aggiungi, rimuovi o riconfigura le viste di destinazione. Una volta che il sistema avrà applicato le modifiche necessarie, inizia una transizione che anima tutte le viste interessate.

Per un controllo aggiuntivo, puoi definire degli insiemi di transizioni che dovrebbero avvenire tra scene predefinite utilizzando un file XML nella directory del progetto res/transition/. All'interno di un elemento <transitionManager>, specifica uno o più tag <transition> che specificano ciascuno una scena (un riferimento a un file di layout) e la transizione da applicare quando entri e/o esci da quella scena. Quindi, gonfia questo insieme di transizioni utilizzando inflateTransitionManager(). Utilizza l'oggetto 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 di TransitionManager.

Quando specifichi una transizione, puoi utilizzare diversi tipi predefiniti definiti dalle sottoclassi di Transition, come Fade e ChangeBounds. Se non specifichi un tipo di transizione, per impostazione predefinita il sistema utilizza AutoTransition, che applica automaticamente 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 ti consente di monitorare le modifiche apportate alle proprietà e di creare animazioni in base a tali modifiche. Ad esempio, puoi fornire una sottoclasse di Transition che rilevi le modifiche alla proprietà "rotazione" di una vista e poi anima le modifiche.

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

Messa in pausa dell'animazione

Le API Animator ora ti 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 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 sottoclasse la classe astratta AnimatorListenerAdapter, che ora include implementazioni vuote per i callback pause e riprendere definite da Animator.AnimatorPauseListener.

Bitmap riutilizzabili

Ora puoi riutilizzare qualsiasi bitmap modificabile in BitmapFactory per decodificare qualsiasi altra bitmap, anche quando la nuova bitmap ha dimensioni diverse, a condizione che 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, visita la pagina 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 la 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 delle 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, perché il buffer di pixel sottostante non viene 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 che vuoi 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 a quel file (possibilmente con accesso in scrittura) senza importare il file nell'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 scelta dei file implementando un fornitore di contenuti come sottoclasse della nuova classe DocumentsProvider. La sottoclasse DocumentsProvider deve includere un filtro per intent che accetti l'azione PROVIDER_INTERFACE ("android.content.action.DOCUMENTS_PROVIDER"). Devi quindi implementare i quattro metodi astratti in DocumentsProvider:

queryRoots()
Deve restituire un Cursor che descriva tutte le directory principali dell'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 ha selezionato un file e l'app client ha richiesto l'accesso chiamando openFileDescriptor().

Per ulteriori informazioni, consulta la guida Storage Access Framework.

Accesso a unità di archiviazione esterne

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, tranne per il 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 dell'app e alla directory OBB hanno ora versioni corrispondenti che forniscono l'accesso ai 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, ad esempio 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 della memoria esterna utilizzando i metodi sopra indicati. Tuttavia, le autorizzazioni sono necessarie se vuoi 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 le stesse funzionalità delle chiamate di sincronizzazione ContentProvider esistenti, ma aggiunge la possibilità di specificare l'interruzione della sincronizzazione se la rete è a consumo, attivando setDisallowMetered().

Input utente

Nuovi tipi di sensori

Il nuovo sensore TYPE_GEOMAGNETIC_ROTATION_VECTOR fornisce dati vettore di rotazione basati su un magnetometro, che è un'alternativa utile al sensore TYPE_ROTATION_VECTOR quando non è disponibile un giroscopio o quando viene utilizzato con eventi del sensore in batch per registrare l'orientamento del dispositivo quando 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 passo integrati nell'hardware:

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

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

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

Eventi dei sensori in batch

Per gestire meglio l'alimentazione dei dispositivi, le API SensorManager ora ti consentono di specificare la frequenza con cui vuoi che il sistema invii alla tua app batch di eventi dei sensori. Questo non riduce il numero di eventi effettivi dei sensori disponibili per la tua app per un determinato periodo di tempo, ma riduce la frequenza con cui il sistema chiama il tuo SensorEventListener con gli aggiornamenti dei sensori. In altre parole, anziché pubblicare ogni evento nell'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 i batch, la classe SensorManager aggiunge due nuove versioni del metodo registerListener() che consentono di specificare la "latenza massima 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 1 minuto, il sistema pubblicherà l'insieme recente di eventi in batch a un intervallo non più lungo di 1 minuto effettuando chiamate consecutive al tuo metodo onSensorChanged(), una volta per ogni evento in batch. Gli eventi del sensore non subiranno mai un ritardo superiore 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 pubblicare gli eventi raggruppati nell'app. Quando il sensore esaurisce la memoria disponibile per gli eventi, inizia a eliminare gli eventi meno recenti per salvare gli eventi più recenti. Puoi evitare di perdere eventi riattivando il dispositivo prima che il sensore esaurisca la memoria e poi chiama il numero flush() per acquisire l'ultimo gruppo di eventi. Per stimare quando la memoria sarà piena e dovrebbe essere svuotata, chiama getFifoMaxEventCount() per ottenere il numero massimo di eventi del sensore che può essere salvato e dividi questo numero per la velocità con cui la tua app desidera ciascun evento. Usa questo calcolo per impostare sveglie con AlarmManager che richiamano il tuo Service (che implementa il SensorEventListener) per scaricare il sensore.

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

Identità controller

Android ora identifica ogni controller collegato con un numero intero univoco su cui puoi eseguire query con getControllerNumber(), semplificando l'associazione di ogni controller a un giocatore diverso in un gioco. Il numero di ciascun controller può cambiare perché i controller vengono disconnessi, connessi o riconfigurati dall'utente, quindi devi 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.

Inoltre, i dispositivi connessi ora forniscono gli ID prodotto e fornitore disponibili in getProductId() e getVendorId(). Se devi modificare le mappature delle chiavi in base al set di chiavi disponibili 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 immersiva. Quando la modalità a schermo intero immersiva è attiva, la tua attività continua a ricevere tutti gli eventi touch. L'utente può mostrare le barre di sistema scorrendo verso l'interno l'area in cui normalmente compaiono. Cancella il flag SYSTEM_UI_FLAG_HIDE_NAVIGATION (e il flag SYSTEM_UI_FLAG_FULLSCREEN, se applicato) 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 dovrai attivare anche fitsSystemWindows per la parte del layout che non deve essere coperta dalle barre di sistema.

Se crei un tema personalizzato, impostane uno come tema principale o 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 di 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 inviare metadati aggiuntivi al generatore di notifiche, come EXTRA_TITLE e EXTRA_PICTURE. La nuova classe Notification.Action definisce le caratteristiche di un'azione associata 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 attivando l'attributo autoMirrored su una risorsa disegnabile o chiamando setAutoMirrored(). Quando l'opzione è attiva, l'elemento Drawable si riflette automaticamente quando la direzione del layout è da destra a sinistra.

Accessibilità

La classe View ora consente di dichiarare "regioni attive" per parti della 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 di "password errata" dovrebbe essere contrassegnata come area attiva, in modo che lo screen reader reciti il messaggio quando cambia.

Anche le app che offrono un servizio di accessibilità possono ora migliorare le proprie capacità con nuove API che forniscono informazioni sulle raccolte di visualizzazioni, ad esempio le visualizzazioni 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 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 dell'unità di archiviazione esterna utilizzando metodi quali getExternalFilesDir(). Tuttavia, le autorizzazioni sono comunque necessarie se vuoi accedere alle regioni condivisibili dell'unità di archiviazione esterna, 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 dell'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 consumer.
FEATURE_DEVICE_ADMIN
Il dispositivo supporta l'applicazione forzata dei criteri relativi ai dispositivi tramite gli amministratori del dispositivo.
FEATURE_NFC_HOST_CARD_EMULATION
Il dispositivo supporta l'emulazione della scheda NFC basata sull'host.
FEATURE_SENSOR_STEP_COUNTER
Il dispositivo include un contatore di passi hardware.
FEATURE_SENSOR_STEP_DETECTOR
Il dispositivo include un rilevatore di passi hardware.

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