Android 14 presenta el acceso seleccionado a Fotos, que permite a los usuarios otorgar a las apps acceso a imágenes y videos específicos de su biblioteca, en lugar de otorgarles acceso a todo el contenido multimedia de un tipo determinado.
Este cambio solo estará habilitado si tu app se orienta a Android 14 (nivel de API 34) o mayores. Si todavía no usas el selector de fotos, te recomendamos que lo implementes en tu app para brindar una experiencia coherente para seleccionar imágenes y videos que también mejora la privacidad del usuario sin tener que solicitar ningún almacenamiento permisos.
Si mantienes tu propio selector de galería con permisos de almacenamiento y necesitas
mantener el control total de su implementación, adaptarla
para usar el nuevo permiso READ_MEDIA_VISUAL_USER_SELECTED
. Si su aplicación
no usa el nuevo permiso, el sistema ejecuta tu app en una compatibilidad
automático.
SDK de destino | Se declaró READ_MEDIA_VISUAL_USER_SELECTED |
Se habilitó el acceso a las fotos seleccionadas | Comportamiento de UX |
---|---|---|---|
SDK 33 | No | No | N/A |
Sí | Sí | Controlado por la app | |
SDK 34 | No | Sí | Controlado por el sistema (comportamiento compatible) |
Sí | Sí | Controlado por la app |
Crea o adapta tu propio selector de galería
La creación de su propio selector de galería requiere un extenso desarrollo y mantenimiento, y tu app debe solicitar permisos de almacenamiento para obtener el consentimiento explícito del usuario. Los usuarios pueden rechazar estas solicitudes o, si tu app se ejecuta en un dispositivo con Android 14 y tu app se orienta a Android 14 (nivel de API 34) o versiones posteriores, limita acceso a contenido multimedia seleccionado. En la siguiente imagen, se muestra un ejemplo de cómo solicitar permisos y seleccionar contenido multimedia con las nuevas opciones.
Esta sección demuestra el enfoque recomendado para crear tu propia galería.
selector con MediaStore
. Si ya mantienes un selector de galería para tu app
y necesitas mantener el control total, puedes usar estos ejemplos para adaptar
para implementarlos. Si no actualizas tu implementación para que controle los elementos seleccionados
Photos Access, el sistema ejecuta tu app en un modo de compatibilidad.
Solicita permisos
Primero, solicita los permisos de almacenamiento correctos en el manifiesto de Android. según la versión del SO:
<!-- 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" />
Luego, solicita los permisos de tiempo de ejecución correctos, según la versión del SO:
// 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))
}
Algunas apps no necesitan permisos
A partir de Android 10 (nivel de API 29), las apps ya no necesitan permisos de almacenamiento para agregarlas
archivos al almacenamiento compartido. Esto significa que las apps pueden agregar imágenes a la galería
grabar videos y guardarlos en el almacenamiento compartido, o descargar facturas en PDF sin
sin tener que solicitar
permisos de almacenamiento. Si tu app solo agrega archivos a archivos compartidos
almacenamiento y no consulta imágenes ni videos, debes dejar de solicitarlo
permisos y establece un maxSdkVersion
de API 28 en tu 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" />
Cómo controlar la reselección de contenido multimedia
Con la función de Acceso a fotos seleccionados en Android 14, tu app debe adoptar las
nuevo permiso READ_MEDIA_VISUAL_USER_SELECTED
para controlar contenido multimedia
volver a seleccionarla y actualizar la interfaz de tu app para permitir que los usuarios le otorguen acceso a tu app
a un conjunto diferente de imágenes y videos. La siguiente imagen muestra un ejemplo de
solicitar permisos y volver a seleccionar medios:
Cuando abras el diálogo de selección, se mostrarán las fotos, los videos o ambos, según lo siguiente:
en los permisos solicitados. Por ejemplo, si solicitas el
permiso READ_MEDIA_VIDEO
sin el permiso READ_MEDIA_IMAGES
, solo
aparecerán videos en la IU para que los usuarios seleccionen archivos.
// Allow the user to select only videos
requestPermissions.launch(arrayOf(READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))
Puedes comprobar si tu app tiene acceso total, parcial o denegado a las
biblioteca de fotos y actualizar la interfaz según corresponda. Solicita estos permisos
cuando la app necesita acceso al almacenamiento, en lugar de hacerlo al inicio. Ten en cuenta que
el otorgamiento de permisos se puede cambiar entre la app de onStart
y la de onResume
devoluciones de llamada de ciclo de vida, ya que el usuario puede cambiar el acceso en la configuración sin
y cierra la 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
}
Consulta la biblioteca del dispositivo
Una vez que hayas verificado que tienes acceso a los permisos de almacenamiento correctos, puedes hacer lo siguiente:
interactuar con MediaStore
para consultar la biblioteca de dispositivos (el mismo enfoque funciona
si el acceso otorgado es parcial o total):
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
}
Se simplifica este fragmento de código para ilustrar cómo interactuar con MediaStore
.
En una app lista para la producción, usa la paginación con algo como el archivo Paging
biblioteca para ayudar a garantizar un buen rendimiento.
Consultar la última selección
Las apps en Android 15 y versiones posteriores, y en Android 14 compatibles con las actualizaciones del sistema de Google Play pueden
consultar la última selección de imágenes y videos realizadas por el usuario sobre el acceso parcial
Para ello, habilita 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)
}
El acceso a las fotos y los videos se conserva cuando se actualiza el dispositivo
En los casos en que tu app esté en un dispositivo que se actualice de una versión anterior de Android a Android 14, el sistema conservará el acceso completo a las fotos y los videos del usuario, y le otorgará algunos permisos automáticamente. El comportamiento exacto depende de los permisos que se le otorguen a tu app antes de que el dispositivo se actualice a Android 14.
Permisos de Android 13
Ten en cuenta la siguiente situación:
- Tu app se instaló en un dispositivo que ejecuta Android 13.
- El usuario otorgó los permisos
READ_MEDIA_IMAGES
yREAD_MEDIA_VIDEO
a tu app. - Luego, el dispositivo se actualiza a Android 14 mientras la app está instalada.
- Tu app comienza a orientarse a Android 14 (nivel de API 34) o versiones posteriores.
En este caso, tu app todavía tiene acceso completo a las fotos y los videos del usuario.
El sistema también mantiene automáticamente los permisos READ_MEDIA_IMAGES
y READ_MEDIA_VIDEO
para tu app.
Permisos de Android 12 y versiones anteriores
Ten en cuenta la siguiente situación:
- Tu app se instaló en un dispositivo que ejecuta Android 13.
- El usuario otorgó los permisos
READ_EXTERNAL_STORAGE
oWRITE_EXTERNAL_STORAGE
a tu app. - Luego, el dispositivo se actualiza a Android 14 mientras la app está instalada.
- Tu app comienza a orientarse a Android 14 (nivel de API 34) o versiones posteriores.
En este caso, tu app todavía tiene acceso completo a las fotos y los videos del usuario.
El sistema también otorga los permisos READ_MEDIA_IMAGES
y READ_MEDIA_VIDEO
a tu app automáticamente.
Prácticas recomendadas
En esta sección, se incluyen varias prácticas recomendadas para usar el permiso READ_MEDIA_VISUAL_USER_SELECTED
. Para obtener más información, consulta
nuestras prácticas recomendadas sobre permisos.
No almacenes el estado del permiso de forma permanente
No almacenes el estado del permiso de forma permanente, lo que incluye SharedPreferences
o DataStore
. Es posible que el estado almacenado no esté sincronizado con el estado real. El estado del permiso puede cambiar después del restablecimiento del permiso.
la hibernación de apps, un cambio iniciado por el usuario en la configuración
la app pasa a segundo plano. En cambio, comprueba los permisos de almacenamiento con
ContextCompat.checkSelfPermission()
No supongas que tienes acceso completo a fotos y videos
Según los cambios introducidos en Android 14, es posible que tu app solo tenga
acceso a la biblioteca de fotos del dispositivo. Si la app almacena en caché datos de MediaStore
cuando se realiza una consulta con ContentResolver
, es posible que la caché no esté actualizada.
- Siempre consulta
MediaStore
conContentResolver
, en lugar de depender de una caché almacenada. - Mantén los resultados en la memoria mientras la app esté en primer plano.
- Actualiza los resultados cuando tu app pase por el ciclo de vida de la app
onResume
ya que el usuario puede cambiar de acceso total a parcial mediante la configuración de permisos.
Trata el acceso de URI como temporario
Si el usuario elige Seleccionar fotos y videos en los permisos del sistema
el acceso de tu aplicación a las fotos y los videos seleccionados caducará en algún momento.
Tu app siempre debe controlar el caso de no tener acceso a ningún Uri
,
importar su autoridad.
Filtra los tipos de medios seleccionables por permiso
El diálogo de selección es sensible al tipo de permiso solicitado:
- La solicitud de
READ_MEDIA_IMAGES
solo muestra las imágenes que se pueden seleccionar. - La solicitud solo de
READ_MEDIA_VIDEO
muestra que solo se puede seleccionar el video. - Cuando se solicitan
READ_MEDIA_IMAGES
yREAD_MEDIA_VIDEO
, se muestra todo biblioteca de fotos para que se pueda seleccionar.
Según los casos de uso de tu app, debes asegurarte de solicitar
para evitar una mala experiencia del usuario. Si un atributo solo se espera
videos que selecciones, asegúrate de solicitar solo READ_MEDIA_VIDEO
.
Cómo solicitar permisos en una sola operación
Para evitar que los usuarios vean varios cuadros de diálogo del tiempo de ejecución del sistema, solicita los permisos READ_MEDIA_VISUAL_USER_SELECTED
, ACCESS_MEDIA_LOCATION
y "lectura de contenido multimedia" (READ_MEDIA_IMAGES
, READ_MEDIA_VIDEO
o ambos) en una sola operación.
Permitir que los usuarios administren su selección
Cuando el usuario elige el modo de acceso parcial, tu app no debe suponer que la biblioteca de fotos del dispositivo está vacía y debería permitir que el usuario otorgue más archivos.
El usuario puede decidir cambiar de acceso total a acceso parcial a través de la sin otorgar acceso a algunos archivos de medios visuales.
Modo de compatibilidad
Si mantienes tu propio selector de galería con permisos de almacenamiento, pero no lo hiciste
adaptó tu app para usar la nueva READ_MEDIA_VISUAL_USER_SELECTED
permiso, el sistema ejecuta tu app en un modo de compatibilidad cada vez que el usuario
debe seleccionar o volver a seleccionar el contenido multimedia.
Comportamiento durante la selección inicial de contenido multimedia
Durante la selección inicial, si un usuario elige "Seleccionar fotos y videos" (consulta
figura 1), se admiten los permisos READ_MEDIA_IMAGES
y READ_MEDIA_VIDEO
durante la sesión de la app, otorgando un otorgamiento de permisos temporal y
acceso temporal a las fotos y los videos seleccionados por el usuario. Cuando tu app pasa a
en segundo plano, o cuando el usuario finaliza activamente tu app, el sistema eventualmente
rechaza estos permisos. Este comportamiento es similar a otros permisos únicos.
Comportamiento durante la reselección de contenido multimedia
Si tu aplicación necesita acceder a fotos y videos adicionales más adelante, puedes
debes solicitar manualmente el permiso READ_MEDIA_IMAGES
READ_MEDIA_VIDEO
nuevamente. El sistema sigue el mismo flujo que
la solicitud de permiso inicial, donde se les pide a los usuarios que seleccionen fotos y videos (consulta
Figura 2).
Si tu app sigue las prácticas recomendadas de permisos, este cambio no debería
romper tu app. Sobre todo, si tu app no supone que el URI
del usuario, almacena el estado del permiso del sistema o actualiza el conjunto de
las imágenes que se muestran después de un cambio de permiso. Sin embargo, es posible que este comportamiento
según el caso de uso de tu app. Para brindar la mejor experiencia
para los usuarios, recomendamos implementar el selector de fotos o adaptar la
selector de galería de la app para controlar este comportamiento directamente con el
READ_MEDIA_VISUAL_USER_SELECTED
.