Concedi l'accesso parziale a foto e video

Android 14 introduce l'accesso per le foto selezionate, che consente agli utenti di concedere alle app l'accesso a immagini e video specifici della loro raccolta, anziché concedere l'accesso a tutti i contenuti multimediali di un determinato tipo.

Questa modifica è attiva solo se la tua app ha come target Android 14 (livello API 34) o versioni successive. Se non utilizzi ancora il selettore di foto, ti consigliamo di implementarlo nella tua app per offrire un'esperienza coerente per la selezione di immagini e video che migliori anche la privacy dell'utente senza dover richiedere autorizzazioni per lo spazio di archiviazione.

Se gestisci il tuo selettore galleria utilizzando le autorizzazioni di archiviazione e devi mantenere il controllo completo sull'implementazione, adatta l'implementazione per utilizzare la nuova autorizzazione READ_MEDIA_VISUAL_USER_SELECTED. Se la tua app non utilizza la nuova autorizzazione, il sistema esegue l'app in modalità di compatibilità.

SDK target READ_MEDIA_VISUAL_USER_SELECTED dichiarato Accesso alle foto selezionate attivato Comportamento UX
SDK 33 No No N/A
Controllata dall'app
SDK 34 No Controllata dal sistema (compatto)
Controllata dall'app

La creazione del tuo selettore galleria richiede uno sviluppo e una manutenzione intensivi. Inoltre, la tua app deve richiedere autorizzazioni per lo spazio di archiviazione per ottenere il consenso esplicito dell'utente. Gli utenti possono rifiutare queste richieste oppure, se la tua app è in esecuzione su un dispositivo con Android 14 e ha come target Android 14 (livello API 34) o versioni successive, limitare l'accesso ai contenuti multimediali selezionati. L'immagine seguente mostra un esempio di richiesta di autorizzazioni e di selezione di contenuti multimediali utilizzando le nuove opzioni.

L'estensione .
Figura 1. La nuova finestra di dialogo consente a un utente di selezionare foto e video specifici che vuole rendere disponibili per la tua app, oltre alle consuete opzioni per concedere l'accesso completo o negare tutto l'accesso.

Questa sezione illustra l'approccio consigliato per creare il tuo selettore galleria utilizzando MediaStore. Se gestisci già un selettore galleria per la tua app e devi mantenere il controllo completo, puoi utilizzare questi esempi per adattare la tua implementazione. Se non aggiorni l'implementazione per gestire l'accesso a foto selezionate, il sistema esegue l'app in modalità di compatibilità.

Richiedi autorizzazioni

Innanzitutto, richiedi le autorizzazioni di archiviazione corrette nel file manifest Android, a seconda della versione del sistema operativo:

<!-- Devices running Android 12L (API level 32) or lower  -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

<!-- Devices running Android 13 (API level 33) or higher -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

<!-- To handle the reselection within the app on devices running Android 14
     or higher if your app targets Android 14 (API level 34) or higher.  -->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />

Quindi, richiedi le autorizzazioni di runtime corrette, a seconda della versione del sistema operativo:

// Register ActivityResult handler
val requestPermissions = registerForActivityResult(RequestMultiplePermissions()) { results ->
    // Handle permission requests results
    // See the permission example in the Android platform samples: https://github.com/android/platform-samples
}

// Permission request logic
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
    requestPermissions.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    requestPermissions.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO))
} else {
    requestPermissions.launch(arrayOf(READ_EXTERNAL_STORAGE))
}

Alcune app non richiedono autorizzazioni

A partire da Android 10 (livello API 29), le app non hanno più bisogno delle autorizzazioni per lo spazio di archiviazione per aggiungere file allo spazio di archiviazione condiviso. Ciò significa che le app possono aggiungere immagini alla galleria, registrare video e salvarli in uno spazio di archiviazione condiviso o scaricare fatture in PDF senza dover richiedere le autorizzazioni per lo spazio di archiviazione. Se la tua app aggiunge solo file allo spazio di archiviazione condiviso e non esegue query su immagini o video, devi interrompere la richiesta di autorizzazioni per lo spazio di archiviazione e impostare un valore maxSdkVersion di API 28 in AndroidManifest.xml:

<!-- No permission is needed to add files to shared storage on Android 10 (API level 29) or higher  -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />

