Ricevere dati da altre app

Così come un'app può inviare dati ad altre app, può anche riceverli da altre app. Pensa a come gli utenti interagiscono con la tua applicazione e quali tipi di dati vuoi ricevere da altre applicazioni. Ad esempio, un'applicazione di social networking potrebbe essere interessata a ricevere contenuti di testo, come un URL web interessante, da un'altra app.

In un'app che utilizza Compose Navigation, la ricezione dei dati inviati da un'altra app è un processo in tre passaggi:

  1. Dichiara un <intent-filter> nel manifest: devi comunque aggiungere un filtro per intent alla tua attività nel file AndroidManifest.xml. In questo modo, il sistema operativo Android sa che la tua applicazione è in grado di ricevere azioni specifiche (come ACTION_SEND) e tipi MIME (come text/plain).

  2. Definisci un navDeepLink nel grafico di navigazione di Compose: collega un navDeepLink corrispondente all'azione e al tipo MIME direttamente alla destinazione componibile che deve mostrare i contenuti. NavController intercetta automaticamente l'intent in entrata e indirizza l'utente direttamente a quella schermata.

  3. Estrai il payload dei dati in entrata: nella schermata di destinazione, accedi agli extra dell'intent (come EXTRA_TEXT o EXTRA_STREAM) per recuperare i contenuti condivisi e aggiornare lo stato della UI.

Le destinazioni di Condivisione diretta sono deep link a un'attività specifica all'interno della tua app. Spesso rappresentano una persona o un gruppo e vengono mostrate nell'Android Sharesheet. Ad esempio, un'app di messaggistica può fornire un target di Condivisione diretta per una persona che rimanda direttamente a una conversazione con quella persona. Per istruzioni dettagliate, consulta Fornisci target di Condivisione diretta.

Tipi MIME supportati

In teoria, un'app deve essere in grado di ricevere la più ampia gamma possibile di tipi MIME. Ad esempio, un'app di messaggistica progettata per l'invio di testo, immagini e video dovrebbe idealmente supportare la ricezione di text/*, image/* e video/*. Ecco alcuni tipi MIME comuni per l'invio e la ricezione di dati in Android.

