Elegir la experiencia de almacenamiento adecuada

La próxima versión estable de Android 14 se acerca rápidamente. Ahora es un buen momento para probar su aplicación con los cambios de esta nueva versión si aún no lo ha hecho. Con Platform Stability, incluso puede enviar aplicaciones dirigidas a SDK 34 a Google Play Store.

Android 14 presenta una nueva función llamada Acceso a fotos seleccionadas, que permite a los usuarios otorgar acceso a aplicaciones a imágenes y videos específicos en su biblioteca, en lugar de otorgar acceso a todos los medios de un tipo en particular. Esta es una excelente manera para que los usuarios se sientan más cómodos compartiendo contenido multimedia con aplicaciones, y también es una excelente manera para que los desarrolladores creen aplicaciones que respeten la privacidad del usuario.

Para facilitar la migración de las aplicaciones que actualmente usan permisos de almacenamiento, las aplicaciones se ejecutarán en un modo de compatibilidad. En este modo, si un usuario elige “Seleccionar fotos y videos”, el permiso parecerá otorgado, pero la aplicación solo tendrá acceso a las fotos seleccionadas. El permiso se revocará cuando el proceso de la aplicación se detenga o esté en segundo plano durante un cierto período de tiempo (similar a los permisos de una sola vez). Cuando su aplicación solicite permiso nuevamente, los usuarios pueden seleccionar un conjunto diferente de imágenes o videos si lo desean. En lugar de dejar que el sistema maneje esta nueva selección, se recomienda que las aplicaciones manejen este proceso para una mejor experiencia de usuario.

Incluso cuando su aplicación maneja la reselección de medios correctamente, creemos que para la gran mayoría de las aplicaciones, el selector de fotos sin permiso que presentamos el año pasado será la mejor solución de selección de medios tanto para el usuario como para la privacidad. La mayoría de las aplicaciones permiten a los usuarios elegir contenido multimedia para realizar tareas como adjuntar a un correo electrónico, cambiar una imagen de perfil, compartir con amigos y la interfaz de usuario familiar del selector de fotos de Android ofrece a los usuarios una experiencia consistente y de alta calidad que ayuda a los usuarios a otorgar acceso. de forma segura, lo que le permite concentrarse en las características distintivas de su aplicación. Si necesita absolutamente una solución más estrechamente integrada, la integración con MediaStore se puede considerar como una alternativa al selector de fotos.

Imagen de la página Mi perfil en un dispositivo móvil

Para usar el selector de fotos en su aplicación, solo necesita registrar el resultado de una actividad:

val pickMedia = registerForActivityResult(PickVisualMedia()) { uri -> if (uri != null) { Log.d(“PhotoPicker”, “URI seleccionado: $uri”) } else { Log.d(“PhotoPicker”, “No medio seleccionado”) } }

El selector de fotos permite la personalización de la selección del tipo de medio entre foto, video o un tipo de mímica específico en el lanzamiento:

pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo)) pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly)) pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly)) pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType(“image/gif”)) ) )

Puede establecer un límite superior al permitir múltiples selecciones:

val pickMultipleMedia = registerForActivityResult(PickMultipleVisualMedia(5)) { uris -> if (uris.isNotEmpty()) { Log.d(“PhotoPicker”, “Número de elementos seleccionados: ${uris.size}”) } else { Log. d(“PhotoPicker”, “Ningún medio seleccionado”) } }

Finalmente, puede habilitar la compatibilidad con el selector de fotos en dispositivos más antiguos a partir de Android KitKat (API 19+) utilizando los servicios de Google Play, agregando esta entrada a su archivo AndroidManifest.xml:

¡En menos de 20 líneas de código tienes un selector de foto/video bien integrado dentro de tu aplicación que no requiere ningún permiso!

Crea tu propio selector de galería

La creación de su propio selector de galería requiere un desarrollo y mantenimiento extensos, y la aplicación debe solicitar permisos de almacenamiento para obtener la suscripción del usuario, que los usuarios pueden negar o, a partir de Android 14, restringir el acceso a los medios seleccionados.

Primero, solicite los permisos de almacenamiento correctos en el manifiesto de Android según la versión de su sistema operativo:

Luego, la aplicación debe solicitar los permisos de tiempo de ejecución correctos, también según la versión del sistema operativo:

val requestPermissions = registerForActivityResult(RequestMultiplePermissions()) { resultados -> } 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)) }

