API per Android 4.0

Livello API: 14

Android 4.0 (ICE_CREAM_SANDWICH) è una release principale della piattaforma che aggiunge una serie di nuove funzionalità per utenti e sviluppatori di app. Oltre a tutte le nuove funzionalità e API illustrate di seguito, Android 4.0 è una release importante per la piattaforma perché consente di accedere agli schermi più piccoli dell'ampio set di API e temi olografici di Android 3.x. In qualità di sviluppatore di app, ora hai un'unica piattaforma e un framework API unificato che ti consente di sviluppare e pubblicare la tua applicazione con un unico APK che offre un'esperienza utente ottimizzata per smartphone, tablet e altro ancora quando esegui la stessa versione di Android: Android 4.0 (livello API 14) o versioni successive.

Per gli sviluppatori, la piattaforma Android 4.0 è disponibile come componente scaricabile per l'SDK Android. La piattaforma scaricabile include una libreria Android e un'immagine di sistema, oltre a un set di skin per emulatori e altro ancora. Per iniziare a sviluppare o testare la piattaforma Android 4.0, utilizza Android SDK Manager per scaricare la piattaforma nel tuo SDK.

Panoramica dell'API

Le sezioni che seguono forniscono una panoramica tecnica delle nuove API in Android 4.0.

API social nel provider di contatti

Le API di contatto definite dal provider ContactsContract sono state ampliate per supportare nuove funzionalità orientate ai social, come un profilo personale per il proprietario del dispositivo e la possibilità per gli utenti di invitare singoli contatti sui social network installati sul dispositivo.

Profilo utente

Android ora include un profilo personale che rappresenta il proprietario del dispositivo, come definito dalla tabella ContactsContract.Profile. Le app social che gestiscono l'identità dell'utente possono contribuire ai dati del profilo dell'utente creando una nuova voce ContactsContract.RawContacts all'interno di ContactsContract.Profile. Ciò significa che i contatti non elaborati che rappresentano l'utente del dispositivo non appartengono alla tabella dei contatti non elaborati tradizionale definita dall'URI ContactsContract.RawContacts; devi invece aggiungere un contatto non elaborato del profilo nella tabella all'indirizzo CONTENT_RAW_CONTACTS_URI. I contatti non elaborati in questa tabella vengono poi aggregati nel singolo profilo visibile all'utente denominato "Io".

L'aggiunta di un nuovo contatto non elaborato per il profilo richiede l'autorizzazione android.Manifest.permission#WRITE_PROFILE. Analogamente, per leggere dalla tabella profilo, devi richiedere l'autorizzazione android.Manifest.permission#READ_PROFILE. Tuttavia, per la maggior parte delle app non dovrebbe essere necessario leggere il profilo utente, anche quando contribuiscono dati al profilo. La lettura del profilo utente è un'autorizzazione sensibile e gli utenti dovrebbero essere scettici nei confronti delle app che la richiedono.

Intenzione di invito

L'azione intent INVITE_CONTACT consente a un'app di richiamare un'azione che indica che l'utente vuole aggiungere un contatto a un social network. L'app che riceve l'app la utilizza per invitare il contatto specificato al social network. La maggior parte delle app sarà nella fase di ricezione di questa operazione. Ad esempio, l'app Persone integrata richiama l'intent di invito quando l'utente seleziona "Aggiungi connessione" per un'app social specifica, elencata nei dettagli di contatto di una persona.

Per rendere visibile l'app nell'elenco "Aggiungi connessione", l'app deve fornire un adattatore di sincronizzazione per sincronizzare i dati di contatto dal social network. Devi quindi indicare al sistema che la tua app risponde all'intent INVITE_CONTACT aggiungendo l'attributo inviteContactActivity al file di configurazione della sincronizzazione dell'app, con un nome completo dell'attività che il sistema deve avviare quando invia l'intent di invito. L'attività che inizia può quindi recuperare l'URI del contatto in questione dai dati dell'intent ed eseguire le operazioni necessarie per invitare il contatto alla rete o aggiungere la persona alle connessioni dell'utente.

Foto grandi

Android ora supporta le foto ad alta risoluzione per i contatti. Ora, quando esegui il push di una foto in un record dei contatti, il sistema la elabora sia in una miniatura 96 x 96 (come in precedenza) sia in una "foto display" 256 x 256 archiviata in un nuovo archivio di foto basato su file (le dimensioni esatte scelte dal sistema potrebbero variare in futuro). Puoi aggiungere una foto di grandi dimensioni a un contatto inserendo una foto grande nella consueta colonna PHOTO di una riga di dati, che il sistema elaborerà nella miniatura appropriata e mostrerà i record fotografici.

Feedback sull'utilizzo dei contatti

Le nuove API ContactsContract.DataUsageFeedback consentono di monitorare la frequenza con cui l'utente utilizza determinati metodi di contatto, ad esempio la frequenza con cui l'utente utilizza ciascun numero di telefono o indirizzo email. Queste informazioni consentono di migliorare il ranking di ogni metodo di contatto associato a ogni persona e di fornire suggerimenti migliori per contattare ogni persona.

Provider di calendari

Le nuove API di calendario consentono di leggere, aggiungere, modificare ed eliminare calendari, eventi, partecipanti, promemoria e avvisi archiviati nel provider del calendario.

Queste API possono essere utilizzate da diverse app e widget per leggere e modificare gli eventi nel calendario. Tuttavia, alcuni dei casi d'uso più interessanti sono gli adattatori di sincronizzazione che sincronizzano il calendario dell'utente da altri servizi di calendario con il provider di calendario, in modo da offrire una posizione unificata per tutti gli eventi dell'utente. Gli eventi di Google Calendar, ad esempio, vengono sincronizzati con il fornitore di calendari tramite l'adattatore di sincronizzazione di Google Calendar, consentendo di visualizzarli con l'app Calendar integrata di Android.

Il modello dei dati per i calendari e le informazioni relative agli eventi nel fornitore di calendari è definito da CalendarContract. Tutti i dati del calendario dell'utente sono archiviati in una serie di tabelle definite da varie sottoclassi di CalendarContract:

  • La tabella CalendarContract.Calendars contiene le informazioni specifiche del calendario. Ogni riga di questa tabella contiene i dettagli di un singolo calendario, come nome, colore, informazioni di sincronizzazione e così via.
  • La tabella CalendarContract.Events contiene informazioni specifiche sull'evento. Ogni riga in questa tabella contiene le informazioni su un singolo evento, come il titolo, la località, l'ora di inizio, l'ora di fine e così via. L'evento può verificarsi una volta o ripetere più volte. I partecipanti, i promemoria e le proprietà estese vengono archiviati in tabelle separate e utilizzano il _ID dell'evento per collegarli all'evento.
  • La tabella CalendarContract.Instances contiene l'ora di inizio e di fine delle occorrenze di un evento. Ogni riga di questa tabella rappresenta una singola occorrenza. Per gli eventi occasionali, è disponibile una mappatura individuale delle istanze agli eventi. Per gli eventi ricorrenti, vengono generate automaticamente più righe per corrispondere alle molteplici occorrenze di quell'evento.
  • La tabella CalendarContract.Attendees contiene le informazioni sul partecipante o sull'ospite all'evento. Ogni riga rappresenta un singolo invitato di un evento. Specifica il tipo di ospite e la sua risposta all'evento.
  • La tabella CalendarContract.Reminders contiene i dati dell'avviso/delle notifiche. Ogni riga rappresenta un singolo avviso per un evento. Un evento può avere più promemoria. Il numero di promemoria per evento viene specificato nel campo MAX_REMINDERS, che viene impostato dall'adattatore di sincronizzazione proprietario del calendario in questione. I promemoria vengono specificati in numero di minuti prima della programmazione dell'evento e specificano un metodo di allarme, ad esempio un avviso, un'email o un SMS per ricordare all'utente.
  • La tabella CalendarContract.ExtendedProperties contiene i campi di dati opachi utilizzati dall'adattatore di sincronizzazione. Il provider non intraprende alcuna azione con gli elementi in questa tabella, tranne per eliminarli quando vengono eliminati i relativi eventi.

Per accedere ai dati del calendario di un utente con il fornitore di calendari, l'applicazione deve richiedere l'autorizzazione READ_CALENDAR (per l'accesso in lettura) e WRITE_CALENDAR (per l'accesso in scrittura).

Intento evento

Se vuoi soltanto aggiungere un evento al calendario dell'utente, puoi utilizzare un intent ACTION_INSERT con i dati definiti da Events.CONTENT_URI per avviare un'attività nell'app Calendar che crea nuovi eventi. L'utilizzo dell'intent non richiede alcuna autorizzazione e puoi specificare i dettagli dell'evento con i seguenti extra:

Provider di segreteria

Il nuovo provider della segreteria consente alle applicazioni di aggiungere messaggi vocali al dispositivo per presentarli tutti in un'unica presentazione visiva. Ad esempio, è possibile che un utente abbia più sorgenti di segreteria, ad esempio una del fornitore di servizi del telefono e altre provenienti da VoIP o da altri servizi vocali alternativi. Queste app possono utilizzare le API dei provider di messaggi vocali per aggiungere i messaggi vocali al dispositivo. L'applicazione Telefono integrata presenta quindi tutti i messaggi vocali all'utente in un'unica presentazione. Sebbene l'applicazione Telefono del sistema sia l'unica in grado di leggere tutti i messaggi vocali, ogni applicazione che fornisce messaggi vocali può leggere quelli che ha aggiunto al sistema (ma non può leggere i messaggi vocali di altri servizi).