Gestire la riselezione dei contenuti multimediali

Con la funzionalità di accesso a foto selezionate in Android 14, la tua app dovrebbe adottare la nuova autorizzazione READ_MEDIA_VISUAL_USER_SELECTED per controllare la riselezione dei contenuti multimediali e aggiornare l'interfaccia dell'app per consentire agli utenti di concedere all'app l'accesso a un insieme diverso di immagini e video. L'immagine seguente mostra un esempio di richiesta di autorizzazioni e di riselezione di contenuti multimediali:

L&#39;estensione .
Figura 2. La nuova finestra di dialogo consente inoltre a un utente di riselezionare le foto e i video da rendere disponibili nella tua app.

All'apertura della finestra di dialogo di selezione, vengono visualizzati foto, video o entrambi, a seconda delle autorizzazioni richieste. Ad esempio, se richiedi l'autorizzazione READ_MEDIA_VIDEO senza l'autorizzazione READ_MEDIA_IMAGES, nella UI verranno visualizzati solo i video in modo che gli utenti possano selezionare i file.

// Allow the user to select only videos
requestPermissions.launch(arrayOf(READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))

Puoi controllare se la tua app ha accesso completo, parziale o negato alla raccolta fotografica del dispositivo e aggiornare l'interfaccia di conseguenza. Richiedi queste autorizzazioni quando l'app ha bisogno dell'accesso allo spazio di archiviazione, anziché all'avvio. Tieni presente che la concessione dell'autorizzazione può essere modificata tra i callback del ciclo di vita dell'app onStart e onResume, poiché l'utente può modificare l'accesso nelle impostazioni senza chiudere l'app.

