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'autoriser les applications à accéder à des images et des vidéos spécifiques de leur bibliothèque, plutôt qu'à l'ensemble des 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 utiliser la nouvelle autorisation READ_MEDIA_VISUAL_USER_SELECTED. Si votre application n'utilise pas la nouvelle autorisation, le système l'exécute en mode de compatibilité.

SDK cible READ_MEDIA_VISUAL_USER_SELECTED déclaré Accès aux photos 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ôle 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 qu'elle 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 contenus multimé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 garder le contrôle total, vous pouvez utiliser ces exemples pour adapter votre implémentation. 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 du système d'exploitation:

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

Demandez ensuite les autorisations d'exécution appropriées, 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 le stockage partagé, ou télécharger des factures PDF sans avoir à demander des autorisations de stockage. Si votre application n'ajoute que des fichiers au stockage partagé et ne interroge pas d'images ni de vidéos, vous devez cesser de demander des autorisations de stockage et définir une maxSdkVersion de l'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 nouvelle sélection de contenus multimédias

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

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 à 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 s'affichent dans l'UI 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 au stockage, et non au démarrage. N'oubliez pas que l'octroi d'autorisation peut être modifié 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 disposez des autorisations de stockage appropriées, vous pouvez interagir avec MediaStore pour interroger la bibliothèque de l'appareil (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.

Bonnes pratiques

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 par 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 apportées par 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 à n'importe quel 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 est sensible au type d'autorisation demandé:

  • Si vous ne demandez que READ_MEDIA_IMAGES, seules les images peuvent être sélectionnées.
  • 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, l'ensemble de la bibliothèque de photos peut être sélectionné.

En fonction des cas d'utilisation de votre application, vous devez vous assurer de demander les autorisations appropriées pour éviter une mauvaise expérience utilisateur. Si une fonctionnalité ne s'attend qu'à des vidéos sélectionnées, 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 à l'aide d'autorisations de stockage, mais que vous n'avez pas adapté votre application pour utiliser la nouvelle autorisation READ_MEDIA_VISUAL_USER_SELECTED, le système exécute votre application en mode compatibilité chaque fois que l'utilisateur doit sélectionner ou sélectionner à nouveau des contenus multimédias.

Comportement lors de la sélection initiale des contenus multimédias

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. Elles donnent 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 que l'utilisateur la ferme volontairement, le système finit par refuser ces autorisations. Ce comportement est similaire à celui d'autres autorisations ponctuelles.

Comportement lors de la ré-sélection de contenu multimédia

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 suit les bonnes pratiques en matière d'autorisations, cette modification ne devrait pas affecter votre application. 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 la modification de l'autorisation. Toutefois, ce comportement peut ne pas être idéal en fonction du cas d'utilisation de votre application. Pour offrir une expérience optimale à vos utilisateurs, nous vous recommandons d'implémenter un 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.