Dato che le API attualmente non consentono alle app di terze parti di leggere tutti i messaggi vocali dal sistema, le uniche app di terze parti che dovrebbero utilizzare le API dei messaggi vocali sono quelle che dispongono della segreteria da recapitare all'utente.

La classe VoicemailContract definisce il fornitore di contenuti per il fornitore di servizi vocali. Le sottoclassi VoicemailContract.Voicemails e VoicemailContract.Status forniscono tabelle in cui le app possono inserire i dati della segreteria per l'archiviazione sul dispositivo. Per un esempio di app del fornitore di servizi vocali, consulta la demo del fornitore di messaggi vocali.

Multimediale

Android 4.0 aggiunge diverse nuove API per le applicazioni che interagiscono con contenuti multimediali come foto, video e musica.

Effetti multimediali

Un nuovo framework di effetti multimediali ti consente di applicare una varietà di effetti visivi a immagini e video. Ad esempio, gli effetti immagine consentono di correggere facilmente gli occhi rossi, convertire un'immagine in scala di grigi, regolare la luminosità, regolare la saturazione, ruotare un'immagine, applicare un effetto fisheye e molto altro. Il sistema esegue tutti gli effetti sulla GPU per ottenere le massime prestazioni.

Per ottenere le massime prestazioni, gli effetti vengono applicati direttamente alle texture OpenGL, quindi l'applicazione deve avere un contesto OpenGL valido prima di poter utilizzare le API degli effetti. Le texture a cui applichi gli effetti provengono da bitmap, da video o perfino dalla fotocamera. Tuttavia, le texture devono rispettare alcune limitazioni:

  1. Devono essere associati a un'immagine texture GL_TEXTURE_2D
  2. Devono contenere almeno un livello di mipmap

Un oggetto Effect definisce un singolo effetto multimediale che puoi applicare a un frame immagine. Il flusso di lavoro di base per creare un Effect è:

  1. Chiama EffectContext.createWithCurrentGlContext() dal tuo contesto OpenGL ES 2.0.
  2. Usa il valore EffectContext restituito per chiamare EffectContext.getFactory(), che restituisce un'istanza di EffectFactory.
  3. Richiama createEffect(), trasmettendo un nome effetto da @link android.media.effect.EffectShop}, ad esempio EFFECT_FISHEYE o EFFECT_VIGNETTE.

Puoi regolare i parametri di un effetto richiamando setParameter() e passando un nome e un valore per il parametro. Ogni tipo di effetto accetta parametri diversi, documentati con il nome dell'effetto. Ad esempio, EFFECT_FISHEYE ha un parametro per scale della distorsione.

Per applicare un effetto a una texture, chiama apply() su Effect e trasmetti la texture di input, la larghezza e l'altezza e la texture di output. La texture di input deve essere associata a un'immagine di texture GL_TEXTURE_2D (in genere questa operazione viene eseguita richiamando la funzione glTexImage2D()). Puoi fornire più livelli di mappa immagine. Se la texture di output non è stata associata a un'immagine di texture, verrà automaticamente associata all'effetto come GL_TEXTURE_2D e con un livello di mappa Mip (0), che avrà le stesse dimensioni dell'input.

È garantito che tutti gli effetti elencati in EffectFactory siano supportati. Tuttavia, alcuni effetti aggiuntivi disponibili da librerie esterne non sono supportati da tutti i dispositivi, quindi devi prima verificare se l'effetto desiderato dalla libreria esterna è supportato chiamando isEffectSupported().

Client di controllo remoto

Il nuovo RemoteControlClient consente ai lettori multimediali di attivare i controlli di riproduzione dai client di controllo remoto come la schermata di blocco del dispositivo. I lettori multimediali possono inoltre mostrare informazioni sui contenuti multimediali attualmente in riproduzione per la visualizzazione sul telecomando, ad esempio informazioni sulle tracce e copertine degli album.

Per abilitare i client di controllo remoto per il tuo media player, crea un'istanza di RemoteControlClient con il relativo costruttore, passando un PendingIntent che trasmetta ACTION_MEDIA_BUTTON. L'intent deve anche dichiarare il componente esplicito BroadcastReceiver nella tua app che gestisce l'evento ACTION_MEDIA_BUTTON.

Per dichiarare quali input di controllo dei contenuti multimediali è in grado di gestire il tuo player, devi chiamare setTransportControlFlags() sul tuo RemoteControlClient, passando un insieme di flag FLAG_KEY_MEDIA_*, come FLAG_KEY_MEDIA_PREVIOUS e FLAG_KEY_MEDIA_NEXT.

Devi quindi registrare il tuo RemoteControlClient passandolo a MediaManager.registerRemoteControlClient(). Una volta registrato, il ricevitore di trasmissione che hai dichiarato quando hai creato un'istanza RemoteControlClient riceverà eventi ACTION_MEDIA_BUTTON quando viene premuto un pulsante da un telecomando. L'intent ricevuto include il KeyEvent per il tasto multimediale premuto, che puoi recuperare dall'intent con getParcelableExtra(Intent.EXTRA_KEY_EVENT).

Per visualizzare sul telecomando le informazioni relative ai contenuti multimediali in riproduzione, chiama editMetaData() e aggiungi i metadati al RemoteControlClient.MetadataEditor restituito. Puoi fornire una bitmap per l'artwork dei contenuti multimediali, informazioni numeriche come il tempo trascorso e informazioni di testo come il titolo della traccia. Per informazioni sulle chiavi disponibili, consulta i flag METADATA_KEY_* in MediaMetadataRetriever.

Per un esempio di implementazione, consulta il sito Random Music Player, che fornisce una logica di compatibilità tale da abilitare il client di controllo remoto sui dispositivi Android 4.0, continuando a supportare i dispositivi fino ad Android 2.1.

Lettori multimediali

  • Per lo streaming di contenuti multimediali online da MediaPlayer ora è necessaria l'autorizzazione INTERNET. Se usi MediaPlayer per riprodurre contenuti da internet, assicurati di aggiungere l'autorizzazione INTERNET al file manifest, altrimenti la riproduzione di contenuti multimediali non funzionerà a partire da Android 4.0.
  • setSurface() consente di definire un Surface che si comporti come il sink video.
  • setDataSource() ti consente di inviare intestazioni HTTP aggiuntive con la tua richiesta, il che può essere utile per il live streaming HTTP(S)
  • Il live streaming HTTP(S) ora rispetta i cookie HTTP nelle richieste

Tipi di elementi multimediali

Android 4.0 aggiunge il supporto per:

  • Protocollo di live streaming HTTP/HTTPS versione 3
  • Codifica audio AAC non elaborata da ADTS
  • Immagini WEBP
  • Video Matroska

Per ulteriori informazioni, consulta l'articolo Formati multimediali supportati.

Fotocamera

La classe Camera ora include le API per il rilevamento dei volti e il controllo delle aree di messa a fuoco e misurazione.

Riconoscimento facciale

Le app fotocamera ora possono migliorare le loro capacità grazie alle API di rilevamento dei volti di Android, che non solo rilevano il volto di un soggetto, ma anche caratteristiche facciali specifiche, come gli occhi e la bocca.

Per rilevare volti nell'applicazione della fotocamera, devi registrare un Camera.FaceDetectionListener chiamando il numero setFaceDetectionListener(). Dopodiché puoi avviare la superficie della videocamera e iniziare a rilevare i volti chiamando il numero startFaceDetection().

Quando il sistema rileva uno o più volti nella scena della videocamera, chiama il callback onFaceDetection() nella tua implementazione di Camera.FaceDetectionListener, incluso un array di oggetti Camera.Face.

Un'istanza di classe Camera.Face fornisce varie informazioni sul volto rilevato, tra cui:

  • Un elemento Rect che specifica i limiti del volto rispetto al campo visivo corrente della videocamera
  • Un numero intero compreso tra 1 e 100 che indica il grado di sicurezza del sistema che l'oggetto sia un volto umano
  • Un ID univoco che ti consente di monitorare più volti
  • Diversi oggetti Point che indicano dove si trovano gli occhi e la bocca

Nota: il rilevamento dei volti potrebbe non essere supportato su alcuni dispositivi, quindi devi verificarlo chiamando getMaxNumDetectedFaces() e assicurarti che il valore restituito sia maggiore di zero. Inoltre, alcuni dispositivi potrebbero non supportare l'identificazione di occhi e bocca, nel qual caso, i campi nell'oggetto Camera.Face saranno nulli.

Aree di messa a fuoco e misurazione

Le app della fotocamera ora possono controllare le aree utilizzate dalla fotocamera per la messa a fuoco e per la misurazione del bilanciamento del bianco e dell'esposizione automatica. Entrambe le funzionalità utilizzano la nuova classe Camera.Area per specificare l'area dell'inquadratura corrente della videocamera che deve essere messa a fuoco o a consumo. Un'istanza della classe Camera.Area definisce i limiti dell'area con un Rect e il peso dell'area, che rappresenta il livello di importanza dell'area rispetto alle altre aree prese in considerazione, con un numero intero.

Prima di impostare un'area di messa a fuoco o un'area di misurazione, devi chiamare rispettivamente getMaxNumFocusAreas() o getMaxNumMeteringAreas(). Se il valore restituito restituisce zero, il dispositivo non supporta la funzionalità corrispondente.