if (
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
    (
        ContextCompat.checkSelfPermission(context, READ_MEDIA_IMAGES) == PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(context, READ_MEDIA_VIDEO) == PERMISSION_GRANTED
    )
) {
    // Full access on Android 13 (API level 33) or higher
} else if (
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
    ContextCompat.checkSelfPermission(context, READ_MEDIA_VISUAL_USER_SELECTED) == PERMISSION_GRANTED
) {
    // Partial access on Android 14 (API level 34) or higher
}  else if (ContextCompat.checkSelfPermission(context, READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {
    // Full access up to Android 12 (API level 32)
} else {
    // Access denied
}

Eseguire query sulla raccolta dei dispositivi

Dopo aver verificato di avere accesso alle autorizzazioni corrette per lo spazio di archiviazione, puoi interagire con MediaStore per eseguire query sulla raccolta dei dispositivi (lo stesso approccio funziona anche se l'accesso concesso è parziale o completo):

data class Media(
    val uri: Uri,
    val name: String,
    val size: Long,
    val mimeType: String,
)

// Run the querying logic in a coroutine outside of the main thread to keep the app responsive.
// Keep in mind that this code snippet is querying only images of the shared storage.
suspend fun getImages(contentResolver: ContentResolver): List<Media> = withContext(Dispatchers.IO) {
    val projection = arrayOf(
        Images.Media._ID,
        Images.Media.DISPLAY_NAME,
        Images.Media.SIZE,
        Images.Media.MIME_TYPE,
    )

    val collectionUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        // Query all the device storage volumes instead of the primary only
        Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
    } else {
        Images.Media.EXTERNAL_CONTENT_URI
    }

    val images = mutableListOf<Media>()

    contentResolver.query(
        collectionUri,
        projection,
        null,
        null,
        "${Images.Media.DATE_ADDED} DESC"
    )?.use { cursor ->
        val idColumn = cursor.getColumnIndexOrThrow(Images.Media._ID)
        val displayNameColumn = cursor.getColumnIndexOrThrow(Images.Media.DISPLAY_NAME)
        val sizeColumn = cursor.getColumnIndexOrThrow(Images.Media.SIZE)
        val mimeTypeColumn = cursor.getColumnIndexOrThrow(Images.Media.MIME_TYPE)

        while (cursor.moveToNext()) {
            val uri = ContentUris.withAppendedId(collectionUri, cursor.getLong(idColumn))
            val name = cursor.getString(displayNameColumn)
            val size = cursor.getLong(sizeColumn)
            val mimeType = cursor.getString(mimeTypeColumn)

            val image = Media(uri, name, size, mimeType)
            images.add(image)
        }
    }

    return@withContext images
}

Questo snippet di codice è stato semplificato per illustrare come interagire con MediaStore. In un'app pronta per la produzione, utilizza l'impaginazione con elementi come la libreria di creazione dei pacchetti per garantire buone prestazioni.

Esegui una query sull'ultima selezione

Le app su Android 15 e versioni successive e su Android 14 con il supporto degli aggiornamenti di sistema Google Play possono eseguire query sull'ultima selezione di immagini e video effettuata dall'utente ad accesso parziale attivando QUERY_ARG_LATEST_SELECTION_ONLY:

if (getExtensionVersion(Build.VERSION_CODES.U) >= 12) {
    val queryArgs = bundleOf(
        QUERY_ARG_SQL_SORT_ORDER to "${Images.Media.DATE_ADDED} DESC"
        QUERY_ARG_LATEST_SELECTION_ONLY to true
    )

    contentResolver.query(collectionUri, projection, queryArgs, null)
}

L'accesso a foto e video viene mantenuto quando viene eseguito l'upgrade del dispositivo

Nei casi in cui la tua app si trovi su un dispositivo su cui viene eseguito l'upgrade da una versione precedente di Android ad Android 14, il sistema mantiene l'accesso completo alle foto e ai video dell'utente e concede automaticamente alcune autorizzazioni alla tua app. Il comportamento esatto dipende dall'insieme di autorizzazioni concesse alla tua app prima che il dispositivo esegua l'upgrade ad Android 14.

Autorizzazioni da Android 13

Considera la seguente situazione:

  1. La tua app è installata su un dispositivo con Android 13.
  2. L'utente ha concesso le autorizzazioni READ_MEDIA_IMAGES e READ_MEDIA_VIDEO alla tua app.
  3. Il dispositivo esegue quindi l'upgrade ad Android 14 mentre l'app è ancora installata.
  4. La tua app inizia ad avere come target Android 14 (livello API 34) o versioni successive.

In questo caso, la tua app ha ancora accesso completo alle foto e ai video dell'utente. Il sistema mantiene anche le autorizzazioni READ_MEDIA_IMAGES e READ_MEDIA_VIDEO concesse automaticamente alla tua app.

Autorizzazioni da Android 12 e versioni precedenti

Considera la seguente situazione:

  1. La tua app è installata su un dispositivo con Android 13.
  2. L'utente ha concesso l'autorizzazione READ_EXTERNAL_STORAGE o WRITE_EXTERNAL_STORAGE alla tua app.
  3. Il dispositivo esegue quindi l'upgrade ad Android 14 mentre l'app è ancora installata.
  4. La tua app inizia ad avere come target Android 14 (livello API 34) o versioni successive.

In questo caso, la tua app ha ancora accesso completo alle foto e ai video dell'utente. Il sistema concede automaticamente anche l'autorizzazione READ_MEDIA_IMAGES e l'autorizzazione READ_MEDIA_VIDEO alla tua app.

best practice

Questa sezione contiene diverse best practice per l'utilizzo dell'autorizzazione READ_MEDIA_VISUAL_USER_SELECTED. Per ulteriori informazioni, consulta le nostre best practice sulle autorizzazioni.

Non archiviare in modo permanente lo stato di autorizzazione

Non archiviare lo stato di autorizzazione in modo permanente, inclusi SharedPreferences o DataStore. Lo stato archiviato potrebbe non essere sincronizzato con lo stato effettivo. Lo stato dell'autorizzazione può cambiare dopo la reimpostazione dell'autorizzazione, la ibernazione dell'app, una modifica avviata dall'utente nelle impostazioni dell'app o quando l'app passa in background. Controlla invece le autorizzazioni per lo spazio di archiviazione utilizzando ContextCompat.checkSelfPermission().

Non dare per scontato l'accesso completo a foto e video

A seconda delle modifiche introdotte in Android 14, la tua app potrebbe avere accesso solo parziale alla raccolta fotografica del dispositivo. Se l'app memorizza i dati di MediaStore nella cache quando viene eseguita una query utilizzando ContentResolver, la cache potrebbe non essere aggiornata.

  • Esegui sempre la query su MediaStore utilizzando ContentResolver, anziché utilizzare una cache archiviata.
  • Mantieni i risultati in memoria mentre l'app è in primo piano.
  • Aggiorna i risultati quando la tua app attraversa il ciclo di vita dell'app onResume, in quanto l'utente potrebbe passare dall'accesso completo all'accesso parziale tramite le impostazioni dell'autorizzazione.

Considera l'accesso URI come temporaneo

Se l'utente sceglie Seleziona foto e video nella finestra di dialogo delle autorizzazioni di sistema, l'accesso della tua app alle foto e ai video selezionati scadrà alla fine. La tua app deve sempre gestire il caso di non avere accesso a Uri, a prescindere dalla loro autorità.

Filtra tipo di media selezionabile per autorizzazione

La finestra di dialogo di selezione è sensibile al tipo di autorizzazione richiesto:

  • Se richiedi solo READ_MEDIA_IMAGES, vengono mostrate solo le immagini selezionabili.
  • Se richiedi solo READ_MEDIA_VIDEO, viene mostrato solo il video selezionabile.
  • Se richiedi sia READ_MEDIA_IMAGES sia READ_MEDIA_VIDEO, l'intera raccolta fotografica è selezionabile.

In base ai casi d'uso della tua app, devi assicurarti di richiedere le autorizzazioni appropriate per evitare un'esperienza utente negativa. Se una funzionalità prevede solo che i video vengano selezionati, assicurati di richiederne solo READ_MEDIA_VIDEO.

Richiedi le autorizzazioni in una singola operazione

Per impedire agli utenti di visualizzare più finestre di dialogo del runtime del sistema, richiedi le autorizzazioni READ_MEDIA_VISUAL_USER_SELECTED, ACCESS_MEDIA_LOCATION e "Lettura contenuti multimediali" (READ_MEDIA_IMAGES, READ_MEDIA_VIDEO o entrambe) in un'unica operazione.

Consenti agli utenti di gestire la propria selezione

Quando l'utente sceglie la modalità di accesso parziale, l'app non deve presupporre che la raccolta fotografica del dispositivo sia vuota e dovrebbe consentire all'utente di concedere più file.

L'utente può decidere di passare dall'accesso completo all'accesso parziale tramite le impostazioni di autorizzazione senza concedere l'accesso ad alcuni file multimediali visivi.

Modalità di compatibilità

Se gestisci il tuo selettore galleria utilizzando le autorizzazioni di archiviazione, ma non hai adattato la tua app per utilizzare la nuova autorizzazione READ_MEDIA_VISUAL_USER_SELECTED, il sistema esegue l'app in modalità di compatibilità ogni volta che l'utente deve selezionare o riselezionare i contenuti multimediali.

Comportamento durante la selezione iniziale dei contenuti multimediali

Durante la selezione iniziale, se un utente sceglie l'opzione "Seleziona foto e video" (vedi Figura 1), durante la sessione dell'app vengono concesse le autorizzazioni READ_MEDIA_IMAGES e READ_MEDIA_VIDEO, fornendo la concessione di un'autorizzazione temporanea e l'accesso temporaneo alle foto e ai video selezionati dall'utente. Quando la tua app passa in background o quando l'utente termina attivamente l'app, il sistema alla fine nega queste autorizzazioni. Questo comportamento è simile a quello delle altre autorizzazioni una tantum.

Comportamento durante la rielezione dei media

Se la tua app deve accedere ad altri video e foto in un secondo momento, devi richiedere manualmente l'autorizzazione READ_MEDIA_IMAGES o l'autorizzazione READ_MEDIA_VIDEO. Il sistema segue lo stesso flusso della richiesta di autorizzazione iniziale, invitando gli utenti a selezionare foto e video (vedi la Figura 2).

Se la tua app segue le best practice relative alle autorizzazioni, questa modifica non dovrebbe compromettere la tua app. Ciò vale in particolare se l'app non presuppone che l'accesso all'URI sia mantenuto, archivia lo stato di autorizzazione di sistema o aggiorna l'insieme di immagini visualizzate dopo la modifica dell'autorizzazione. Tuttavia, questo comportamento potrebbe non essere ideale, a seconda del caso d'uso della tua app. Per offrire agli utenti la migliore esperienza possibile, ti consigliamo di implementare il selettore di foto o di adattare il selettore galleria dell'app per gestire questo comportamento direttamente utilizzando l'autorizzazione READ_MEDIA_VISUAL_USER_SELECTED.