Ricevi contenuti avanzati

Figura 1. L'API unificata fornisce un unico punto per gestire i contenuti in entrata, indipendentemente dal meccanismo dell'interfaccia utente specifico, ad esempio l'incollatura dal menu di tocco e pressione o l'utilizzo del trascinamento.

Gli utenti amano immagini, video e altri contenuti espressivi, ma l'inserimento e lo spostamento di questi contenuti nelle app non è sempre facile. Per semplificare la ricezione di contenuti avanzati da parte delle app, Android 12 (livello API 31) introduce un'API unificata che consente alla tua app di accettare contenuti da qualsiasi origine: appunti, tastiera o trascinamento.

Puoi collegare un'interfaccia, ad esempio OnReceiveContentListener, ai componenti dell'interfaccia utente e ricevere un callback quando i contenuti vengono inseriti tramite qualsiasi meccanismo. Il callback diventa l'unico punto in cui il codice può gestire la ricezione di tutti i contenuti, dal testo semplice e formattato al markup, alle immagini, ai video, ai file audio e altro ancora.

Per la compatibilità con le versioni precedenti di Android, questa API è anche disponibile in AndroidX, a partire da Core 1.7 e Appcompat 1.4, che ti consigliamo di utilizzare quando implementi questa funzionalità.

Panoramica

Con le altre API esistenti, ogni meccanismo dell'interfaccia utente, ad esempio il menu di tocco e pressione o il trascinamento, ha la propria API corrispondente. Ciò significa che devi eseguire l'integrazione con ogni API separatamente, aggiungendo codice simile per ogni meccanismo che inserisce contenuti:

Un'immagine che mostra le diverse azioni e l'API relativa da implementare
Figura 2. In precedenza, le app implementavano un'API diversa per ogni meccanismo dell'interfaccia utente per l'inserimento di contenuti.

L'API OnReceiveContentListener consolida questi diversi percorsi di codice creando una singola API da implementare, in modo che tu possa concentrarti sulla logica specifica dell'app e lasciare che la piattaforma gestisca il resto:

Un'immagine che mostra l'API unificata semplificata
Figura 3. L'API unificata consente di implementare una singola API che supporta tutti i meccanismi dell'interfaccia utente.

Questo approccio significa anche che quando vengono aggiunti nuovi modi per inserire contenuti nella piattaforma, non devi apportare modifiche aggiuntive al codice per abilitare il supporto nella tua app. Se la tua app deve implementare una personalizzazione completa per un caso d'uso specifico, puoi comunque utilizzare le API esistenti, che continuano a funzionare allo stesso modo.

Implementazione

L'API è un'interfaccia di listener con un singolo metodo, OnReceiveContentListener. Per supportare le versioni precedenti della piattaforma Android, ti consigliamo di utilizzare l' interfaccia OnReceiveContentListener corrispondente nella libreria AndroidX Core.

Per utilizzare l'API, implementa il listener specificando i tipi di contenuti che la tua app può gestire:

Kotlin

object MyReceiver : OnReceiveContentListener {
    val MIME_TYPES = arrayOf("image/*", "video/*")
    
    // ...
    
    override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? {
        TODO("Not yet implemented")
    }
}

Java

public class MyReceiver implements OnReceiveContentListener {
     public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"};
     // ...
}

Dopo aver specificato tutti i tipi MIME di contenuti supportati dalla tua app, implementa il resto del listener:

Kotlin

class MyReceiver : OnReceiveContentListener {
    override fun onReceiveContent(view: View, contentInfo: ContentInfoCompat): ContentInfoCompat {
        val split = contentInfo.partition { item: ClipData.Item -> item.uri != null }
        val uriContent = split.first
        val remaining = split.second
        if (uriContent != null) {
            // App-specific logic to handle the URI(s) in uriContent.
        }
        // Return anything that your app didn't handle. This preserves the
        // default platform behavior for text and anything else that you aren't
        // implementing custom handling for.
        return remaining
    }