Per specificare le aree di messa a fuoco o di misurazione da utilizzare, chiama setFocusAreas() o setMeteringAreas(). Ciascuno esegue un List di Camera.Area oggetti che indicano le aree da considerare per la messa a fuoco o la misurazione. Ad esempio, potresti implementare una funzionalità che permette all'utente di impostare l'area di messa a fuoco toccando un'area dell'anteprima, che puoi poi tradurre in un oggetto Camera.Area e richiedere che la fotocamera metta a fuoco quell'area della scena. La messa a fuoco o l'esposizione in quell'area vengono continuamente aggiornate man mano che la scena cambia.

Messa a fuoco automatica continua per le foto

Ora puoi attivare la messa a fuoco automatica continua (CAF) quando scatti le foto. Per attivare il CAF nell'app della fotocamera, passa FOCUS_MODE_CONTINUOUS_PICTURE a setFocusMode(). Quando vuoi scattare una foto, chiama il numero autoFocus(). Il tuo Camera.AutoFocusCallback riceve immediatamente un callback per indicare se è stato raggiunto lo stato attivo. Per riattivare il CAF dopo aver ricevuto la richiamata, devi chiamare il numero cancelAutoFocus().

Nota: la messa a fuoco automatica continua è supportata anche per l'acquisizione di video utilizzando FOCUS_MODE_CONTINUOUS_VIDEO, che è stato aggiunto nel livello API 9.

Altre funzionalità della fotocamera

  • Mentre registri un video, ora puoi chiamare il numero takePicture() per salvare una foto senza interrompere la sessione video. Prima di farlo, devi chiamare isVideoSnapshotSupported() per assicurarti che l'hardware lo supporti.
  • Ora puoi bloccare l'esposizione automatica e il bilanciamento del bianco con i criteri setAutoExposureLock() e setAutoWhiteBalanceLock() per evitare che queste proprietà vengano modificate.
  • Ora puoi chiamare il numero setDisplayOrientation() mentre è in corso l'anteprima della fotocamera. In precedenza, potevi richiamare solo prima di avviare l'anteprima, ma ora puoi modificare l'orientamento in qualsiasi momento.

Intent di trasmissione videocamera

  • Camera.ACTION_NEW_PICTURE: indica che l'utente ha scattato una nuova foto. L'app Fotocamera integrata richiama questa trasmissione dopo aver scattato una foto e anche le app fotocamera di terze parti dovrebbero trasmettere questo intento dopo aver scattato una foto.
  • Camera.ACTION_NEW_VIDEO: indica che l'utente ha acquisito un nuovo video. L'app Fotocamera integrata richiama questa trasmissione dopo la registrazione di un video e anche le app della fotocamera di terze parti devono trasmettere questo intento dopo aver acquisito un video.

Android Beam (NDEF Push con NFC)

Android Beam è una nuova funzione NFC che consente di inviare messaggi NDEF da un dispositivo all'altro (un processo noto anche come "NDEF Push"). Il trasferimento di dati viene avviato quando due dispositivi Android che supportano Android Beam sono vicini (circa 4 cm), in genere con la schiena che si tocca. I dati all'interno del messaggio NDEF possono contenere tutti i dati che vuoi condividere tra i dispositivi. Ad esempio, l'app Persone condivide i contatti, YouTube condivide i video e il browser condivide gli URL tramite Android Beam.

Per trasmettere dati tra dispositivi che utilizzano Android Beam, devi creare un NdefMessage contenente le informazioni che vuoi condividere quando la tua attività è in primo piano. Devi poi passare NdefMessage al sistema in uno dei due seguenti modi:

Se vuoi eseguire un codice specifico dopo che il sistema ha consegnato il messaggio NDEF all'altro dispositivo, puoi implementare NfcAdapter.OnNdefPushCompleteCallback e impostarlo con setNdefPushCompleteCallback(). Il sistema chiamerà quindi onNdefPushComplete() alla consegna del messaggio.

Sul dispositivo ricevente, il sistema invia messaggi push NDEF in modo simile ai normali tag NFC. Il sistema richiama un intent con l'azione ACTION_NDEF_DISCOVERED per avviare un'attività, con un URL o un tipo MIME impostato in base al primo NdefRecord nel NdefMessage. Per l'attività a cui vuoi rispondere, puoi dichiarare i filtri per intent per gli URL o i tipi MIME che interessano la tua app. Per ulteriori informazioni su Tag Dispatch, consulta la guida per gli sviluppatori NFC.

Se vuoi che NdefMessage trasmetta un URI, puoi usare il metodo di convenienza createUri per creare un nuovo NdefRecord in base a una stringa o a un oggetto Uri. Se l'URI è un formato speciale che vuoi che l'applicazione riceva anche durante un evento Android Beam, devi creare un filtro di intent per la tua attività utilizzando lo stesso schema URI per ricevere il messaggio NDEF in arrivo.

Devi anche passare un "record app Android" con NdefMessage per garantire che l'applicazione gestisca il messaggio NDEF in arrivo, anche se altre applicazioni filtrano per la stessa azione intent. Puoi creare un record di applicazione Android chiamando createApplicationRecord() e passando il nome del pacchetto dell'applicazione. Quando l'altro dispositivo riceve il messaggio NDEF con il record dell'applicazione e più applicazioni contengono attività che gestiscono l'intent specificato, il sistema consegna sempre il messaggio all'attività nell'applicazione (in base al record dell'applicazione corrispondente). Se l'applicazione non è installata sul dispositivo di destinazione, il sistema utilizza il record dell'applicazione Android per avviare Google Play e indirizzare l'utente all'applicazione per installarla.

Se l'applicazione non utilizza le API NFC per eseguire i messaggi push NDEF, Android offre un comportamento predefinito: quando l'applicazione è in primo piano su un dispositivo e Android Beam viene richiamato su un altro dispositivo Android, l'altro dispositivo riceve un messaggio NDEF con un record di applicazione Android che identifica l'applicazione. Se l'applicazione è installata sul dispositivo ricevente, il sistema la avvia; in caso contrario, Google Play si apre e l'utente viene indirizzato alla tua applicazione per installarla.

Puoi leggere ulteriori informazioni su Android Beam e su altre funzioni NFC nella guida per gli sviluppatori Nozioni di base su NFC. Per alcuni esempi di codice che utilizzano Android Beam, consulta la demo di Android Beam.

Wi-Fi P2P

Android ora supporta le connessioni Wi-Fi peer-to-peer (P2P) tra dispositivi con piattaforma Android e altri tipi di dispositivi (in conformità con il programma di certificazione Wi-Fi DirectTM di Wi-Fi Alliance) senza hotspot o connessione a internet. Il framework Android fornisce un insieme di API Wi-Fi P2P che ti consentono di rilevare e connetterti ad altri dispositivi quando ciascuno supporta il Wi-Fi P2P, quindi di comunicare tramite una connessione veloce su distanze molto più lunghe di una connessione Bluetooth.

Un nuovo pacchetto, android.net.wifi.p2p, contiene tutte le API per eseguire connessioni peer-to-peer con il Wi-Fi. La classe principale con cui devi lavorare è WifiP2pManager, che puoi acquisire chiamando getSystemService(WIFI_P2P_SERVICE). Il WifiP2pManager include API che consentono di:

  • Inizializza la tua applicazione per le connessioni P2P chiamando initialize()
  • Scopri i dispositivi nelle vicinanze chiamando il numero discoverPeers()
  • Avvia una connessione P2P chiamando il numero connect()
  • E altro ancora

Sono necessarie anche molte altre interfacce e classi, ad esempio:

  • L'interfaccia WifiP2pManager.ActionListener consente di ricevere callback quando un'operazione come il rilevamento dei peer o la connessione ai peer ha esito positivo o negativo.
  • L'interfaccia WifiP2pManager.PeerListListener ti consente di ricevere informazioni sui peer rilevati. Il callback fornisce un WifiP2pDeviceList, da cui puoi recuperare un oggetto WifiP2pDevice per ogni dispositivo nel raggio d'azione e ottenere informazioni quali nome, indirizzo, tipo di dispositivo, configurazioni WPS supportate dal dispositivo e altro ancora.
  • L'interfaccia WifiP2pManager.GroupInfoListener consente di ricevere informazioni su un gruppo P2P. Il callback fornisce un oggetto WifiP2pGroup, che fornisce informazioni sul gruppo come il proprietario, il nome della rete e la passphrase.
  • dell'interfaccia di WifiP2pManager.ConnectionInfoListener ti consente di ricevere informazioni sulla connessione attuale. Il callback fornisce un oggetto WifiP2pInfo, che contiene informazioni ad esempio se è stato formato un gruppo e chi è il proprietario del gruppo.

Per poter utilizzare le API Wi-Fi P2P, la tua app deve richiedere le seguenti autorizzazioni utente:

  • ACCESS_WIFI_STATE
  • CHANGE_WIFI_STATE
  • INTERNET (anche se la tua app non si connette tecnicamente a internet, la comunicazione con peer P2P Wi-Fi tramite socket Java standard richiede l'autorizzazione a internet).

Il sistema Android trasmette anche diverse azioni durante determinati eventi Wi-Fi P2P:

Per saperne di più, consulta la documentazione di WifiP2pManager. Guarda anche l'applicazione di esempio Demo Wi-Fi P2P.

Dispositivi Bluetooth per la salute

Android ora supporta i dispositivi Bluetooth Health Profile, che ti consentono di creare applicazioni che utilizzano il Bluetooth per comunicare con dispositivi per la salute che supportano il Bluetooth, come misuratori del battito cardiaco, misuratori del sangue, termometri e bilance.

Analogamente alle cuffie normali e ai dispositivi con profilo A2DP, devi chiamare getProfileProxy() con un tipo di profilo BluetoothProfile.ServiceListener e HEALTH per stabilire una connessione con l'oggetto proxy del profilo.

Una volta acquisito il proxy del Profilo di salute (l'oggetto BluetoothHealth), la connessione e la comunicazione con dispositivi sanitari associati richiedono le seguenti nuove classi Bluetooth:

  • BluetoothHealthCallback: devi estendere questa classe e implementare i metodi di callback per ricevere aggiornamenti sulle modifiche dello stato di registrazione e dello stato del canale Bluetooth.
  • BluetoothHealthAppConfiguration: durante i callback al tuo BluetoothHealthCallback, riceverai un'istanza di questo oggetto, che fornisce informazioni di configurazione sul dispositivo Bluetooth disponibile, che devi usare per eseguire varie operazioni, come avviare e terminare connessioni con le API BluetoothHealth.

Per ulteriori informazioni sull'uso del Profilo dell'integrità Bluetooth, consulta la documentazione di BluetoothHealth.

Accessibilità

Android 4.0 migliora l'accessibilità per gli utenti con disabilità visiva con la nuova modalità Esplora al tocco e le API estese che consentono di fornire ulteriori informazioni sulla visualizzazione dei contenuti o di sviluppare servizi di accessibilità avanzati.

Modalità Esplora al tocco

Gli utenti ipovedenti possono ora esplorare lo schermo toccando e trascinando un dito sullo schermo per ascoltare le descrizioni vocali dei contenuti. Poiché la modalità Esplora al tocco funziona come un cursore virtuale, consente agli screen reader di identificare il testo descrittivo come fanno gli screen reader quando l'utente naviga con un D-pad o una trackball, leggendo le informazioni fornite da android:contentDescription e setContentDescription() durante un evento di passaggio del mouse simulato. Tieni quindi presente che ti ricordiamo che devi fornire un testo descrittivo per le viste nella tua applicazione, in particolare per ImageButton, EditText, ImageView e altri widget che potrebbero non contenere naturalmente testo descrittivo.

Accessibilità per le visualizzazioni

Per migliorare le informazioni disponibili per i servizi di accessibilità come gli screen reader, puoi implementare nuovi metodi di callback per gli eventi di accessibilità nei componenti View personalizzati.

È importante notare innanzitutto che il comportamento del metodo sendAccessibilityEvent() è cambiato in Android 4.0. Come con la versione precedente di Android, quando un utente attiva i servizi di accessibilità sul dispositivo e si verifica un evento di input, ad esempio un clic o il passaggio del mouse, la rispettiva visualizzazione riceve una notifica con una chiamata a sendAccessibilityEvent(). In precedenza, l'implementazione di sendAccessibilityEvent() avrebbe inizializzato AccessibilityEvent e inviato a AccessibilityManager. Il nuovo comportamento prevede alcuni metodi di callback aggiuntivi che consentono alla visualizzazione e ai relativi elementi padre di aggiungere ulteriori informazioni contestuali all'evento:

  1. Quando richiamati, i metodi sendAccessibilityEvent() e sendAccessibilityEventUnchecked() rimandano a onInitializeAccessibilityEvent().

    Le implementazioni personalizzate di View potrebbero voler implementare onInitializeAccessibilityEvent() per collegare ulteriori informazioni sull'accessibilità a AccessibilityEvent, ma dovrebbero anche chiamare la super implementazione per fornire informazioni predefinite come la descrizione standard dei contenuti, l'indice degli elementi e altro ancora. In questo callback, però, non devi aggiungere altro contenuto di testo, cosa che accadrà.

  2. Una volta inizializzato, se l'evento è uno dei vari tipi che devono essere compilati con informazioni di testo, la vista riceve una chiamata a dispatchPopulateAccessibilityEvent(), che rimanda al callback onPopulateAccessibilityEvent().

    Le implementazioni personalizzate di View in genere devono implementare onPopulateAccessibilityEvent() per aggiungere ulteriori contenuti di testo a AccessibilityEvent se il testo android:contentDescription manca o è insufficiente. Per aggiungere altre descrizioni di testo a AccessibilityEvent, chiama il numero getText().add().

  3. A questo punto, View passa l'evento oltre la gerarchia delle viste richiamando requestSendAccessibilityEvent() nella vista principale. Ogni vista padre ha quindi la possibilità di aumentare le informazioni sull'accessibilità aggiungendo un AccessibilityRecord, fino a raggiungere la vista principale, il che invia l'evento a AccessibilityManager con sendAccessibilityEvent().

Oltre ai nuovi metodi descritti sopra, che sono utili quando si estende la classe View, puoi anche intercettare questi callback eventi su qualsiasi View estendendo AccessibilityDelegate e impostandolo nella visualizzazione con setAccessibilityDelegate(). In questo caso, ogni metodo di accessibilità nella vista reindirizza la chiamata al metodo corrispondente nel delegato. Ad esempio, quando la vista riceve una chiamata a onPopulateAccessibilityEvent(), la passa allo stesso metodo in View.AccessibilityDelegate. Tutti i metodi non gestiti dal delegato vengono restituiti direttamente alla visualizzazione per il comportamento predefinito. In questo modo puoi eseguire l'override solo dei metodi necessari per una determinata visualizzazione senza estendere la classe View.

Se vuoi mantenere la compatibilità con versioni di Android precedenti alla 4.0, supportando al contempo le nuove API di accessibilità, puoi utilizzare la versione più recente della libreria di assistenza v4 (in Pacchetto di compatibilità, r4) utilizzando un insieme di classi di utilità che forniscono le nuove API di accessibilità in una progettazione compatibile con le versioni precedenti.

Servizi di accessibilità

Se stai sviluppando un servizio di accessibilità, le informazioni sui vari eventi di accessibilità sono state notevolmente ampliate per consentire agli utenti feedback di accessibilità più avanzati. In particolare, gli eventi vengono generati in base alla composizione delle viste, fornendo migliori informazioni di contesto e consentendo ai servizi di accessibilità di attraversare le gerarchie delle viste per ottenere ulteriori informazioni sulle viste e gestire casi speciali.

Se stai sviluppando un servizio di accessibilità (ad esempio uno screen reader), puoi accedere a ulteriori informazioni sui contenuti e attraversare le gerarchie delle visualizzazioni con la seguente procedura:

  1. Quando ricevi un AccessibilityEvent da un'applicazione, chiama AccessibilityEvent.getRecord() per recuperare un AccessibilityRecord specifico (potrebbero esserci diversi record associati all'evento).
  2. Da AccessibilityEvent o da un singolo AccessibilityRecord, puoi chiamare getSource() per recuperare un oggetto AccessibilityNodeInfo.

    Un AccessibilityNodeInfo rappresenta un singolo nodo dei contenuti delle finestre in un formato che consente di eseguire query sulle informazioni di accessibilità relative a quel nodo. L'oggetto AccessibilityNodeInfo restituito da AccessibilityEvent descrive l'origine evento, mentre l'origine da un AccessibilityRecord descrive il predecessore dell'origine evento.

  3. Con AccessibilityNodeInfo puoi eseguire query sullo stesso, chiamare getParent() o getChild() per attraversare la gerarchia delle viste e persino aggiungere viste secondarie al nodo.

Affinché l'applicazione possa pubblicarsi nel sistema come servizio di accessibilità, deve dichiarare un file di configurazione XML corrispondente a AccessibilityServiceInfo. Per ulteriori informazioni sulla creazione di un servizio di accessibilità, consulta le pagine AccessibilityService e SERVICE_META_DATA per informazioni sulla configurazione XML.

Altre API per l'accessibilità

Se ti interessa conoscere lo stato di accessibilità del dispositivo, AccessibilityManager ha alcune nuove API, ad esempio:

Servizi di controllo ortografico

Un nuovo framework di controllo ortografico consente alle app di creare controlli ortografici in modo simile al framework dei metodi di input (per gli IME). Per creare una nuova funzione di controllo ortografico, devi implementare un servizio che estenda SpellCheckerService ed estenda la classe SpellCheckerService.Session per fornire suggerimenti ortografici basati sul testo fornito dai metodi di callback dell'interfaccia. Nei metodi di callback SpellCheckerService.Session, devi restituire i suggerimenti di ortografia come oggetti SuggestionsInfo.

Le applicazioni con un servizio di controllo ortografico devono dichiarare l'autorizzazione BIND_TEXT_SERVICE come richiesto dal servizio. Il servizio deve anche dichiarare un filtro per intent con <action android:name="android.service.textservice.SpellCheckerService" /> come azione dell'intent e deve includere un elemento <meta-data> che dichiari le informazioni di configurazione per il controllo ortografico.

Per esempi di codice, consulta l'app Servizio di controllo ortografico e l'app Client di controllo ortografico di esempio.

Motori di sintesi vocale

Le API di sintesi vocale (TTS) di Android sono state notevolmente estese per consentire alle applicazioni di implementare più facilmente motori di sintesi vocale personalizzati, mentre le applicazioni che vogliono utilizzare un motore TTS dispongono di un paio di nuove API per la selezione di un motore.

Utilizzo di motori di sintesi vocale

Nelle versioni precedenti di Android, potevi utilizzare la classe TextToSpeech per eseguire operazioni di sintesi vocale (TTS) usando il motore TTS fornito dal sistema o impostare un motore personalizzato utilizzando setEngineByPackageName(). In Android 4.0, il metodo setEngineByPackageName() è stato ritirato e ora puoi specificare il motore da utilizzare con un nuovo costruttore TextToSpeech che accetti il nome di pacchetto di un motore TTS.

Puoi anche eseguire query sui motori di sintesi vocale disponibili con getEngines(). Questo metodo restituisce un elenco di oggetti TextToSpeech.EngineInfo, che includono metadati come l'icona, l'etichetta e il nome del pacchetto del motore.

Creazione di motori di sintesi vocale

In precedenza, i motori personalizzati richiedevano che il motore venisse creato utilizzando un file di intestazione nativo non documentato. In Android 4.0, è disponibile una serie completa di API framework per la creazione di motori TTS.

La configurazione di base richiede un'implementazione di TextToSpeechService che risponda all'intent INTENT_ACTION_TTS_SERVICE. Il lavoro principale per un motore TTS avviene durante il callback onSynthesizeText() in un servizio che estende TextToSpeechService. Questo metodo fornisce due oggetti:

  • SynthesisRequest: contiene vari dati, tra cui il testo da sintetizzare, le impostazioni internazionali, la velocità della voce e il tono della voce.
  • SynthesisCallback: è l'interfaccia tramite la quale il motore di sintesi vocale fornisce i dati vocali risultanti come audio in streaming. Innanzitutto il motore deve chiamare start() per indicare che è pronto a fornire l'audio, quindi chiamare audioAvailable(), passando i dati audio in un buffer di byte. Una volta che il motore ha trasmesso tutto l'audio attraverso il buffer, chiama done().

Ora che il framework supporta un'API vera per la creazione di motori TTS, il supporto per l'implementazione del codice nativo è stato rimosso. Cerca un post del blog su un livello di compatibilità che puoi usare per convertire i vecchi motori di sintesi vocale nel nuovo framework.

Per un motore di sintesi vocale di esempio che utilizza le nuove API, vedi l'app di esempio Text To Speech Engine.

Utilizzo della rete

Android 4.0 offre agli utenti una visibilità precisa sulla quantità di dati di rete utilizzati dalle loro applicazioni. L'app Impostazioni fornisce controlli che consentono agli utenti di gestire l'impostazione di limiti per l'utilizzo dei dati di rete e persino di disattivare l'uso dei dati in background per singole app. Per evitare che gli utenti disattivino l'accesso della tua app ai dati in background, devi sviluppare strategie per utilizzare la connessione dati in modo efficiente e regolare l'utilizzo in base al tipo di connessione disponibile.

Se la tua applicazione esegue molte transazioni di rete, devi fornire impostazioni che consentano agli utenti di controllare le abitudini di utilizzo dei dati dell'app, ad esempio la frequenza di sincronizzazione dei dati, se eseguire caricamenti/download solo quando il Wi-Fi è connesso, se utilizzare i dati in roaming e così via. Con questi controlli a loro disposizione è molto meno probabile che gli utenti disattivino l'accesso dell'app ai dati quando stanno per raggiungere i limiti, perché possono invece usare il controllo preciso della tua app. Se fornisci un'attività di preferenza con queste impostazioni, devi includere nel file manifest la dichiarazione di un filtro per intent per l'azione ACTION_MANAGE_NETWORK_USAGE. Ecco alcuni esempi:

<activity android:name="DataPreferences" android:label="@string/title_preferences">
    <intent-filter>
       <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
       <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Questo filtro per intent indica al sistema che si tratta dell'attività che controlla l'utilizzo dei dati da parte della tua applicazione. Pertanto, quando l'utente controlla la quantità di dati utilizzati dalla tua app dall'app Impostazioni, è disponibile un pulsante "Visualizza impostazioni applicazione" che avvia la tua attività di preferenza in modo che l'utente possa perfezionare la quantità di dati utilizzata dall'app.

Tieni inoltre presente che getBackgroundDataSetting() ora è deprecato e restituisce sempre true. Usa invece getActiveNetworkInfo(). Prima di tentare qualsiasi transazione di rete, devi sempre chiamare getActiveNetworkInfo() per ottenere il NetworkInfo che rappresenta la rete attuale ed eseguire una query su isConnected() per verificare se il dispositivo dispone di una connessione. Puoi quindi controllare altre proprietà della connessione, ad esempio se il dispositivo è in roaming o è connesso al Wi-Fi.

Enterprise

Android 4.0 espande le funzionalità per le applicazioni aziendali con le funzionalità elencate di seguito.

Servizi VPN

La nuova VpnService consente alle applicazioni di creare una propria VPN (Virtual Private Network, rete privata virtuale), in esecuzione come Service. Un servizio VPN crea un'interfaccia per una rete virtuale con le proprie regole di indirizzo e routing ed esegue tutte le operazioni di lettura e scrittura con un descrittore di file.

Per creare un servizio VPN, utilizza VpnService.Builder, che ti consente di specificare l'indirizzo di rete, il server DNS, la route di rete e altro ancora. Al termine, puoi stabilire l'interfaccia chiamando establish(), che restituisce un ParcelFileDescriptor.

Dal momento che un servizio VPN può intercettare i pacchetti, ci sono implicazioni relative alla sicurezza. Di conseguenza, se implementi VpnService, il servizio deve richiedere BIND_VPN_SERVICE per garantire che solo il sistema possa eseguire l'associazione (solo al sistema viene concessa questa autorizzazione, le app non possono richiederla). Per utilizzare il servizio VPN, gli utenti devono abilitarlo manualmente nelle impostazioni di sistema.

Criteri relativi ai dispositivi

Le applicazioni che gestiscono le limitazioni relative ai dispositivi ora possono disattivare la videocamera utilizzando setCameraDisabled() e la proprietà USES_POLICY_DISABLE_CAMERA (applicata con un elemento <disable-camera /> nel file di configurazione dei criteri).

Gestione dei certificati

La nuova classe KeyChain fornisce API che consentono di importare e accedere ai certificati nell'archivio chiavi di sistema. I certificati semplificano l'installazione dei certificati client (per convalidare l'identità dell'utente) e dei certificati delle autorità di certificazione (per verificare l'identità del server). Applicazioni come browser web o client di posta possono accedere ai certificati installati per autenticare gli utenti sui server. Per ulteriori informazioni, consulta la documentazione di KeyChain.

Sensori del dispositivo

In Android 4.0 sono stati aggiunti due nuovi tipi di sensori:

  • TYPE_AMBIENT_TEMPERATURE: un sensore di temperatura che fornisce la temperatura ambiente (ambiente) in gradi Celsius.
  • TYPE_RELATIVE_HUMIDITY: un sensore di umidità che fornisce l'umidità relativa ambientale (ambiente) in percentuale.

Se un dispositivo ha entrambi i sensori TYPE_AMBIENT_TEMPERATURE e TYPE_RELATIVE_HUMIDITY, puoi utilizzarli per calcolare il punto di rugiada e l'umidità assoluta.

Il precedente sensore di temperatura, TYPE_TEMPERATURE, è stato ritirato. Dovresti usare il sensore TYPE_AMBIENT_TEMPERATURE.

Inoltre, i tre sensori sintetici di Android sono stati notevolmente migliorati, ora presentano una latenza minore e un output più fluido. Questi sensori includono il sensore di gravità (TYPE_GRAVITY), il sensore del vettore di rotazione (TYPE_ROTATION_VECTOR) e il sensore di accelerazione lineare (TYPE_LINEAR_ACCELERATION). I sensori migliorati si basano sul sensore del giroscopio per migliorarne l'output, pertanto i sensori vengono visualizzati solo sui dispositivi dotati di un giroscopio.

Barra delle azioni

L'oggetto ActionBar è stato aggiornato in modo da supportare diversi nuovi comportamenti. Ma soprattutto, il sistema gestisce agevolmente le dimensioni e la configurazione della barra delle azioni quando viene eseguita su schermi più piccoli per offrire un'esperienza utente ottimale su schermi di tutte le dimensioni. Ad esempio, quando lo schermo è stretto (come quando un telefono è in orientamento verticale), le schede di navigazione della barra delle azioni vengono visualizzate in una "barra in pila", che viene visualizzata direttamente sotto la barra principale. Puoi anche attivare una "barra delle azioni divisa", che posiziona tutte le attività in una barra separata nella parte inferiore dello schermo quando lo schermo è stretto.

Barra delle azioni divisa

Se la barra delle azioni include più attività, non tutte potranno essere inserite nella barra delle azioni su uno schermo stretto, pertanto il sistema ne inserirà altre nel menu extra. Tuttavia, Android 4.0 consente di attivare la "barra delle azioni divisa", in modo che più attività possano essere visualizzate sullo schermo in una barra separata nella parte inferiore dello schermo. Per attivare la barra delle azioni divisa, aggiungi android:uiOptions con "splitActionBarWhenNarrow" al tag <application> o ai singoli tag <activity> nel file manifest. Quando questa opzione è attiva, quando la schermata è stretta, il sistema aggiungerà un'altra barra nella parte inferiore dello schermo per tutte le attività (nella barra di azione principale non verrà visualizzata alcuna attività).

Se vuoi utilizzare le schede di navigazione fornite dalle API ActionBar.Tab, ma non hai bisogno della barra delle azioni principale in alto (vuoi che vengano visualizzate solo le schede nella parte superiore), attiva la barra delle azioni divisa come descritto sopra e chiama anche setDisplayShowHomeEnabled(false) per disattivare l'icona dell'applicazione nella barra delle azioni. Se non è rimasto nulla nella barra delle azioni principale, scompare; rimangono solo le schede di navigazione in alto e le attività nella parte inferiore dello schermo.

Stili della barra delle azioni

Se vuoi applicare stili personalizzati alla barra delle azioni, puoi utilizzare le nuove proprietà di stile backgroundStacked e backgroundSplit per applicare un disegno o un colore di sfondo rispettivamente alla barra in pila e alla barra divisa. Puoi anche impostare questi stili in tempo di esecuzione con setStackedBackgroundDrawable() e setSplitBackgroundDrawable().

Provider di azioni

La nuova classe ActionProvider consente di creare un gestore specializzato per le attività. Un provider di azioni può definire una visualizzazione delle azioni, un comportamento predefinito delle azioni e un sottomenu per ogni attività a cui è associato. Quando vuoi creare un'attività con comportamenti dinamici (ad esempio una visualizzazione azione variabile, un'azione predefinita o un sottomenu), l'estensione di ActionProvider è una soluzione adeguata per creare un componente riutilizzabile, invece di gestire le varie trasformazioni dell'attività nel frammento o nell'attività.

Ad esempio, ShareActionProvider è un'estensione di ActionProvider che facilita un'azione di "condivisione" dalla barra delle azioni. Anziché utilizzare un'attività tradizionale che richiama l'intent ACTION_SEND, puoi utilizzare questo provider di azioni per presentare una visualizzazione dell'azione con un elenco a discesa di applicazioni che gestiscono l'intent ACTION_SEND. Quando l'utente seleziona un'applicazione da utilizzare per l'azione, ShareActionProvider memorizza la selezione e la inserisce nella visualizzazione azione per accedere più rapidamente alla condivisione con l'app.

Per dichiarare un fornitore di azioni per un'attività, includi l'attributo android:actionProviderClass nell'elemento <item> del menu opzioni dell'attività, con il nome della classe del fornitore di azioni come valore. Ecco alcuni esempi:

<item android:id="@+id/menu_share"
      android:title="Share"
      android:showAsAction="ifRoom"
      android:actionProviderClass="android.widget.ShareActionProvider" />

Nel metodo di callback onCreateOptionsMenu() dell'attività, recupera un'istanza del provider di azioni dalla voce di menu e imposta l'intent:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options, menu)
    val shareActionProvider = menu.findItem(R.id.menu_share)?.actionProvider as? ShareActionProvider
    // Set the share intent of the share action provider.
    shareActionProvider?.setShareIntent(createShareIntent())
    ...
    return super.onCreateOptionsMenu(menu)
}