Con la función de acceso a Fotos seleccionadas en Android 14, su aplicación debe adoptar el nuevo permiso READ_MEDIA_VISUAL_USER_SELECTED para controlar la reselección de medios y actualizar la experiencia del usuario de la aplicación para permitirles otorgar acceso a la aplicación a un conjunto diferente de imágenes y videos.

Al abrir el cuadro de diálogo de selección, las fotos y/o los videos se mostrarán según los permisos solicitados: si solicita el permiso READ_MEDIA_VIDEO sin el permiso READ_MEDIA_IMAGES, solo los videos aparecerán en la interfaz de usuario para que los usuarios seleccionen los archivos.

requestPermissions.launch(arrayOf(READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))

Puede verificar si su aplicación tiene acceso total, parcial o denegado a la biblioteca de fotos del dispositivo y actualizar su UX en consecuencia. Ahora es aún más importante solicitar estos permisos cuando la aplicación solicita acceso al espacio de almacenamiento, en lugar de al inicio. Tenga en cuenta que la concesión de permisos se puede cambiar entre las devoluciones de llamada del ciclo de vida onStart y onResume, ya que el usuario puede cambiar el acceso en la configuración sin cerrar la aplicación.

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 ) ) { } else if ( Build.VERSION .SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && ContextCompat.checkSelfPermission(context, READ_MEDIA_VISUAL_USER_SELECTED) == PERMISSION_GRANTED ) { } else if (ContextCompat.checkSelfPermission(context, READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED) { } else { }

Después de verificar que tiene acceso a los permisos de almacenamiento correctos, puede interactuar con MediaStore para consultar la biblioteca del dispositivo (ya sea que se otorgue acceso parcial o total):

data class Media(val uri: Uri, val name: String, val size: Long, val mimeType: String, val dateToken: Long) suspend fun getImages(contentResolver: ContentResolver): List = withContext(Dispatchers.IO) { val proyección = 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) { Images .Media.getContentUri(MediaStore.VOLUME_EXTERNAL) } else { Images.Media.EXTERNAL_CONTENT_URI } val images = mutableListOf() contentResolver.query( collectionUri, proyección, nulo, nulo, “${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 (colecciónUri, cursor.getLong(idColumn)) val nombre = cursor.getString(displayNameColumn) val tamaño = cursor.getLong (sizeColumn) val mimeType = cursor.getString(mimeTypeColumn) val dateToken = cursor.getLong(4) val image = Promedio (uri, nombre, tamaño, mimeType, dateToken) images.add(image) } } return@withContext images }

El fragmento de código anterior se simplifica para ilustrar cómo interactuar con MediaStore. En una aplicación de producción adecuada, debería considerar usar la paginación con algo como Biblioteca de paginación para asegurar un buen desempeño.

Es posible que no necesite permisos

A partir de Android 10 (API 29), ya no se requieren permisos de almacenamiento para agregar archivos al almacenamiento compartido. Esto significa que puede agregar imágenes a la galería, grabar videos y guardarlos en un espacio de almacenamiento compartido o descargar facturas en formato PDF sin tener que solicitar permisos de almacenamiento. Si su aplicación solo agrega archivos al almacenamiento compartido y no consulta imágenes o videos, debe dejar de solicitar permisos de almacenamiento y establecer una API maxSdkVersion de 28 en el archivo AndroidManifest.xml:

ACTION_GET_CONTENT cambio de comportamiento

En nuestra última publicación de blog sobre archivado, anunciamos que implementaremos un cambio de comportamiento cada vez que ACCIÓN_GET_CONTENIDO la intención se dispara con un tipo de imagen y/o video mimo. Si aún no ha probado este cambio, puede habilitarlo manualmente en su dispositivo:

adb shell device_config establece storage_native_boot take_over_get_content verdadero

Esto explica cómo ofrecer la selección de medios visuales en su aplicación con los cambios de privacidad que hemos realizado en varias versiones de Android. Si tiene algún comentario o sugerencia, envíe entradas a nuestro detector de problemas.

Compruebe también

en vivo desde Droidcon, incluida la mayor actualización de Gemini en Android Studio y más lanzamientos del SDK de Android.

Acabamos de lanzar nuestro episodio de otoño de #TheAndroidShow en YouTube etcétera desarrollador.android.comy esta vez …

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *