Accorder un accès limité aux photos et aux vidéos

Android 14 introduit l'accès aux photos sélectionnées, qui permet aux utilisateurs d'accorder aux applications l'accès à des images et des vidéos spécifiques de leur bibliothèque, plutôt que d'accorder l'accès à tous les contenus multimédias d'un type donné.

Cette modification n'est activée que si votre application cible Android 14 (niveau d'API 34) ou version ultérieure. Si vous n'utilisez pas encore le sélecteur de photos, nous vous recommandons de l'implémenter dans votre application pour offrir une expérience cohérente de sélection d'images et de vidéos, tout en améliorant la confidentialité des utilisateurs, sans avoir à demander d'autorisations de stockage.

Si vous gérez votre propre sélecteur de galerie à l'aide d'autorisations de stockage et que vous devez garder un contrôle total sur votre implémentation, adaptez-la pour qu'elle utilise la nouvelle autorisation READ_MEDIA_VISUAL_USER_SELECTED. Si votre application n'utilise pas la nouvelle autorisation, le système l'exécute dans un mode de compatibilité.

SDK cible READ_MEDIA_VISUAL_USER_SELECTED déclaré Accès aux photos sélectionnées activé Comportement de l'expérience utilisateur
SDK 33 Non Non N/A
Oui Oui Contrôle par l'application
SDK 34 Non Oui Contrôlées par le système (comportement de compatibilité)
Oui Oui Contrôle par l'application

La création de votre propre sélecteur de galerie nécessite des opérations de développement et de maintenance importantes. Votre application doit demander des autorisations d'accès à l'espace de stockage pour obtenir le consentement explicite de l'utilisateur. Les utilisateurs peuvent refuser ces requêtes ou, si votre application s'exécute sur un appareil équipé d'Android 14 et cible Android 14 (niveau d'API 34) ou version ultérieure, limiter l'accès aux contenus multimédias sélectionnés. L'image suivante montre un exemple de demande d'autorisations et de sélection de médias à l'aide des nouvelles options.

L'extension .
Figure 1. La nouvelle boîte de dialogue permet à un utilisateur de sélectionner les photos et vidéos spécifiques qu'il souhaite mettre à la disposition de votre application, en plus des options habituelles pour accorder un accès complet ou refuser tout accès.

Cette section présente l'approche recommandée pour créer votre propre sélecteur de galerie à l'aide de MediaStore. Si vous gérez déjà un sélecteur de galerie pour votre application et que vous devez en conserver le contrôle total, vous pouvez adapter votre implémentation à l'aide de ces exemples. Si vous ne mettez pas à jour votre implémentation pour gérer l'accès aux photos sélectionnées, le système exécute votre application en mode de compatibilité.

Demander des autorisations

Tout d'abord, demandez les autorisations de stockage appropriées dans le fichier manifeste Android, en fonction de la version de l'OS:

<!-- 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" />

Ensuite, demandez les autorisations d'exécution appropriées, également en fonction de la version de l'OS:

// 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))
}

Certaines applis n'ont pas besoin d'autorisations

À partir d'Android 10 (niveau d'API 29), les applications n'ont plus besoin d'autorisations de stockage pour ajouter des fichiers à l'espace de stockage partagé. Cela signifie que les applications peuvent ajouter des images à la galerie, enregistrer des vidéos et les enregistrer dans un espace de stockage partagé, ou télécharger des factures PDF sans avoir à demander d'autorisations de stockage. Si votre application n'ajoute que des fichiers à l'espace de stockage partagé et n'interroge pas les images ni les vidéos, vous devez cesser de demander des autorisations de stockage et définir une maxSdkVersion d'API 28 dans votre 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" />

Gérer la resélection des contenus multimédias

Avec la fonctionnalité d'accès aux photos sélectionnées sous Android 14, votre application doit adopter la nouvelle autorisation READ_MEDIA_VISUAL_USER_SELECTED pour contrôler la sélection des contenus multimédias et mettre à jour l'interface de votre application pour permettre aux utilisateurs d'accorder à votre application l'accès à un autre ensemble d'images et de vidéos. L'image suivante montre un exemple de demande d'autorisations et de resélection d'un contenu multimédia:

L&#39;extension .
Figure 2. La nouvelle boîte de dialogue permet également à l'utilisateur de sélectionner à nouveau les photos et vidéos qu'il souhaite mettre à la disposition de votre application.

Lorsque vous ouvrez la boîte de dialogue de sélection, des photos, des vidéos ou les deux s'affichent en fonction des autorisations demandées. Par exemple, si vous demandez l'autorisation READ_MEDIA_VIDEO sans l'autorisation READ_MEDIA_IMAGES, seules les vidéos apparaîtront dans l'interface utilisateur pour que les utilisateurs puissent sélectionner des fichiers.

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

Vous pouvez vérifier si votre application dispose d'un accès complet, partiel ou refusé à la bibliothèque photo de l'appareil et mettre à jour votre interface en conséquence. Demandez ces autorisations lorsque l'application a besoin d'accéder à l'espace de stockage, plutôt qu'au démarrage. N'oubliez pas que l'autorisation d'accès peut être modifiée entre les rappels de cycle de vie de l'application onStart et onResume, car l'utilisateur peut modifier l'accès dans les paramètres sans fermer votre application.

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
}

Interroger la bibliothèque d'appareils

Après avoir vérifié que vous avez accès aux autorisations de stockage appropriées, vous pouvez interagir avec MediaStore pour interroger la bibliothèque d'appareils (la même approche fonctionne, que l'accès accordé soit partiel ou complet):

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
}

Cet extrait de code est simplifié pour illustrer comment interagir avec MediaStore. Dans une application prête pour la production, utilisez la pagination avec un élément comme la bibliothèque Paging pour garantir de bonnes performances.

Interroger la dernière sélection

Les applications sous Android 15 et versions ultérieures et Android 14 compatibles avec les mises à jour du système Google Play peuvent interroger la dernière sélection d'images et de vidéos effectuées par l'utilisateur en accès partiel en activant 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'accès aux photos et vidéos est préservé lorsque l'appareil est mis à niveau

Si votre application est installée sur un appareil qui met à niveau une version antérieure d'Android vers Android 14, le système conserve un accès complet aux photos et vidéos de l'utilisateur et accorde automatiquement certaines autorisations à votre application. Le comportement exact dépend de l'ensemble d'autorisations accordées à votre application avant la mise à niveau de l'appareil vers Android 14.

Autorisations d'Android 13

Prenons la situation suivante :

  1. Votre application est installée sur un appareil équipé d'Android 13.
  2. L'utilisateur a accordé les autorisations READ_MEDIA_IMAGES et READ_MEDIA_VIDEO à votre application.
  3. L'appareil passe ensuite à Android 14 et votre application n'est pas désinstallée.
  4. Votre application commence à cibler Android 14 (niveau d'API 34) ou version ultérieure.

Dans ce cas, votre application dispose d'un accès complet aux photos et vidéos de l'utilisateur. Le système conserve également les autorisations READ_MEDIA_IMAGES et READ_MEDIA_VIDEO accordées automatiquement à votre application.

Autorisations d'Android 12 et versions antérieures

Prenons la situation suivante :

  1. Votre application est installée sur un appareil équipé d'Android 13.
  2. L'utilisateur a accordé l'autorisation READ_EXTERNAL_STORAGE ou WRITE_EXTERNAL_STORAGE à votre application.
  3. L'appareil passe ensuite à Android 14 et votre application n'est pas désinstallée.
  4. Votre application commence à cibler Android 14 (niveau d'API 34) ou version ultérieure.

Dans ce cas, votre application dispose d'un accès complet aux photos et vidéos de l'utilisateur. Le système accorde également automatiquement l'autorisation READ_MEDIA_IMAGES et l'autorisation READ_MEDIA_VIDEO à votre application.

pour réussir votre lancement

Cette section contient plusieurs bonnes pratiques concernant l'utilisation de l'autorisation READ_MEDIA_VISUAL_USER_SELECTED. Pour en savoir plus, consultez nos bonnes pratiques concernant les autorisations.

Ne pas stocker l'état d'autorisation de manière permanente

Ne stockez pas l'état d'autorisation de manière permanente, y compris SharedPreferences ou DataStore. L'état stocké peut ne pas être synchronisé avec l'état réel. L'état de l'autorisation peut changer après la réinitialisation de l'autorisation, l'hibernation de l'application, une modification des paramètres de votre application à l'initiative de l'utilisateur ou lorsque votre application passe en arrière-plan. Vérifiez plutôt les autorisations de stockage à l'aide de ContextCompat.checkSelfPermission().

Ne pas supposer que vous avez un accès complet aux photos et vidéos

En raison des modifications introduites dans Android 14, il est possible que votre application ne dispose que d'un accès partiel à la bibliothèque de photos de l'appareil. Si l'application met en cache des données MediaStore lorsqu'elle est interrogée à l'aide de ContentResolver, une mise à jour du cache est peut-être nécessaire.

  • Interrogez toujours MediaStore à l'aide de ContentResolver, au lieu d'utiliser un cache stocké.
  • Gardez les résultats en mémoire lorsque votre application est au premier plan.
  • Actualisez les résultats lorsque votre application passe par le cycle de vie de l'application onResume, car l'utilisateur peut passer d'un accès complet à un accès partiel via les paramètres d'autorisation.

Traiter l'accès à l'URI comme temporaire

Si l'utilisateur choisit Sélectionner des photos et des vidéos dans la boîte de dialogue des autorisations système, l'accès de votre application aux photos et vidéos sélectionnées expire. Votre application doit toujours gérer l'absence d'accès à un Uri, quelle que soit son autorité.

Filtrer le type de contenu sélectionnable en fonction de l'autorisation

La boîte de dialogue de sélection tient compte du type d'autorisation demandé:

  • Si vous ne demandez que READ_MEDIA_IMAGES, seules les images pouvant être sélectionnées s'affichent.
  • Si vous ne demandez que READ_MEDIA_VIDEO, seule la vidéo peut être sélectionnée.
  • Si vous demandez à la fois READ_MEDIA_IMAGES et READ_MEDIA_VIDEO, vous pouvez sélectionner toute la bibliothèque photo.

En fonction des cas d'utilisation de votre application, assurez-vous de demander les autorisations appropriées pour éviter une mauvaise expérience utilisateur. Si une fonctionnalité ne nécessite que la sélection de vidéos, veillez à ne demander que READ_MEDIA_VIDEO.

Demander des autorisations en une seule opération

Pour empêcher les utilisateurs de voir plusieurs boîtes de dialogue d'exécution du système, demandez les autorisations READ_MEDIA_VISUAL_USER_SELECTED, ACCESS_MEDIA_LOCATION et "lecture des médias" (READ_MEDIA_IMAGES, READ_MEDIA_VIDEO ou les deux) lors d'une même opération.

Autoriser les utilisateurs à gérer leur sélection

Lorsque l'utilisateur choisit le mode d'accès partiel, votre application ne doit pas supposer que la bibliothèque de photos de l'appareil est vide, mais doit permettre à l'utilisateur d'accorder plus de fichiers.

L'utilisateur peut décider de passer d'un accès complet à un accès partiel via les paramètres d'autorisation sans accorder l'accès à certains fichiers multimédias visuels.

Mode de compatibilité

Si vous gérez votre propre sélecteur de galerie en utilisant des autorisations de stockage, mais que vous n'avez pas adapté votre application à la nouvelle autorisation READ_MEDIA_VISUAL_USER_SELECTED, le système exécute votre application en mode de compatibilité chaque fois que l'utilisateur doit sélectionner ou resélectionner des contenus multimédias.

Comportement lors de la sélection initiale du support

Lors de la sélection initiale, si un utilisateur choisit "Sélectionner des photos et des vidéos" (voir la figure 1), les autorisations READ_MEDIA_IMAGES et READ_MEDIA_VIDEO sont accordées pendant la session de l'application, ce qui fournit une autorisation et un accès temporaires aux photos et vidéos sélectionnées par l'utilisateur. Lorsque votre application passe en arrière-plan ou lorsque l'utilisateur la ferme activement, le système finit par refuser ces autorisations. Ce comportement est similaire à celui d'autres autorisations ponctuelles.

Comportement lors de la resélection du support

Si votre application a besoin d'accéder à des photos et vidéos supplémentaires ultérieurement, vous devez redemander manuellement l'autorisation READ_MEDIA_IMAGES ou READ_MEDIA_VIDEO. Le système suit le même flux que pour la demande d'autorisation initiale, invitant les utilisateurs à sélectionner des photos et des vidéos (voir la figure 2).

Si votre application respecte les bonnes pratiques concernant les autorisations, cette modification ne devrait pas l'endommager. Cela est particulièrement vrai si votre application ne suppose pas que l'accès à l'URI est conservé, stocke l'état de l'autorisation système ou actualise l'ensemble des images affichées après le changement d'autorisation. Toutefois, ce comportement n'est peut-être pas idéal selon le cas d'utilisation de votre application. Pour offrir la meilleure expérience utilisateur possible, nous vous recommandons d'implémenter le sélecteur de photos ou d'adapter le sélecteur de galerie de votre application pour gérer ce comportement directement à l'aide de l'autorisation READ_MEDIA_VISUAL_USER_SELECTED.