Java

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.options, menu);
    ShareActionProvider shareActionProvider =
          (ShareActionProvider) menu.findItem(R.id.menu_share).getActionProvider();
    // Set the share intent of the share action provider.
    shareActionProvider.setShareIntent(createShareIntent());
    ...
    return super.onCreateOptionsMenu(menu);
}

Per un esempio utilizzando ShareActionProvider, consulta ActionBarShareActionProviderActivity in ApiDemos.

Visualizzazioni comprimibili delle azioni

Le attività che forniscono una visualizzazione azione ora possono passare dallo stato di visualizzazione azione allo stato tradizionale dell'attività. In precedenza, solo la compressione SearchView supportava quando veniva utilizzata come visualizzazione azioni, ma ora puoi aggiungere una visualizzazione azione per qualsiasi attività e passare dallo stato espanso (la visualizzazione azione è visibile) a quello compresso (l'elemento azione è visibile).

Per dichiarare che un'attività che contiene una visualizzazione azione può essere comprimibile, includi il flag “collapseActionView" nell'attributo android:showAsAction dell'elemento <item> nel file XML del menu.

Per ricevere callback quando una visualizzazione delle azioni passa dalla visualizzazione espansa a quella compressa, registra un'istanza di MenuItem.OnActionExpandListener con il rispettivo MenuItem chiamando setOnActionExpandListener(). In genere, dovresti farlo durante il callback onCreateOptionsMenu().

