API per Android 4.3

Livello API: 18

Android 4.3 (JELLY_BEAN_MR2) è un aggiornamento della release Jelly Bean che offre nuove funzionalità per utenti e app sviluppatori. Il presente documento fornisce un'introduzione alle nuove API.

Se sei uno sviluppatore di app, devi scaricare l'immagine di sistema Android 4.3 e SDK di SDK Manager come il prima possibile. Se non hai un dispositivo con Android 4.3 su cui testare l'app, usare il sistema Android 4.3 per testare la tua app nell'emulatore Android. Quindi, crea le tue app sulla base della piattaforma Android 4.3 per iniziare a utilizzare le API più recenti.

Aggiorna il livello API target

Per ottimizzare meglio la tua app per i dispositivi con Android 4.3, devi impostare targetSdkVersion su "18", installalo su un'immagine di sistema Android 4.3, testarlo, quindi pubblicare un aggiornamento con questa modifica.

Puoi usare le API in Android 4.3 e supportare anche le versioni precedenti aggiungendo condizioni al codice che controllano il livello API di sistema prima di eseguirlo API non supportate dal tuo minSdkVersion. Per scoprire di più sul mantenimento della compatibilità con le versioni precedenti, consulta l'articolo Supporto di differenze Versioni della piattaforma.

Nella libreria di assistenza di Android sono disponibili anche varie API che consentono di implementare nuove funzionalità sulle versioni precedenti della piattaforma.

Per saperne di più su come funzionano i livelli API, leggi l'articolo Che cos'è un'API Livello?

Importanti cambiamenti del comportamento

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

Se la tua app utilizza intent impliciti...

La tua app potrebbe funzionare in modo anomalo in un ambiente del profilo con limitazioni.

Gli utenti in un ambiente con profilo limitato potrebbero non avere a disposizione tutte le app Android standard. Ad esempio, un profilo con limitazioni potrebbe avere browser web e app fotocamera disattivati. Quindi la tua app non deve fare ipotesi su quali app disponibile perché se chiami startActivity() senza verificare se un'app è disponibile per gestire Intent, la tua app potrebbe arrestarsi in modo anomalo in un profilo con limitazioni.

Quando utilizzi un intent implicito, devi sempre verificare che un'app sia disponibile per gestire l'intent chiamando resolveActivity() o queryIntentActivities(). Ad esempio:

Kotlin

val intent = Intent(Intent.ACTION_SEND)
...
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show()
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
...
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show();
}

Se la tua app dipende dagli account...

La tua app potrebbe funzionare in modo anomalo in un ambiente del profilo con limitazioni.

Gli utenti all'interno di un ambiente di profilo limitato non hanno accesso agli account utente per impostazione predefinita. Se la tua app dipende da un Account, l'app potrebbe arrestarsi in modo anomalo o comportarsi in modo anomalo in modo imprevisto quando utilizzato in un profilo con limitazioni.

Se preferisci impedire ai profili con limitazioni di utilizzare completamente la tua app perché dipende dai dati dell'account sensibili. Specifica l'attributo android:requiredAccountType nel campo <application> del file manifest. .

Se vuoi consentire ai profili con limitazioni di continuare a usare la tua app anche se non possono creare i propri account, quindi disattivare le funzionalità dell'app che richiedono un account o consentire ai profili con limitazioni di accedere agli account creati dall'utente principale. Per ulteriori informazioni informazioni, consulta la sezione di seguito in merito a Supportare gli account in un profilo con limitazioni.

Se la tua app utilizza VideoView...

Le dimensioni del tuo video potrebbero essere inferiori su Android 4.3.

Nelle versioni precedenti di Android, il widget VideoView è stato rilevato in modo errato ha calcolato il valore "wrap_content" per layout_height e layout_width affinché corrisponda a "match_parent". Pertanto, anche se l'uso di "wrap_content" per l'altezza o la larghezza potrebbe aver precedentemente fornito il layout video desiderato, ciò potrebbe comportare una riduzione delle dimensioni dei video su Android 4.3 e versioni successive. Per risolvere il problema, sostituisci "wrap_content" con "match_parent" e verifica che il tuo video venga visualizzato come previsto su Android 4.3 e versioni precedenti.

Profili con limitazioni

Sui tablet Android, ora gli utenti possono creare profili con limitazioni in base all'utente principale. Quando gli utenti creano un profilo con limitazioni, possono attivare limitazioni, ad esempio quali app disponibili per il profilo. Un nuovo set di API in Android 4.3 consente anche di creare modelli impostazioni delle limitazioni per le app che sviluppi. Ad esempio, utilizzando le nuove API, puoi Consentire agli utenti di controllare il tipo di contenuti disponibili all'interno dell'app quando viene eseguita in un ambiente del profilo limitato.

L'interfaccia utente che consente agli utenti di controllare le limitazioni che hai creato è gestita dal sistema Applicazione Impostazioni. Per mostrare all'utente le impostazioni relative alle limitazioni dell'app: devi dichiarare le limitazioni fornite dalla tua app creando un elemento BroadcastReceiver che riceve l'intent ACTION_GET_RESTRICTION_ENTRIES. Il sistema richiama questo intent per eseguire query per tutte le app per le limitazioni disponibili, quindi crea la UI per consentire all'utente principale gestire le restrizioni per ogni profilo con limitazioni.

Nel metodo onReceive() di sul tuo BroadcastReceiver, devi creare un RestrictionEntry per ogni limitazione offerta dalla tua app. Ogni RestrictionEntry definisce un titolo, una descrizione e uno dei i seguenti tipi di dati:

  • TYPE_BOOLEAN per una limitazione che è true o false.
  • TYPE_CHOICE per una limitazione con più opzioni che si escludono a vicenda (scelte dei pulsanti di opzione).
  • TYPE_MULTI_SELECT per una limitazione che contiene più opzioni che non si escludono a vicenda (opzioni di casella di controllo).