I destinatari si registrano I mittenti inviano
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
image/*
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
Estensioni dei file supportate application/pdf

Consulta il registro ufficiale dei tipi di media MIME di IANA.

Crea target di condivisione efficaci

Quando gli utenti toccano un target di condivisione associato a un'attività specifica, consenti loro di confermare e modificare i contenuti condivisi prima che la tua app li utilizzi. Questo è particolarmente importante per i dati di testo.

Ricevi dati nella tua app

La ricezione di dati condivisi in un'app che utilizza Compose prevede la dichiarazione di filtri per intent nel manifest, il routing degli intent in entrata alla schermata corretta con i deep link e l'estrazione del payload dall'intent per aggiornare la UI.

Aggiorna il manifest

I filtri per intent informano il sistema su quali intent sono accettati da un componente dell'app. Analogamente a come hai creato un intent con un'azione ACTION_SEND nella lezione Invio di dati ad altre app, crei filtri per intent per ricevere intent con questa azione. Puoi definire un filtro per intent nel manifest utilizzando l'elemento <intent-filter>. Ad esempio, se la tua app gestisce la ricezione di contenuti di testo, un manifest che include una o più immagini di qualsiasi tipo sarà simile al seguente snippet:

<activity android:name=".ui.MyActivity" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

Quando un'altra app tenta di condividere uno di questi elementi creando un intent e passandolo a startActivity(), la tua applicazione viene elencata come opzione in Android Sharesheet o nel resolver degli intent. Se l'utente seleziona la tua app, viene avviata l'attività corrispondente (.ui.MyActivity nell'esempio precedente). Spetta poi a te gestire i contenuti in modo appropriato all'interno del codice e della UI.

In Compose Navigation, collega un navDeepLink direttamente alla destinazione componibile che deve mostrare i contenuti. Quando un'altra app condivide dati che corrispondono al tuo filtro per intent, Compose Navigation indirizza l'utente direttamente a questa destinazione:

navDeepLink corrisponde all'azione e al tipo MIME dell'intent in entrata per passare alla schermata di destinazione corretta. Una volta raggiunta la destinazione, il gestore controlla l'intent per determinare quale payload è stato ricevuto (ad esempio un'immagine singola o più immagini) ed estrae gli extra corrispondenti.

Gestisci i contenuti in arrivo

Per recuperare i contenuti pubblicati da un Intent, leggi l'attività corrente da LocalActivity.current all'interno del composable, quindi esamina l'intent per determinare cosa fare dopo. Se questa attività può essere avviata da altre parti del sistema (ad esempio l'Avvio app), tieni conto di questo aspetto quando esamini l'intent.

Presta particolare attenzione al controllo dei dati in entrata: potrebbe essere impostato un tipo MIME errato o l'immagine inviata potrebbe essere estremamente grande. Elabora i dati binari o le operazioni di I/O pesanti (come la decodifica di immagini di grandi dimensioni o la scrittura di file) in modo asincrono utilizzando le coroutine (come Dispatchers.IO) anziché nel thread dell'interfaccia utente principale.

@Composable
fun SharesheetHandler() {
    val activity = LocalActivity.current
    val intent = activity?.intent

    when (intent?.action) {
        Intent.ACTION_SEND -> {
            if (intent.type == "text/plain") {
                handleSendText(intent) // Handle text being sent
            } else if (intent.type?.startsWith("image/") == true) {
                handleSendImage(intent) // Handle single image being sent
            }
        }

        Intent.ACTION_SEND_MULTIPLE -> {
            if (intent.type?.startsWith("image/") == true) {
                handleSendMultipleImages(intent) // Handle multiple images being sent
            }
        }

        else -> {
            // Handle other intents, such as being started from the home screen
        }
    }
}

private fun handleSendText(intent: Intent) {
    intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
        // Update UI state with the shared text
    }
}

private fun handleSendImage(intent: Intent) {
    val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUri?.let {
        // Update UI state with the shared image
    }
}

private fun handleSendMultipleImages(intent: Intent) {
    val imageUris =
        IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUris?.let {
        // Update UI state with the shared images
    }
}

Quando estrai dati binari o URI da extra di intent (come EXTRA_STREAM), utilizza IntentCompat.getParcelableExtra() o IntentCompat.getParcelableArrayListExtra() dalla libreria AndroidX Core, come mostrato nelle funzioni handleSendImage e handleSendMultipleImages precedenti. Android 13 (livello API 33) ritira il metodo Intent.getParcelableExtra(String) non parametrizzato a favore di metodi con sicurezza dei tipi che accettano il tipo di classe previsto.

L'aggiornamento della UI dopo la ricezione dei dati può essere semplice come l'aggiornamento dello stato per compilare un TextField o complesso come l'applicazione di un filtro a un'immagine. Spetta alla tua app decidere cosa succede dopo.

Condivisione di URL di screenshot

Quando acquisisci uno screenshot, puoi condividere lo screenshot e qualsiasi URL associato. In questo modo, l'esperienza utente è più completa. Quando ricevi un URL, assicurati di recuperare il campo EXTRA_TEXT dall'intent, come mostrato nell'esempio seguente:

IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
    // Handle the EXTRA_TEXT as well
    val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
    // Update UI state with the shared image and the EXTRA_TEXT if available
}

Assicurati che gli utenti riconoscano la tua app

La tua app è rappresentata dalla relativa icona e dalla relativa etichetta in Android Sharesheet e nel resolver degli intent. Entrambi sono definiti nel manifest. Puoi impostare etichette di attività o filtri per intent per fornire un contesto più ampio.

A partire da Android 10 (livello API 29), Android Sharesheet utilizza solo le icone impostate nel manifest nel tag application. Android ignora le icone impostate sui tag intent-filter e activity.

Ricevere contenuti avanzati

Sebbene gli intent ACTION_SEND consentano di ricevere dati da Android Sharesheet e dal resolver degli intent a livello di attività o navigazione, le app possono anche ricevere contenuti avanzati (come immagini, video, file audio e testo con stile) tramite interazioni dirette con l'interfaccia utente. Questi meccanismi includono:

  • Incolla dagli appunti (menu Tocca e tieni premuto)
  • Inserimento di contenuti multimediali direttamente dalla tastiera su schermo (IME), ad esempio adesivi o GIF
  • Trascinamento di contenuti da un'altra app in modalità multi-finestra o schermo diviso

Nelle UI basate su View, Android 12 (livello API 31) e AndroidX Core 1.7 introducono l'API OnReceiveContentListener unificata. Questo listener consolida la gestione dei contenuti dagli appunti, dalla tastiera e dal trascinamento in un'unica callback. Per istruzioni dettagliate su come implementare questa funzionalità in Views, consulta Ricevi contenuti avanzati.

In Jetpack Compose, puoi gestire la ricezione di contenuti avanzati inseriti nei componenti dell'interfaccia utente (come i campi di testo) utilizzando il modificatore Modifier.contentReceiver o i modificatori di trascinamento.