Per controllare una visualizzazione delle azioni comprimibili, puoi chiamare collapseActionView() e expandActionView() sul rispettivo MenuItem.

Quando crei una visualizzazione delle azioni personalizzate, puoi anche implementare la nuova interfaccia CollapsibleActionView per ricevere i callback quando la visualizzazione viene espansa e compressa.

Altre API per la barra delle azioni

  • setHomeButtonEnabled() consente di specificare se l'icona/il logo si comporta come un pulsante per andare alla schermata Home o verso l'alto (passa il valore "true" per fare in modo che si comporti come un pulsante).
  • setIcon() e setLogo() consentono di definire l'icona o il logo della barra delle azioni al momento dell'attivazione.
  • Fragment.setMenuVisibility() consente di attivare o disattivare la visibilità delle voci del menu opzioni dichiarate dal frammento. Questo è utile se il frammento è stato aggiunto all'attività, ma non è visibile, quindi le voci di menu dovrebbero essere nascoste.
  • FragmentManager.invalidateOptionsMenu() consente di invalidare il menu opzioni dell'attività durante vari stati del ciclo di vita dei frammenti in cui l'utilizzo del metodo equivalente di Activity potrebbe non essere disponibile.

Interfaccia utente e visualizzazioni

Android 4.0 introduce una serie di nuove visualizzazioni e altri componenti dell'interfaccia utente.

Layout griglia

GridLayout è un nuovo gruppo di visualizzazioni che posiziona le visualizzazioni secondarie in una griglia rettangolare. A differenza di TableLayout, GridLayout si basa su una gerarchia piatta e non utilizza viste intermedie, come le righe di tabella, per fornire la struttura. Gli elementi secondari specificano invece quali righe e colonne devono occupare (le celle possono estendersi su più righe e/o colonne) e, per impostazione predefinita, sono disposte in sequenza su tutte le righe e le colonne della griglia. L'orientamento GridLayout determina se gli elementi secondari sequenziali sono disposti orizzontalmente o verticalmente per impostazione predefinita. Lo spazio tra gli elementi secondari può essere specificato utilizzando le istanze della nuova vista Space o impostando i relativi parametri di margine sugli elementi secondari.

Consulta ApiDemos per esempi che utilizzano GridLayout.

Visualizzazione texture

TextureView è una nuova visualizzazione che ti consente di mostrare uno stream di contenuti, ad esempio un video o una scena OpenGL. Sebbene simile a SurfaceView, TextureView è univoco in quanto si comporta come una visualizzazione normale, anziché creare una finestra separata, quindi puoi considerarla come qualsiasi altro oggetto View. Ad esempio, puoi applicare trasformazioni, animarla utilizzando ViewPropertyAnimator o regolarne l'opacità con setAlpha().

Tieni presente che TextureView funziona solo all'interno di una finestra con accelerazione hardware.

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

Cambia widget

Il nuovo widget Switch è un pulsante di attivazione/disattivazione a due stati che gli utenti possono trascinare da un lato o dall'altro (o semplicemente toccare) per passare da un'opzione all'altra.

Puoi utilizzare gli attributi android:textOn e android:textOff per specificare il testo da visualizzare sull'opzione quando questa è attiva e disattivata. L'attributo android:text consente inoltre di applicare un'etichetta accanto all'opzione.

Per un esempio sull'uso dei sensori, consulta il file di layout switches.xml e la relativa attività Switches (Cambio).