Quindi inserisci tutti gli oggetti RestrictionEntry in un ArrayList e li inserisci nel risultato del broadcast receiver come valore per il parametro EXTRA_RESTRICTIONS_LIST extra.

Il sistema crea l'UI per le limitazioni della tua app nell'app Impostazioni e salva ogni con la chiave univoca che hai fornito per ogni RestrictionEntry . Quando l'utente apre la tua app, puoi eseguire una query per conoscere eventuali restrizioni attuali chiamata getApplicationRestrictions(). Questo restituisce un elemento Bundle contenente le coppie chiave-valore per ogni restrizione che hai definito con gli oggetti RestrictionEntry.

Se vuoi fornire restrizioni più specifiche che non possono essere gestite da valori booleani, scelta e valori a scelta multipla, puoi creare un'attività in cui l'utente può specificare limitazioni e consentire agli utenti di aprire questa attività dalle impostazioni delle limitazioni. Nel tuo broadcast receiver, includi il EXTRA_RESTRICTIONS_INTENT extra nel risultato Bundle. Questo extra deve specificare un Intent che indica la classe Activity da avviare (utilizza il putParcelable() per trasmettere EXTRA_RESTRICTIONS_INTENT con l'intent). Quando l'utente principale accede alla tua attività per impostare limitazioni personalizzate, i tuoi l'attività deve quindi restituire un risultato contenente i valori di restrizione in un extra utilizzando la chiave EXTRA_RESTRICTIONS_LIST o EXTRA_RESTRICTIONS_BUNDLE, a seconda che tu abbia specificato RestrictionEntry di oggetti o coppie chiave-valore, rispettivamente.

Account di assistenza in un profilo con limitazioni

Tutti gli account aggiunti all'utente principale sono disponibili per un profilo con limitazioni, ma non sono accessibili dalle API AccountManager per impostazione predefinita. Se tenti di aggiungere un account con AccountManager mentre ti trovi in una zona con restrizioni profilo, riceverai un risultato non corretto. A causa di queste limitazioni, puoi usufruire di: tre opzioni:

  • Consentire l'accesso agli account del proprietario da un profilo con limitazioni.

    Per accedere a un account da un profilo con limitazioni, devi aggiungere l'attributo android:restrictedAccountType al tag <application>:

    <application ...
        android:restrictedAccountType="com.example.account.type" >
    

    Attenzione: l'attivazione di questo attributo fornisce Accesso delle app agli account dell'utente principale dai profili con limitazioni. Dovresti quindi consentire solo se le informazioni visualizzate dall'app non rivelano l'identificazione personale informazioni (PII) considerate sensibili. Le impostazioni di sistema informeranno l'istanza principale all'utente che l'app concede profili con limitazioni ai propri account, pertanto all'utente deve essere chiaro l'accesso all'account è importante per la funzionalità della tua app. Se possibile, devi anche Fornire adeguati controlli delle restrizioni per l'utente principale che definiscono il livello di accesso all'account è consentito nella tua app.

  • Disattivare alcune funzionalità se non è possibile modificare gli account.

    Se vuoi utilizzare gli account, ma non ne hai bisogno per l'account principale funzionalità, puoi verificare la disponibilità degli account e disabilitare le funzionalità quando non sono disponibili. Controlla innanzitutto se è disponibile un account. In caso contrario, chiedi se è possibile creare un nuovo account chiamando il numero getUserRestrictions() e controlla il DISALLOW_MODIFY_ACCOUNTS extra nel risultato. Se è true, devi disattivare le funzionalità dell'app che richiedono l'accesso agli account. Ad esempio:

    Kotlin

    val um = context.getSystemService(Context.USER_SERVICE) as UserManager
    val restrictions: Bundle = um.userRestrictions
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }
    

    Java

    UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    Bundle restrictions = um.getUserRestrictions();
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }
    

    Nota: in questo scenario, non devi dichiarare eventuali nuovi attributi nel file manifest.

  • Disattivare l'app quando non puoi accedere agli account privati.

    Se invece è importante che la tua app non sia disponibile per i profili con limitazioni perché la tua app dipende da informazioni personali sensibili presenti in un account (e dal fatto che i profili con limitazioni attualmente non è possibile aggiungere nuovi account), aggiungi l'attributo android:requiredAccountType al tag <application>:

    <application ...
        android:requiredAccountType="com.example.account.type" >
    

    Ad esempio, l'app Gmail utilizza questo attributo per disattivarsi per i profili con limitazioni, perché l'indirizzo email personale del proprietario non deve essere disponibile per i profili con limitazioni.

  • Wireless e connettività

    Bluetooth Low Energy (Smart Ready)

    Android ora supporta Bluetooth Low Energy (LE) con nuove API in android.bluetooth. Con le nuove API puoi creare app Android che comunicano con Bluetooth Low Energy periferiche come rilevatori del battito cardiaco e contapassi.

    Poiché Bluetooth LE è una funzione hardware che non è disponibile I dispositivi basati su Android, devi dichiarare nel file manifest un <uses-feature> elemento per "android.hardware.bluetooth_le":

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
    

    Se hai già familiarità con le API Bluetooth classiche di Android, tieni presente che l'utilizzo del Le API Bluetooth LE presentano alcune differenze. La cosa più importante è che ora esiste una classe BluetoothManager che dovresti utilizzare per alcune operazioni di alto livello come acquisire un BluetoothAdapter, ottenere un elenco di dispositivi e controllare lo stato di un dispositivo. Ad esempio, questo è il modo in cui dovresti ottenere BluetoothAdapter:

    Kotlin

    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothAdapter = bluetoothManager.adapter
    

    Java

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();
    

    Per trovare le periferiche Bluetooth LE, chiama startLeScan() sul dispositivo BluetoothAdapter, passandogli un'implementazione dell'interfaccia BluetoothAdapter.LeScanCallback. Quando la funzionalità Bluetooth rileva una periferica Bluetooth LE, la tua implementazione BluetoothAdapter.LeScanCallback riceve una chiamata al Metodo onLeScan(). Questo fornisce un oggetto BluetoothDevice che rappresenta dispositivo rilevato, il valore RSSI relativo al dispositivo e un array di byte contenente record della pubblicità.

    Se vuoi eseguire la scansione solo per tipi specifici di periferiche, puoi invece chiamare startLeScan() e includere un array di oggetti UUID che specificano i servizi GATT supportati dalla tua app.

    Nota: puoi cercare solo dispositivi Bluetooth LE oppure cerca dispositivi Bluetooth classici utilizzando le API precedenti. Impossibile scansionare contemporaneamente LE e Classic dispositivi Bluetooth contemporaneamente.

    Per connetterti a una periferica Bluetooth LE, chiama connectGatt() sul BluetoothDevice, passandogli un'implementazione BluetoothGattCallback. La tua implementazione di BluetoothGattCallback riceve callback relativi alla connettività lo stato del dispositivo e altri eventi. È durante onConnectionStateChange() callback che puoi iniziare a comunicare con il dispositivo se il metodo supera STATE_CONNECTED come nuovo stato.

    L'accesso alle funzioni Bluetooth su un dispositivo richiede inoltre che l'app richieda determinati Autorizzazioni utente Bluetooth. Per ulteriori informazioni, consulta la guida dell'API Bluetooth Low Energy.

    Modalità solo ricerca Wi-Fi

    Durante il tentativo di identificare la posizione dell'utente, Android potrebbe utilizzare la rete Wi-Fi per determinare la posizione scansionando i punti di accesso vicini. Tuttavia, gli utenti spesso mantengono il Wi-Fi disattivato consumare meno batteria, di conseguenza i dati sulla posizione sono meno precisi. Android ora include un modalità di sola ricerca che consente al Wi-Fi del dispositivo di scansionare i punti di accesso per contribuire a ottenere la posizione senza connettersi a un punto di accesso, riducendo notevolmente l'utilizzo della batteria.

    Se vuoi acquisire la posizione dell'utente ma il Wi-Fi è attualmente disattivato, puoi richiedere all'utente di attivare la modalità di sola ricerca Wi-Fi chiamando startActivity() con l'azione ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE.

    Configurazione Wi-Fi

    Le nuove API WifiEnterpriseConfig consentono ai servizi orientati all'azienda di Automatizzare la configurazione Wi-Fi per i dispositivi gestiti.

    Risposta rapida per le chiamate in arrivo

    Da Android 4.0, una funzionalità chiamata "Risposta rapida" consente agli utenti di rispondere alle richieste chiamate con un messaggio di testo immediato senza dover rispondere alla chiamata o sbloccare il dispositivo. Finora, questi messaggi rapidi erano sempre gestiti dall'app di messaggistica predefinita. Ora qualsiasi app può dichiarare la sua capacità di gestire questi messaggi creando un Service con un filtro per intent per ACTION_RESPOND_VIA_MESSAGE.

    Quando l'utente risponde a una chiamata in arrivo con una risposta rapida, l'app Telefono invia l'intent ACTION_RESPOND_VIA_MESSAGE con un URI descrivendo il destinatario (il chiamante) e i EXTRA_TEXT extra con il messaggio che l'utente vuole inviare. Quando il servizio riceve l'intent, dovrebbe consegnare il messaggio e si interrompono immediatamente (la tua app non dovrebbe mostrare un'attività).

    Per ricevere questo intent, devi dichiarare l'autorizzazione SEND_RESPOND_VIA_MESSAGE.

    Multimediale

    Miglioramenti a MediaExtractor e MediaCodec

    Ora Android semplifica la scrittura delle creatività Lettori per lo streaming su HTTP (DASH) conformi allo standard ISO/IEC 23009-1 utilizzando le API esistenti in MediaCodec e MediaExtractor. Il framework alla base di queste API è stato aggiornato per supportare analisi di file MP4 frammentati, ma la tua app è ancora responsabile dell'analisi dei metadati MPD e passando i singoli stream a MediaExtractor.

    Se vuoi utilizzare DASH con contenuti criptati, tieni presente che il metodo getSampleCryptoInfo() restituisce i metadati MediaCodec.CryptoInfo che descrivono la struttura di ogni contenuto multimediale criptato campione. Inoltre, il metodo getPsshInfo() è stato aggiunto MediaExtractor in modo da poter accedere ai metadati PSSH per i contenuti multimediali DASH. Questo metodo restituisce una mappa degli oggetti UUID in byte, con il UUID che specifica lo schema di crittografia e i byte sono i dati specifici a questo schema.

    DRM multimediale

    La nuova classe MediaDrm offre una soluzione modulare per i diritti digitali (DRM) con i tuoi contenuti multimediali separando i problemi DRM dalla riproduzione di contenuti multimediali. Per questa separazione delle API consente di riprodurre contenuti criptati con Widevine senza dover per utilizzare il formato multimediale Widevine. Questa soluzione DRM supporta anche la crittografia comune DASH, puoi utilizzare vari schemi DRM con i tuoi contenuti in streaming.

    Puoi utilizzare MediaDrm per ottenere messaggi di richiesta della chiave opachi ed elaborare l'operazione messaggi di risposta chiave dal server per l'acquisizione e il provisioning delle licenze. La tua app è responsabile della gestione delle comunicazioni di rete con i server; La classe MediaDrm fornisce solo la possibilità di generare ed elaborare i messaggi.

    Le API MediaDrm sono destinate a essere utilizzate insieme MediaCodec API introdotte in Android 4.1 (livello API 16), tra cui MediaCodec per la codifica e decodifica dei contenuti, MediaCrypto per la gestione dei contenuti criptati e MediaExtractor per estrarre e demuxare i contenuti.

    Devi prima creare MediaExtractor e MediaCodec oggetti. A questo punto, puoi accedere al set di dati UUID, che in genere si trovano nei metadati dei contenuti, e li usa per creare un di un oggetto MediaDrm con il relativo costruttore.

    Codifica video da una piattaforma

    Android 4.1 (livello API 16) ha aggiunto la classe MediaCodec per gli utenti di basso livello codifica e decodifica dei contenuti multimediali. Quando codifichi i video, devi fornire Android 4.1 i contenuti multimediali con un array ByteBuffer, ma Android 4.3 ora consente di utilizzare Surface come input per un codificatore. Ad esempio, questo ti permette di codificare l'input da un file video esistente o utilizzando fotogrammi generati da OpenGL ES.

    Per utilizzare Surface come input per il codificatore, devi prima chiamare configure() per MediaCodec. Quindi chiama createInputSurface() per ricevere il Surface con cui potrai trasmettere in streaming i tuoi contenuti multimediali.

    Ad esempio, puoi utilizzare il valore Surface specificato come finestra per un report OpenGL contesto passandolo a eglCreateWindowSurface(). Poi, durante il rendering della superficie, chiama eglSwapBuffers() per passare il frame a MediaCodec.

    Per iniziare la codifica, chiama start() sul MediaCodec. Al termine, chiama signalEndOfInputStream() per terminare la codifica e chiamare release() sul Surface.

    Muxing di contenuti multimediali

    La nuova classe MediaMuxer consente il multiplex tra uno stream audio e uno stream video. Queste API fungono da controparte al MediaExtractor aggiunta in Android 4.2 per il de-multiplexing (demuxing) dei contenuti multimediali.

    I formati di output supportati sono definiti in MediaMuxer.OutputFormat. Al momento, MP4 è l'unico formato di output supportato, attualmente supportato da MediaMuxer solo uno stream audio e/o uno stream video alla volta.

    MediaMuxer è progettato principalmente per funzionare con MediaCodec in modo da poter eseguire l'elaborazione video tramite MediaCodec, quindi salva in un file MP4 tramite MediaMuxer. Puoi anche utilizzare MediaMuxer in combinazione con MediaExtractor per eseguire l'editing multimediale senza la necessità di codifica o decodifica.

    Avanzamento della riproduzione e scrubbing per RemoteControlClient

    In Android 4.0 (livello API 14), è stato aggiunto RemoteControlClient a attivare i controlli di riproduzione dei contenuti multimediali da client di controllo remoto come i controlli disponibili sul schermata di blocco. Android 4.3 ora consente a questi controller di visualizzare i contenuti e i controlli per eseguire lo scrubbing della riproduzione. Se hai attivato il controllo remoto per il tuo app multimediale con le API RemoteControlClient, dopodiché potrai consentire la riproduzione eseguire lo scrubbing implementando due nuove interfacce.

    Innanzitutto, devi abilitare il flag FLAG_KEY_MEDIA_POSITION_UPDATE passandolo a setTransportControlsFlags().

    Poi implementa le due nuove interfacce seguenti:

    RemoteControlClient.OnGetPlaybackPositionListener
    È incluso il callback onGetPlaybackPosition(), che richiede la posizione attuale dei tuoi contenuti multimediali quando il telecomando deve aggiornare l'avanzamento nella sua UI.
    RemoteControlClient.OnPlaybackPositionUpdateListener
    È incluso il callback onPlaybackPositionUpdate(), che indica all'app il nuovo codice temporale per i contenuti multimediali quando l'utente esegue lo scrubbing della riproduzione con dell'interfaccia utente del telecomando.

    Dopo aver aggiornato la riproduzione con la nuova posizione, chiama setPlaybackState() per indicare nuovi stati, posizione e velocità di riproduzione.

    Una volta definite queste interfacce, puoi impostarle per RemoteControlClient chiamando setOnGetPlaybackPositionListener() e rispettivamente setPlaybackPositionUpdateListener().

    Grafica

    Supporto per OpenGL ES 3.0

    Android 4.3 aggiunge interfacce Java e supporto nativo per OpenGL ES 3.0. Nuove funzionalità principali forniti in OpenGL ES 3.0 includono:

    • Accelerazione degli effetti visivi avanzati
    • Compressione texture ETC2/EAC di alta qualità come funzionalità standard
    • Una nuova versione del linguaggio di ombreggiatura GLSL ES con supporto di numeri interi e in virgola mobile a 32 bit
    • Rendering avanzato della texture
    • Standardizzazione più ampia delle dimensioni delle texture e dei formati del buffer di rendering

    L'interfaccia Java per OpenGL ES 3.0 su Android è fornita con GLES30. Se utilizzi OpenGL ES 3.0, assicurati di dichiararlo nel file manifest con il <uses-feature> e l'attributo android:glEsVersion. Ad esempio:

    <manifest>
        <uses-feature android:glEsVersion="0x00030000" />
        ...
    </manifest>
    

    E ricorda di specificare il contesto OpenGL ES richiamando setEGLContextClientVersion(), passando 3 come versione.

    Per ulteriori informazioni sull'uso di OpenGL ES, incluso come verificare se il dispositivo è supportato Versione OpenGL ES in fase di runtime, consulta la guida all'API OpenGL ES.

    Mipmapping per drawables

    L'utilizzo di una mipmap come origine per la tua bitmap o il tuo drawable è un modo semplice per fornire un di alta qualità e diverse scale dell'immagine, il che può essere particolarmente utile se si prevede immagine da ridimensionare durante un'animazione.

    Android 4.2 (livello API 17) ha aggiunto il supporto delle mipmap in Bitmap di classe: Android scambia le immagini mip in Bitmap dopo hanno fornito un'origine mipmap e hanno abilitato setHasMipMap(). Ora in Android 4.3 puoi attivare le mipmap anche per un oggetto BitmapDrawable, fornendo un asset mipmap e impostando l'attributo android:mipMap in un file di risorse bitmap o chiamando hasMipMap().

    Interfaccia utente

    Visualizza overlay

    La nuova classe ViewOverlay fornisce un livello trasparente sopra un View su cui puoi aggiungere contenuti visivi e che non influiscono la gerarchia del layout. Puoi ricevere un ViewOverlay a qualsiasi View chiamando il numero getOverlay(). L'overlay ha sempre le stesse dimensioni e la stessa posizione della vista host (la vista da cui è stata creata), consentendoti di aggiungere contenuti che compaiono davanti alla vista dell'host ma che non possono estendersi entro i limiti di quella vista host.

    L'utilizzo di un ViewOverlay è particolarmente utile quando vuoi creare come lo scorrimento di una visualizzazione all'esterno del contenitore o lo spostamento di elementi sullo schermo senza influire sulla gerarchia delle visualizzazioni. Tuttavia, poiché l'area utilizzabile di un overlay è limitato alla stessa area della vista host, se vuoi animare una visualizzazione spostandoti all'esterno dalla sua posizione nel layout, devi utilizzare un overlay di una vista principale che abbia lo stesso limiti del layout.

    Quando crei un overlay per una visualizzazione widget come Button, puoi aggiungere Drawable oggetti all'overlay chiamando add(Drawable). Se chiami getOverlay() per una visualizzazione di layout, ad esempio RelativeLayout, l'oggetto restituito è ViewGroupOverlay. La La classe ViewGroupOverlay è una sottoclasse di ViewOverlay che ti consente anche di aggiungere View richiamando add(View).

    Nota: tutti gli elementi disegnabili e le viste aggiunti a un overlay. sono solo immagini. Non possono ricevere stato attivo o eventi di input.

    Ad esempio, il seguente codice anima una vista scorrendo verso destra posizionandola nell'overlay della vista principale, per poi eseguire un'animazione di traduzione su tale vista:

    Kotlin

    val view: View? = findViewById(R.id.view_to_remove)
    val container: ViewGroup? = view?.parent as ViewGroup
    
    container?.apply {
        overlay.add(view)
        ObjectAnimator.ofFloat(view, "translationX", right.toFloat())
                .start()
    }
    

    Java

    View view = findViewById(R.id.view_to_remove);
    ViewGroup container = (ViewGroup) view.getParent();
    container.getOverlay().add(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
    anim.start();
    

    Layout limiti ottici

    Per le viste che contengono immagini di sfondo con nove patch, ora puoi specificare che debbano essere allineata con le viste vicine in base alla "ottica" limiti dell'immagine di sfondo anziché del "clip" limiti della vista.

    Ad esempio, le figure 1 e 2 mostrano ciascuna lo stesso layout, ma la versione nella figura 1 è utilizzando i limiti di clip (comportamento predefinito), mentre la figura 2 utilizza i limiti ottici. Poiché le immagini con nove patch utilizzate per il pulsante e la cornice digitale includono spaziature interne intorno ai bordi, non sembrano allinearsi tra loro o con il testo quando vengono usati i limiti dei clip.

    Nota: gli screenshot nelle figure 1 e 2 mostrano la dicitura "Mostra limiti di layout" impostazione sviluppatore attivata. Per ogni vista, le linee rosse indicano il limiti, le linee blu indicano i limiti del clip e il rosa indica quelli.

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

    Figura 2. Layout con limiti ottici.

    Per allineare le visualizzazioni in base ai relativi limiti ottici, imposta l'attributo android:layoutMode su "opticalBounds" in uno dei layout principali. Ad esempio:

    <LinearLayout android:layoutMode="opticalBounds" ... >
    

    Figura 3. Visualizzazione ingrandita della nove patch del pulsante Holo con limiti ottici.

    Affinché questo comando funzioni, le nove immagini con patch applicate allo sfondo delle viste devono specificare i limiti ottici utilizzando le linee rosse lungo la parte inferiore e il lato destro del file con nove patch (come come mostrato nella figura 3). Le linee rosse indicano la regione da sottrarre i limiti del clip, lasciando i margini ottici dell'immagine.

    Quando attivi i limiti ottici per un elemento ViewGroup nel layout, le viste discendenti ereditano la modalità di layout dei limiti ottici a meno che non la sostituisci per un gruppo impostazione di android:layoutMode su "clipBounds". Tutti gli elementi di layout rispettano inoltre limiti ottici delle visualizzazioni del figlio, adattando i propri limiti in base ai limiti ottici le viste al loro interno. Tuttavia, gli elementi di layout (sottoclassi di ViewGroup) attualmente non supporta i limiti ottici per le immagini con nove patch applicate al proprio sfondo.

    Se crei una vista personalizzata assegnando sottoclassi View, ViewGroup o una qualsiasi delle sue sottoclassi, la vista erediterà questi comportamenti dei collegamenti ottici.

    Nota: tutti i widget supportati dal tema Holo sono stati aggiornati con limiti ottici, tra cui Button, Spinner, EditText e altri. Puoi quindi trarre immediatamente vantaggio dall'impostazione Attributo android:layoutMode a "opticalBounds" se la tua app applica un tema Holo (Theme.Holo, Theme.Holo.Light e così via).

    Per specificare limiti ottici per le tue immagini a nove patch con lo strumento Disegna 9 patch, tieni premuto Ctrl quando facendo clic sui pixel del bordo.

    Animazione per valori rettangolari

    Ora puoi animare due valori Rect con il nuovo RectEvaluator. Questa nuova classe è un'implementazione di TypeEvaluator che puoi passare a ValueAnimator.setEvaluator().

    Listener di collegamento finestra e stato attivo

    In precedenza, se volevi ascoltare quando la visualizzazione era collegata/scollegata dalla finestra oppure quando l'elemento attivo è stato modificato, devi eseguire l'override della classe View per implementare onAttachedToWindow() e onDetachedFromWindow() o onWindowFocusChanged(), rispettivamente.

    Ora, per ricevere eventi di collegamento e scollegamento, puoi implementare ViewTreeObserver.OnWindowAttachListener e impostarlo in una vista con addOnWindowAttachListener(). Per ricevere eventi di evidenziazione, puoi implementare ViewTreeObserver.OnWindowFocusChangeListener e impostarlo in una vista con addOnWindowFocusChangeListener().

    Supporto overscan della TV

    Per assicurarti che la tua app riempia l'intero schermo di tutti i televisori, ora puoi attivare l'overscan layout dell'app. La modalità di overscan viene determinata dal flag FLAG_LAYOUT_IN_OVERSCAN, che puoi attivare con temi della piattaforma come Theme_DeviceDefault_NoActionBar_Overscan o attivando il metodo Stile windowOverscan in un tema personalizzato.

    Orientamento schermo

    La <activity> screenOrientation del tag ora supporta valori aggiuntivi per rispettare la preferenza dell'utente per la rotazione automatica:

    "userLandscape"
    Ha lo stesso comportamento di "sensorLandscape", tranne se l'utente disattiva la rotazione automatica il dispositivo si blocca nel normale orientamento orizzontale e non si capovolge.
    "userPortrait"
    Ha lo stesso comportamento di "sensorPortrait", tranne se l'utente disattiva la rotazione automatica e poi si blocca nel normale orientamento verticale e non si capovolge.
    "fullUser"
    Ha lo stesso comportamento di "fullSensor" e consente la rotazione in tutte e quattro le direzioni, ad eccezione di se l'utente disattiva la rotazione automatica, si blocca nell'orientamento preferito dell'utente.

    Inoltre, ora puoi anche dichiarare "locked" per bloccare l'orientamento dell'app all'orientamento corrente dello schermo.

    Animazioni di rotazione

    Il nuovo campo rotationAnimation in WindowManager ti consente di scegliere tra una delle tre animazioni seguenti quando il sistema cambia l'orientamento dello schermo. Le tre animazioni sono:

    Nota: queste animazioni sono disponibili solo se hai impostato l'utilizzo della modalità "a schermo intero" per la tua attività. attivabile con temi quali Theme.Holo.NoActionBar.Fullscreen.

    Ad esempio, ecco come abilitare la "dissolvenza incrociata" animazione:

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val params: WindowManager.LayoutParams = window.attributes
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE
        window.attributes = params
        ...
    }
    

    Java

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        getWindow().setAttributes(params);
        ...
    }
    

    Input utente

    Nuovi tipi di sensori

    Il nuovo sensore TYPE_GAME_ROTATION_VECTOR ti consente di rilevare le rotazioni del dispositivo senza preoccuparti delle interferenze magnetiche. A differenza del sensore TYPE_ROTATION_VECTOR, il TYPE_GAME_ROTATION_VECTOR non si basa sul nord magnetico.

    I nuovi sensori TYPE_GYROSCOPE_UNCALIBRATED e TYPE_MAGNETIC_FIELD_UNCALIBRATED forniscono dati non elaborati dei sensori senza per le stime delle differenziazioni. Vale a dire, gli attuali TYPE_GYROSCOPE e TYPE_MAGNETIC_FIELD I sensori forniscono dati dei sensori che tengono conto dei bias stimati derivati dal giroscopio e dal ferro duro nel dispositivo. Mentre il nuovo valore "non calibrato" di questi sensori forniscono dati non elaborati dei sensori e offre i valori di bias stimati separatamente. Questi sensori ti consentono fornire una calibrazione personalizzata per i dati dei sensori migliorando il bias stimato con dati esterni.

    Listener di notifica

    In Android 4.3 è stata aggiunta una nuova classe di servizio, NotificationListenerService, che consente alla tua app di ricevere informazioni sulle nuove notifiche non appena vengono pubblicate dal sistema.

    Se al momento la tua app utilizza le API del servizio di accessibilità per accedere alle notifiche di sistema, devi aggiornarla in modo da utilizzare queste API.

    Provider di contatti

    Query per "contattabili"

    La nuova query del fornitore di contatti, Contactables.CONTENT_URI, fornisce un modo efficiente per ottenere un Cursor contenente tutti gli indirizzi email e i numeri di telefono appartenenti a tutti i contatti corrispondenti alla query specificata.

    Query sui delta dei contatti

    Al provider di contatti sono state aggiunte nuove API che ti consentono di eseguire query efficaci sulle modifiche recenti ai dati dei contatti. In precedenza, la tua app poteva ricevere una notifica quando qualcosa nei dati dei contatti cambiava, ma non sapevate esattamente cosa cambiava e dovevate recuperare tutti i contatti per poi ripeterli per scoprire la modifica.

    Per tenere traccia delle modifiche apportate a inserimenti e aggiornamenti, ora puoi includere il parametro CONTACT_LAST_UPDATED_TIMESTAMP con la tua selezione per eseguire query solo sui contatti che sono cambiati dall'ultima query al provider.

    Per monitorare quali contatti sono stati eliminati, la nuova tabella ContactsContract.DeletedContacts fornisce un log dei contatti eliminati (ma ogni contatto eliminato viene conservato in questa tabella per un periodo di tempo limitato). Analogamente a CONTACT_LAST_UPDATED_TIMESTAMP, puoi utilizzare il nuovo parametro di selezione, CONTACT_DELETED_TIMESTAMP, per controllare quali contatti sono stati eliminati dall'ultima volta che hai eseguito una query sul provider. La tabella contiene anche la costante DAYS_KEPT_MILLISECONDS contenente il numero di giorni (in millisecondi) in cui verrà conservato il log.

    Inoltre, il provider di contatti ora trasmette l'azione CONTACTS_DATABASE_CREATED quando l'utente cancella la memoria dei contatti dal menu delle impostazioni di sistema, ricreando in modo efficace Database del provider di contatti. Ha lo scopo di segnalare alle app che devono abbandonare tutti i contatti informazioni archiviate e ricaricarle con una nuova query.

    Per un esempio di codice che utilizza queste API per verificare le modifiche ai contatti, cerca in ApiDemos campione disponibile nel download degli esempi di SDK.

    Localizzazione

    Supporto migliorato per il testo bidirezionale

    Le versioni precedenti di Android supportano le lingue e il layout da destra a sinistra (RTL). ma a volte non gestiscono correttamente il testo nelle direzioni miste. Quindi Android 4.3 aggiunge le API BidiFormatter che ti aiutano a formattare correttamente il testo in direzione opposta senza includerne parti in parte.

    Ad esempio, quando vuoi creare una frase con una variabile di stringa come "Forse cercavi 15 Bay Street, Laurel, CA?", di solito passi una risorsa stringa localizzata e la variabile a String.format():

    Kotlin

    val suggestion = String.format(resources.getString(R.string.did_you_mean), address)
    

    Java

    Resources res = getResources();
    String suggestion = String.format(res.getString(R.string.did_you_mean), address);
    

    Tuttavia, se le impostazioni internazionali sono ebraiche, la stringa formattata risulta così:

    엄 엄 엄 엄 엄

    Sbagliato perché il "15" deve essere a sinistra di "Bay Street". La soluzione consiste nell'utilizzare BidiFormatter e il relativo metodo unicodeWrap(). Ad esempio, il codice riportato sopra diventa:

    Kotlin

    val bidiFormatter = BidiFormatter.getInstance()
    val suggestion = String.format(
            resources.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address)
    )
    

    Java

    Resources res = getResources();
    BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    String suggestion = String.format(res.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address));
    

    Per impostazione predefinita, unicodeWrap() utilizza una forte euristica della stima della direzionalità, che può sbagliare se la prima per la direzione del testo non rappresenta la direzione appropriata per i contenuti nel complesso. Se necessario, puoi specificare un'euristica diversa passando una delle costanti TextDirectionHeuristic da TextDirectionHeuristics a unicodeWrap().

    Nota: queste nuove API sono disponibili anche per le versioni precedenti di Android tramite l'Assistenza di Android Libreria, con il corso BidiFormatter e le API correlate.

    Servizi di accessibilità

    Gestire gli eventi chiave

    Ora un AccessibilityService può ricevere una richiamata per eventi di input chiave con il metodo di callback onKeyEvent(). Ciò consente al tuo servizio di accessibilità di gestire l'input per i dispositivi di input basati su tasti come le tastiere e traducono questi eventi in azioni speciali che in precedenza era possibile solo con l'input tocco o il d-pad del dispositivo.

    Seleziona il testo e copia/incolla

    AccessibilityNodeInfo ora fornisce API che consentono un AccessibilityService per selezionare, tagliare, copiare e incollare testo in un nodo.

    Per specificare la selezione del testo da tagliare o copiare, il servizio di accessibilità può utilizzare il nuovo azione, ACTION_SET_SELECTION, superato e la posizione di inizio e fine della selezione con ACTION_ARGUMENT_SELECTION_START_INT e ACTION_ARGUMENT_SELECTION_END_INT. In alternativa, puoi selezionare il testo modificando la posizione del cursore utilizzando il metodo azione, ACTION_NEXT_AT_MOVEMENT_GRANULARITY (in precedenza solo per spostare la posizione del cursore) e aggiungere l'argomento ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN.

    Puoi quindi tagliare o copiare con ACTION_CUT, ACTION_COPY, poi incolla con ACTION_PASTE.

    Nota: queste nuove API sono disponibili anche per le versioni precedenti di Android tramite l'Assistenza di Android Raccolta, con AccessibilityNodeInfoCompat .

    Dichiara le funzioni di accessibilità

    A partire da Android 4.3, un servizio di accessibilità deve dichiarare le funzionalità di accessibilità nel file di metadati per usare alcune funzioni di accessibilità. Se la funzionalità non è richiesta nel file dei metadati, la caratteristica sarà autonoma. Per dichiarare il servizio funzionalità di accessibilità, è necessario utilizzare attributi XML che corrispondano ai vari "capability" costanti in AccessibilityServiceInfo .

    Ad esempio, se un servizio non richiede la funzionalità flagRequestFilterKeyEvents, non riceverà gli eventi chiave.

    Test e debug

    Test automatici dell'interfaccia utente

    La nuova classe UiAutomation fornisce API che ti consentono di simulare gli utenti azioni per l'automazione dei test. Utilizzando le API AccessibilityService della piattaforma, UiAutomation Le API ti consentono di esaminare i contenuti dello schermo e inserire eventi arbitrari sulla tastiera e sul tocco.

    Per ottenere un'istanza di UiAutomation, chiama Instrumentation.getUiAutomation(). Nell'ordine Affinché questo comando funzioni, devi fornire l'opzione -w con il comando instrument durante l'esecuzione di InstrumentationTestCase da adb shell.

    Con l'istanza UiAutomation, puoi eseguire eventi arbitrari per testare la tua app chiamando executeAndWaitForEvent(), passando un Runnable per l'esecuzione, un timeout per l'operazione e un'implementazione dell'interfaccia UiAutomation.AccessibilityEventFilter. È nell'ambito dell'implementazione di UiAutomation.AccessibilityEventFilter che riceverai una chiamata che ti consente di filtrare gli eventi che ti interessano e determinarne l'esito positivo o un errore di uno specifico scenario di test.

    Per osservare tutti gli eventi durante un test, crea un'implementazione di UiAutomation.OnAccessibilityEventListener e passala a setOnAccessibilityEventListener(). L'interfaccia listener riceve quindi una chiamata a onAccessibilityEvent() Ogni volta che si verifica un evento, la ricezione di un oggetto AccessibilityEvent che descrive l'evento.

    Le API UiAutomation espongono una serie di altre operazioni a un livello molto basso per incoraggiare lo sviluppo di strumenti di test dell'interfaccia utente come uiautomator. Ad esempio, UiAutomation può anche:

    • Inserisci eventi di input
    • Modificare l'orientamento dello schermo
    • Acquisisci screenshot

    E, soprattutto per gli strumenti di test dell'interfaccia utente, le API UiAutomation funzionano oltre i confini delle applicazioni, a differenza di quelli in Instrumentation.

    Eventi Systrace per le app

    Android 4.3 aggiunge la classe Trace con due metodi statici: beginSection() e endSection(), che ti consentono di definire blocchi di codice da includere nel report di Systrace. Creando di codice tracciabile nell'app, i log di systrace forniscono un'analisi analisi dei punti di rallentamento all'interno dell'app.

    Per informazioni sull'utilizzo dello strumento Systrace, consulta Analyzing Display and Performance with Systrace.

    Sicurezza

    Archivio chiavi Android per le chiavi private delle app

    Android ora offre un provider di sicurezza Java personalizzato nel KeyStore Android Key Store, che consente di generare e salvare chiavi private possono essere visti e utilizzati solo dalla tua app. Per caricare l'archivio chiavi Android, "AndroidKeyStore" a KeyStore.getInstance().

    Per gestire le credenziali private della tua app nell'Android Key Store, genera una nuova chiave con KeyPairGenerator con KeyPairGeneratorSpec. Prima ottieni un'istanza di KeyPairGenerator chiamando getInstance(). Quindi chiama initialize(), passandogli un'istanza KeyPairGeneratorSpec, che puoi usare usando KeyPairGeneratorSpec.Builder. Infine, ricevi KeyPair chiamando il numero generateKeyPair().

    Archivio credenziali hardware

    Android ora supporta anche lo spazio di archiviazione con supporto hardware per il tuo KeyChain e credenziali, fornendo maggiore sicurezza rendendo le chiavi non disponibili per l'estrazione. Vale a dire che, una volta le chiavi si trovano in un archivio chiavi supportato da hardware (Secure Element, TPM o TrustZone), possono essere utilizzate operazioni crittografiche, ma non è possibile esportare il materiale della chiave privata. Persino il kernel del sistema operativo non possono accedere a questo materiale della chiave. Non tutti i dispositivi Android supportano lo spazio di archiviazione su hardware, puoi verificare in fase di runtime se lo spazio di archiviazione supportato dall'hardware è disponibile chiamando KeyChain.IsBoundKeyAlgorithm().

    Dichiarazioni dei file manifest

    Funzionalità richieste dichiarabili

    I seguenti valori sono ora supportati in <uses-feature> per assicurarti che la tua app sia installata soltanto su dispositivi che offrono le funzionalità per le esigenze della tua app.

    FEATURE_APP_WIDGETS
    Dichiara che l'app offre un widget dell'app e deve essere installata solo su dispositivi con includere una schermata Home o un'area simile in cui gli utenti possono incorporare widget delle app. Esempio:
    <uses-feature android:name="android.software.app_widgets" android:required="true" />
    
    FEATURE_HOME_SCREEN
    Dichiara che l'app funziona come una sostituzione della schermata Home e deve essere installata soltanto su dispositivi che supportano app di terze parti nella schermata Home. Esempio:
    <uses-feature android:name="android.software.home_screen" android:required="true" />
    
    FEATURE_INPUT_METHODS
    Dichiara che l'app offre un metodo di immissione personalizzato (una tastiera creata con InputMethodService) e deve essere installata soltanto su dispositivi con supportano metodi di immissione di terze parti. Esempio:
    <uses-feature android:name="android.software.input_methods" android:required="true" />
    
    FEATURE_BLUETOOTH_LE
    Dichiara che l'app utilizza le API Bluetooth Low Energy e deve essere installata solo sui dispositivi in grado di comunicare con altri dispositivi tramite Bluetooth Low Energy. Esempio:
    <uses-feature android:name="android.software.bluetooth_le" android:required="true" />
    

    Autorizzazioni utente

    I seguenti valori sono ora supportati in <uses-permission> per dichiarare autorizzazioni richieste dalla tua app per accedere a determinate API.

    BIND_NOTIFICATION_LISTENER_SERVICE
    Necessari per utilizzare le nuove API NotificationListenerService.
    SEND_RESPOND_VIA_MESSAGE
    Necessari per ricevere i ACTION_RESPOND_VIA_MESSAGE l'intento.

    Per una visualizzazione dettagliata di tutte le modifiche API in Android 4.3, vedi Report Differenze API.