    companion object {
        val MIME_TYPES = arrayOf("image/*", "video/*")
    }
}

Java

 public class MyReceiver implements OnReceiveContentListener {
     public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"};

     @Override
     public ContentInfoCompat onReceiveContent(View view, ContentInfoCompat contentInfo) {
         Pair<ContentInfoCompat, ContentInfoCompat> split = contentInfo.partition(
                 item -> item.getUri() != null);
         ContentInfo uriContent = split.first;
         ContentInfo remaining = split.second;
         if (uriContent != null) {
             // App-specific logic to handle the URI(s) in uriContent.
         }
         // Return anything that your app didn't handle. This preserves the
         // default platform behavior for text and anything else that you aren't
         // implementing custom handling for.
         return remaining;
     }
 }

Se la tua app supporta già la condivisione con gli intent, puoi riutilizzare la logica specifica dell'app per la gestione degli URI dei contenuti. Restituisci tutti i dati rimanenti per delegare la gestione di questi dati alla piattaforma.

Dopo aver implementato il listener, impostalo sugli elementi dell'interfaccia utente appropriati nella tua app:

Kotlin

class MyActivity : Activity() {
    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        val myInput = findViewById(R.id.my_input)
        ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, MyReceiver())
    }
}

Java

public class MyActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
         // ...

         AppCompatEditText myInput = findViewById(R.id.my_input);
         ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, new MyReceiver());
     }
}

Autorizzazioni URI

Le autorizzazioni di lettura vengono concesse e rilasciate automaticamente dalla piattaforma per tutti gli URI dei contenuti nel payload passato a OnReceiveContentListener.

In genere, la tua app elabora gli URI dei contenuti in un servizio o in un'attività. Per l'elaborazione a lunga esecuzione, utilizza WorkManager. Quando implementi questa funzionalità, estendi le autorizzazioni al servizio o all'attività di destinazione passando i contenuti utilizzando Intent.setClipData e impostando il flag FLAG_GRANT_READ_URI_PERMISSION.

In alternativa, puoi utilizzare un thread in background nel contesto corrente per elaborare i contenuti. In questo caso, devi mantenere un riferimento all'oggetto payload ricevuto dal listener per assicurarti che le autorizzazioni non vengano revocate prematuramente dalla piattaforma.

Elementi View personalizzati

Se la tua app utilizza una sottoclasse View personalizzata, assicurati che OnReceiveContentListener non venga ignorato.

Se la classe View esegue l'override del onCreateInputConnection metodo, utilizza l'API Jetpack InputConnectionCompat.createWrapper per configurare InputConnection.

Se la classe View esegue l'override del onTextContextMenuItem metodo, delega a super quando la voce di menu è R.id.paste o R.id.pasteAsPlainText.

Confronto con l'API per le immagini della tastiera

Puoi considerare l'API OnReceiveContentListener come la versione successiva dell' API per le immagini della tastiera esistente. Questa API unificata supporta la funzionalità dell'API per le immagini della tastiera, nonché alcune funzionalità aggiuntive. La compatibilità con dispositivi e funzionalità varia a seconda che tu utilizzi la libreria Jetpack o le API native dell'SDK Android.

Tabella 1. Funzionalità supportate e livelli API per Jetpack.
Azione o funzionalità Supportata dall'API per le immagini della tastiera Supportata dall'API unificata
Inserisci dalla tastiera Sì (livello API 13 e versioni successive) Sì (livello API 13 e versioni successive)
Inserisci utilizzando l'opzione Incolla dal menu di tocco e pressione No
Inserisci utilizzando il trascinamento No Sì (livello API 24 e versioni successive)
Tabella 2. Funzionalità supportate e livelli API per le API native API.
Azione o funzionalità Supportata dall'API per le immagini della tastiera Supportata dall'API unificata
Inserisci dalla tastiera Sì (livello API 25 e versioni successive) Sì (Android 12 e versioni successive)
Inserisci utilizzando l'opzione Incolla dal menu di tocco e pressione No
Inserisci utilizzando il trascinamento No