Android 3.0 ha introdotto PopupMenu per creare brevi menu contestuali che vengono visualizzati in corrispondenza di un punto di ancoraggio da te specificato (di solito nel punto dell'elemento selezionato). Android 4.0 estende PopupMenu con un paio di funzionalità utili:

Preferenze

Una nuova classe astratta TwoStatePreference funge da base per le preferenze che offrono un'opzione di selezione a due stati. Il nuovo SwitchPreference è un'estensione di TwoStatePreference che fornisce un widget Switch nella visualizzazione delle preferenze per consentire agli utenti di attivare o disattivare un'impostazione senza dover aprire una schermata o una finestra di dialogo di preferenza aggiuntiva. Ad esempio, l'applicazione Impostazioni utilizza un SwitchPreference per le impostazioni Wi-Fi e Bluetooth.

Temi di sistema

Il tema predefinito per tutte le applicazioni destinate ad Android 4.0 (impostando targetSdkVersion o minSdkVersion su “14" o versioni successive) ora è il tema "predefinito del dispositivo": Theme.DeviceDefault. Può trattarsi di un tema scuro Holo o di un tema scuro diverso definito dal dispositivo specifico.

Quando è installata la stessa versione di Android, la famiglia di temi Theme.Holo non cambierà da un dispositivo all'altro. Se applichi esplicitamente uno qualsiasi dei temi Theme.Holo alle tue attività, non ti preoccupare che il tema non cambierà su dispositivi diversi all'interno della stessa versione della piattaforma.

Se vuoi che la tua app si integri con il tema generale del dispositivo (ad esempio se diversi OEM forniscono temi predefiniti diversi per il sistema), devi applicare esplicitamente i temi della famiglia Theme.DeviceDefault.

Pulsante del menu Opzioni

A partire da Android 4.0, noterai che gli smartphone non richiedono più un pulsante hardware Menu. Tuttavia, non c'è motivo di preoccuparsi se la tua applicazione esistente fornisce un menu opzioni e prevede che sia presente un pulsante Menu. Per garantire che le app esistenti continuino a funzionare come previsto, il sistema fornisce un pulsante Menu sullo schermo per le app progettate per versioni precedenti di Android.

Per un'esperienza utente ottimale, le app nuove e aggiornate dovrebbero utilizzare ActionBar per fornire l'accesso alle voci di menu e impostare targetSdkVersion su "14" per sfruttare i comportamenti predefiniti del framework più recenti.

Controlli per la visibilità dell'interfaccia utente di sistema

Sin dagli albori di Android, il sistema ha gestito un componente dell'interfaccia utente noto come barra di stato, che risiede nella parte superiore dei dispositivi degli smartphone per fornire informazioni quali l'indicatore dell'operatore, l'ora, le notifiche e così via. Android 3.0 ha aggiunto la barra di sistema per i tablet, che si trova nella parte inferiore dello schermo, per fornire i controlli di navigazione del sistema (Home, Indietro e così via) nonché un'interfaccia per gli elementi tradizionalmente forniti dalla barra di stato. In Android 4.0, il sistema fornisce un nuovo tipo di UI di sistema chiamata barra di navigazione. Potresti considerare la barra di navigazione una versione perfezionata della barra di sistema progettata per gli smartphone: fornisce controlli di navigazione per i dispositivi che non hanno controparti hardware per la navigazione nel sistema, ma esclude l'interfaccia utente di notifica e i controlli delle impostazioni della barra di sistema. Un dispositivo che fornisce la barra di navigazione ha anche la barra di stato in alto.

Finora, puoi nascondere la barra di stato sugli smartphone utilizzando il flag FLAG_FULLSCREEN. In Android 4.0, le API che controllano la visibilità della barra di sistema sono state aggiornate per riflettere meglio il comportamento della barra di sistema e della barra di navigazione:

  • Il flag SYSTEM_UI_FLAG_LOW_PROFILE sostituisce il flag STATUS_BAR_HIDDEN. Se impostato, questo flag attiva la modalità "low profile" per la barra di sistema o la barra di navigazione. La luminosità dei pulsanti di navigazione è attenuata e anche gli altri elementi della barra di sistema vengono nascosti. L'attivazione di questa funzionalità è utile per creare giochi più coinvolgenti senza distrazioni per i pulsanti di navigazione del sistema.
  • Il flag SYSTEM_UI_FLAG_VISIBLE sostituisce il flag STATUS_BAR_VISIBLE per richiedere la visualizzazione della barra di sistema o della barra di navigazione.
  • SYSTEM_UI_FLAG_HIDE_NAVIGATION è un nuovo flag che richiede di nascondere completamente la barra di navigazione. Tieni presente che funziona solo per la barra di navigazione utilizzata da alcuni telefoni (non nasconde la barra di sistema sui tablet). La barra di navigazione torna alla visualizzazione non appena il sistema riceve l'input dell'utente. Di conseguenza, questa modalità è utile principalmente per la riproduzione di video o per altri casi in cui è necessario l'intero schermo, ma non è necessario l'input dell'utente.

Puoi impostare ciascuno di questi flag per la barra di sistema e la barra di navigazione chiamando setSystemUiVisibility() in qualsiasi vista della tua attività. Lo strumento di gestione delle finestre combina (OR insieme) tutti i flag di tutte le viste della finestra e li applica all'interfaccia utente di sistema purché la finestra sia attiva per l'input. Quando la finestra perde lo stato attivo dell'input (l'utente esce dall'app o viene visualizzata una finestra di dialogo), i flag non sono più attivi. Analogamente, se rimuovi queste visualizzazioni dalla gerarchia delle visualizzazioni, i relativi flag non verranno più applicati.

Per sincronizzare altri eventi della tua attività con modifiche di visibilità all'interfaccia utente di sistema (ad esempio, nascondere la barra delle azioni o altri controlli dell'interfaccia utente quando l'interfaccia utente di sistema si nasconde), devi registrare un View.OnSystemUiVisibilityChangeListener per ricevere una notifica quando la visibilità della barra di sistema o della barra di navigazione cambia.

Consulta la classe OverscanActivity per una dimostrazione delle diverse opzioni dell'interfaccia utente di sistema.

Framework di input

Android 4.0 aggiunge il supporto per gli eventi di passaggio del cursore e per i nuovi eventi relativi a stilo e pulsanti del mouse.

Eventi di passaggio del mouse

La classe View ora supporta eventi "al passaggio del mouse" per consentire interazioni più complete tramite l'uso di dispositivi puntatori (come un mouse o altri dispositivi che attivano un cursore sullo schermo).

Per ricevere eventi di passaggio del mouse su una vista, implementa View.OnHoverListener e registralo con setOnHoverListener(). Quando si verifica un evento di passaggio del mouse nella visualizzazione, il listener riceve una chiamata a onHover(), che fornisce il valore View che ha ricevuto l'evento e un MotionEvent che descrive il tipo di evento di passaggio del mouse che si è verificato. L'evento di passaggio del mouse può essere uno dei seguenti:

View.OnHoverListener deve restituire true da onHover() se gestisce l'evento di passaggio del mouse. Se l'ascoltatore restituisce false, l'evento di passaggio del mouse viene inviato alla vista principale come di consueto.

Se l'applicazione utilizza pulsanti o altri widget che cambiano aspetto in base allo stato corrente, ora puoi utilizzare l'attributo android:state_hovered in un elenco di stati disegnabile per fornire uno sfondo diverso da disegnare quando un cursore passa sopra la visualizzazione.

Per una dimostrazione dei nuovi eventi di passaggio del mouse, consulta la classe Hover in ApiDemos.

Eventi relativi a pulsanti del mouse e stilo

Android ora fornisce API per la ricezione di input da un dispositivo di input con stilo, ad esempio una periferica per tablet digitalizzatore o un touchscreen abilitato per stilo.

L'input dello stilo funziona in modo simile all'input del tocco o del mouse. Quando lo stilo è a contatto con il digitalizzatore, le applicazioni ricevono eventi tattili esattamente come quando si utilizza un dito per toccare il display. Quando lo stilo passa sopra il digitalizzatore, le applicazioni ricevono eventi di passaggio del mouse proprio come quando il puntatore del mouse viene spostato sul display quando non viene premuto alcun pulsante.

L'applicazione può distinguere tra input dito, mouse, stilo e gomma eseguendo una query sul "tipo di strumento" associato a ciascun puntatore in MotionEvent utilizzando getToolType(). I tipi di strumenti attualmente definiti sono: TOOL_TYPE_UNKNOWN, TOOL_TYPE_FINGER, TOOL_TYPE_MOUSE, TOOL_TYPE_STYLUS e TOOL_TYPE_ERASER. Se esegui una query sul tipo di strumento, l'applicazione può scegliere di gestire l'input dello stilo in modi diversi.

L'applicazione può anche eseguire query su quali pulsanti del mouse o dello stilo vengono premuti eseguendo una query sullo "stato del pulsante" di un MotionEvent utilizzando getButtonState(). Gli stati del pulsante attualmente definiti sono: BUTTON_PRIMARY, BUTTON_SECONDARY, BUTTON_TERTIARY, BUTTON_BACK e BUTTON_FORWARD. Per comodità, i pulsanti Indietro e Avanti del mouse vengono mappati automaticamente ai tasti KEYCODE_BACK e KEYCODE_FORWARD. L'applicazione può gestire questi tasti per supportare la navigazione in avanti e indietro basata sui pulsanti del mouse.

Oltre a misurare con precisione la posizione e la pressione di un contatto, alcuni dispositivi di input con stilo segnalano anche la distanza tra la punta dello stilo e il digitalizzatore, l'angolo di inclinazione dello stilo e l'angolo di orientamento dello stilo. La tua applicazione può eseguire query su queste informazioni utilizzando getAxisValue() con i codici degli assi AXIS_DISTANCE, AXIS_TILT e AXIS_ORIENTATION.

Per una dimostrazione dei tipi di strumenti, degli stati dei pulsanti e dei codici dei nuovi assi, consulta la classe TouchPaint in ApiDemos.

Proprietà

La nuova classe Property fornisce un modo rapido, efficiente e semplice per specificare una proprietà su qualsiasi oggetto che consente ai chiamanti di impostare/recuperare in modo generico i valori degli oggetti di destinazione. Consente inoltre la funzionalità di trasferimento dei riferimenti a campi/metodi e permette al codice di impostare/recuperare valori della proprietà senza conoscere i dettagli di quali sono i campi/metodi.

Ad esempio, se vuoi impostare il valore del campo bar sull'oggetto foo, in precedenza dovresti farlo:

Kotlin

foo.bar = value

Java

foo.bar = value;

Se vuoi chiamare il setter per un campo privato sottostante bar, devi eseguire questa procedura in precedenza:

Kotlin

foo.setBar(value)

Java

foo.setBar(value);

Tuttavia, se vuoi passare l'istanza foo e impostare un altro codice come valore bar, non c'è modo di farlo prima di Android 4.0.

Utilizzando la classe Property, puoi dichiarare un oggetto Property BAR nella classe Foo in modo da poter impostare il campo sull'istanza foo della classe Foo nel seguente modo:

Kotlin

BAR.set(foo, value)

Java

BAR.set(foo, value);

La classe View ora utilizza la classe Property per consentirti di impostare vari campi, ad esempio le proprietà di trasformazione aggiunte in Android 3.0 (ROTATION, ROTATION_X, TRANSLATION_X e così via).

La classe ObjectAnimator utilizza anche la classe Property, quindi puoi creare un ObjectAnimator con Property, che è più veloce, più efficiente e più sicuro per i tipi di testo rispetto all'approccio basato su stringhe.

Accelerazione hardware

A partire da Android 4.0, l'accelerazione hardware per tutte le finestre è abilitata per impostazione predefinita se la tua applicazione ha impostato targetSdkVersion o minSdkVersion su “14" o versioni successive. L'accelerazione hardware in genere genera animazioni più fluide, scorrimento più fluido e prestazioni e risposta all'interazione dell'utente migliori in generale.

Se necessario, puoi disattivare manualmente l'accelerazione hardware con l'attributo hardwareAccelerated per singoli elementi <activity> o per l'elemento <application>. In alternativa, puoi disattivare l'accelerazione hardware per singole visualizzazioni chiamando setLayerType(LAYER_TYPE_SOFTWARE).

Per ulteriori informazioni sull'accelerazione hardware, incluso un elenco delle operazioni di disegno non supportate, consulta il documento Accelerazione hardware.

Modifiche JNI

Nelle versioni precedenti di Android, i riferimenti locali JNI non erano handle indiretti; Android utilizzava i puntatori diretti. Questo non era un problema fintanto che il garbage collection non spostava gli oggetti, ma sembrava funzionare perché rendeva possibile la scrittura di codice con bug. In Android 4.0, il sistema ora utilizza riferimenti indiretti per rilevare questi bug.

Tutto quello che devi sapere sui riferimenti locali di JNI è descritto nella sezione "Riferimenti locali e globali" dei Suggerimenti di JNI. In Android 4.0, la funzionalità CheckJNI è stata migliorata per rilevare questi errori. Guarda il Blog per sviluppatori Android per leggere un prossimo post sugli errori comuni dei riferimenti JNI e su come correggerli.

Questa modifica all'implementazione di JNI interessa solo le app destinate ad Android 4.0 impostando targetSdkVersion o minSdkVersion su “14" o versioni successive. Se hai impostato un valore inferiore per questi attributi, i riferimenti locali JNI si comportano come nelle versioni precedenti.

WebKit

  • WebKit aggiornato alla versione 534.30
  • Supporto per i caratteri indiani (devanagari, bengalese e tamil, compreso il supporto dei caratteri complessi necessari per combinare i glifi) in WebView e il browser integrato
  • Supporto per i caratteri etiopi, georgiani e armeni in WebView e il browser integrato
  • L'assistenza per WebDriver ti consente di testare più facilmente le app che usano WebView

Browser Android

L'applicazione browser aggiunge le seguenti funzionalità per supportare le applicazioni web:

Autorizzazioni

Di seguito sono riportate nuove autorizzazioni:

Funzionalità dispositivo

Di seguito sono riportate le nuove funzionalità dei dispositivi:

  • FEATURE_WIFI_DIRECT: dichiara che l'applicazione utilizza il Wi-Fi per le comunicazioni peer-to-peer.

Per una visualizzazione dettagliata di tutte le modifiche all'API in Android 4.0 (livello API 14), consulta il report Differenze API.

API precedenti

Oltre a quanto riportato sopra, Android 4.0 supporta naturalmente tutte le API delle versioni precedenti. Poiché la piattaforma Android 3.x è disponibile solo per i dispositivi con schermi di grandi dimensioni, se hai sviluppato lo sviluppo principalmente per gli smartphone, potresti non essere a conoscenza di tutte le API aggiunte ad Android in queste release recenti.

Diamo un'occhiata ad alcune delle API più importanti che potrebbero essere sfuggite e che ora sono disponibili anche sugli smartphone:

Android 3.0
  • Fragment: un componente del framework che consente di separare elementi di un'attività in moduli indipendenti che definiscono la propria UI e il proprio ciclo di vita. Consulta la guida per gli sviluppatori relativa ai frammenti.
  • ActionBar: un'alternativa alla barra del titolo tradizionale nella parte superiore della finestra delle attività. Include il logo dell'applicazione nell'angolo a sinistra e fornisce una nuova interfaccia per le voci del menu. Consulta la guida per gli sviluppatori relativa alla barra delle azioni.
  • Loader: un componente del framework che facilita il caricamento asincrono dei dati in combinazione con i componenti dell'interfaccia utente per caricare dinamicamente i dati senza bloccare il thread principale. Consulta la guida per gli sviluppatori relativa ai caricatori.
  • Appunti di sistema: le applicazioni possono copiare e incollare dati (oltre al semplice testo) da e verso gli appunti a livello di sistema. I dati ritagliati possono essere testo normale, un URI o un intent. Consulta la guida per gli sviluppatori Copia e incolla.
  • Trascinamento: un insieme di API integrate nel framework di visualizzazione che facilita le operazioni di trascinamento. Consulta la guida per gli sviluppatori relativa al trascinamento.
  • Un nuovissimo framework di animazione flessibile ti consente di animare proprietà arbitrarie di qualsiasi oggetto (visualizzazione, disegnabile, frammento, oggetto o qualsiasi altro elemento) e di definire aspetti dell'animazione come durata, interpolazione, ripetizione e altro ancora. Grazie al nuovo framework, le animazioni in Android sono più semplici che mai. Consulta la guida per gli sviluppatori Animazione proprietà.
  • Grafica e Compute Engine RenderScript: RenderScript offre un'API di computing e rendering di grafica 3D ad alte prestazioni a livello nativo, che scrivi in base allo standard C99, fornendo le prestazioni che ti aspetti da un ambiente nativo, pur mantenendo la portabilità su diverse CPU e GPU. Consulta la guida per gli sviluppatori di RenderScript.
  • Grafica 2D con accelerazione hardware: ora puoi attivare il renderer OpenGL per la tua applicazione impostando {android:hardwareAccelerated="true"} nell'elemento <application> dell'elemento manifest o per singoli elementi <activity>. Ciò si traduce in animazioni più fluide, scorrimento più fluido e prestazioni e risposta all'interazione dell'utente migliori in generale.

    Nota: se imposti minSdkVersion o targetSdkVersion per la tua applicazione su "14" o su un valore superiore, l'accelerazione hardware viene attivata per impostazione predefinita.

  • E molto altro ancora. Per ulteriori informazioni, consulta le note sulla piattaforma Android 3.0.
Android 3.1
  • API USB: nuove API e potenti API per integrare le periferiche connesse con le applicazioni Android. Le API si basano su uno stack USB e su servizi integrati nella piattaforma, compreso il supporto sia per le interazioni con l'host USB sia per i dispositivi. Consulta la guida per gli sviluppatori relativa a host e accessori USB.
  • API MTP/PTP: le applicazioni possono interagire direttamente con le videocamere connesse e altri dispositivi PTP per ricevere notifiche quando i dispositivi vengono collegati e rimossi, per gestire i file e l'archiviazione su tali dispositivi e trasferire file e metadati da e verso questi dispositivi. L'API MTP implementa il sottoinsieme PTP (Picture Transfer Protocol) della specifica MTP (Media Transfer Protocol). Consulta la documentazione di android.mtp.
  • API RTP: Android espone un'API al suo stack RTP (Real-time Transport Protocol) integrato, che le applicazioni possono utilizzare per gestire il flusso di dati on demand o interattivo. In particolare, le app che offrono VOIP, push-to-talk, conferenze e streaming audio possono utilizzare l'API per avviare sessioni e trasmettere o ricevere stream di dati su qualsiasi rete disponibile. Consulta la documentazione di android.net.rtp.
  • Supporto per joystick e altri input di movimento generici.
  • Consulta le note sulla piattaforma Android 3.1 per molte altre nuove API.
Android 3.2
  • Le nuove schermate supportano le API che ti offrono un maggiore controllo su come vengono visualizzate le applicazioni su schermi di diverse dimensioni. L'API estende l'attuale modello di supporto dello schermo con la possibilità di scegliere come target con precisione specifici intervalli di dimensioni dello schermo in base alle dimensioni, misurate in unità di pixel indipendenti dalla densità (ad esempio 600 dp o 720 dp in larghezza), anziché in base a dimensioni generalizzate degli schermi (ad es. grande o xlarge). Ad esempio, questo è importante per distinguere un dispositivo da 5" da un dispositivo da 7", che in genere vengono entrambi definiti come schermi "grandi". Vedi il post del blog, Nuovi strumenti per la gestione delle dimensioni dello schermo.
  • Nuove costanti per <uses-feature> per dichiarare i requisiti per l'orientamento dello schermo orizzontale o verticale.
  • La configurazione delle "dimensioni dello schermo" del dispositivo ora cambia quando si cambia l'orientamento dello schermo. Se la tua app ha come target il livello API 13 o versioni successive, devi gestire la modifica della configurazione di "screenSize" se vuoi anche gestire la modifica della configurazione di "orientation". Per saperne di più, visita la pagina android:configChanges.
  • Consulta le note sulla piattaforma Android 3.2 per altre nuove API.

Livello API

All'API Android 4.0 viene assegnato un identificatore di numero intero, 14, archiviato nel sistema stesso. Questo identificatore, chiamato "livello API", consente al sistema di determinare correttamente se un'applicazione è compatibile con il sistema prima di installarla.

Per utilizzare le API introdotte in Android 4.0 nella tua applicazione, devi compilare l'applicazione su una piattaforma Android che supporti il livello API 14 o successivo. A seconda delle esigenze, potresti anche dover aggiungere un attributo android:minSdkVersion="14" all'elemento <uses-sdk>.

Per ulteriori informazioni, consulta la sezione Che cos'è il livello API?