Con el objetivo de darles a los usuarios más control sobre sus archivos y acotar el desorden, en Android 10 se introdujo un nuevo paradigma de almacenamiento para apps llamado almacenamiento específico. El almacenamiento específico cambia la forma en la que las apps almacenan los archivos y acceden a ellos en el almacenamiento externo de un dispositivo. Si deseas migrar tu app a fin de admitir el almacenamiento específico, sigue las prácticas recomendadas para casos prácticos de almacenamiento comunes que se describen en esta guía. Se organizan los casos prácticos en dos categorías: control de archivos multimedia y control de archivos que no son multimedia.
Para obtener más información sobre cómo almacenar archivos y acceder a ellos en Android, consulta las guías de capacitación sobre almacenamiento.
Cómo controlar archivos multimedia
En esta sección se describen algunos de los casos prácticos comunes para controlar archivos multimedia (archivos de video, imágenes y audio) y se explica el enfoque general que tu app puede usar. En la siguiente tabla, se resume cada uno de estos casos prácticos y se incluyen vínculos a cada una de las secciones que contienen más detalles.
Caso práctico | Resumen |
---|---|
Cómo mostrar todos los archivos de imagen o video | Usa el mismo enfoque para todas las versiones de Android. |
Cómo mostrar imágenes o videos de una carpeta en particular | Usa el mismo enfoque para todas las versiones de Android. |
Cómo acceder a la información de ubicación desde las fotos | Usa un enfoque si tu app usa almacenamiento específico. Usa un enfoque diferente si tu app inhabilita el almacenamiento específico. |
Cómo modificar o borrar varios archivos multimedia en una sola operación | Usa un enfoque para Android 11. En Android 10 inhabilita el almacenamiento específico y usa el enfoque para Android 9 y versiones anteriores. |
Cómo importar una sola imagen que ya existe | Usa el mismo enfoque para todas las versiones de Android. |
Cómo capturar una sola imagen | Usa el mismo enfoque para todas las versiones de Android. |
Cómo compartir archivos multimedia con otras apps | Usa el mismo enfoque para todas las versiones de Android. |
Cómo compartir archivos multimedia con una app específica | Usa el mismo enfoque para todas las versiones de Android. |
Cómo acceder a archivos desde código o bibliotecas que usan rutas de archivos directas | Usa un enfoque para Android 11. En Android 10 inhabilita el almacenamiento específico y usa el enfoque para Android 9 y versiones anteriores. |
Cómo mostrar archivos de imagen o video de varias carpetas
Busca una colección multimedia con la API de query()
. Para ordenar o filtrar los archivos multimedia, ajusta los parámetros projection
, selection
, selectionArgs
y sortOrder
.
Cómo mostrar imágenes o videos de una carpeta en particular
Usa este enfoque:
- Sigue las prácticas recomendadas que se describen en Cómo solicitar permisos de la app y solicita el permiso
READ_EXTERNAL_STORAGE
. - Recupera archivos multimedia basados en el valor de
MediaColumns.DATA
, que contiene la ruta absoluta del sistema de archivos hasta el elemento multimedia del disco.
Cómo acceder a la información de ubicación desde las fotos
Si tu app usa almacenamiento específico, sigue los pasos de la sección Información de ubicación en fotografías de la guía de almacenamiento de contenido multimedia.
Cómo modificar o borrar varios archivos multimedia en una sola operación
Incorpora lógica basada en las versiones de Android en las que se ejecuta tu app.
Si se ejecuta en Android 11
Usa este enfoque:
- Crea un intent pendiente para la solicitud de escritura o eliminación de tu app con
MediaStore.createWriteRequest()
oMediaStore.createTrashRequest()
y, luego, solicita al usuario permiso a fin de invocar ese intent y editar un conjunto de archivos. Evalúa la respuesta del usuario:
- Si se otorgó el permiso, continúa con la operación de modificación o eliminación.
- Si no se otorgó el permiso, explícale al usuario por qué la función de tu app necesita el permiso.
Obtén más información para realizar operaciones por lotes con estos métodos disponibles en Android 11.
Si se ejecuta en Android 10
Si tu app está orientada a Android 10 (nivel 29 de API), inhabilita el almacenamiento específico y continúa usando el enfoque para Android 9 y versiones anteriores a fin de realizar esta operación.
Si se ejecuta en Android 9 o versiones anteriores
Usa este enfoque:
- Sigue las recomendaciones que se describen en Cómo solicitar permisos de la app y solicita el permiso
WRITE_EXTERNAL_STORAGE
. - Usa la API de
MediaStore
para modificar o borrar los archivos multimedia.
Cómo importar una sola imagen que ya existe
Si deseas importar una sola imagen que ya existe (por ejemplo, para usarla como foto del perfil de un usuario), tu app puede usar su propia IU en la operación, o bien el selector del sistema.
Cómo presentar tu propia interfaz de usuario
Usa este enfoque:
- Sigue las recomendaciones que se describen en Cómo solicitar permisos de la app y solicita el permiso
READ_EXTERNAL_STORAGE
. - Usa la API de
query()
para buscar en una colección de archivos multimedia. - Muestra los resultados en la IU personalizada de tu app.
Cómo usar el selector del sistema
Usa el intent ACTION_GET_CONTENT
, que le pide al usuario que elija una imagen para importar.
Si deseas filtrar los tipos de imágenes que el selector del sistema presenta al usuario, puedes usar setType()
o EXTRA_MIME_TYPES
.
Cómo capturar una sola imagen
Si deseas capturar una sola imagen para usarla en tu app (por ejemplo, como foto del perfil de un usuario), usa el intent ACTION_IMAGE_CAPTURE
a fin de pedirle al usuario que tome una foto con la cámara del dispositivo. El sistema almacena la foto capturada en la tabla MediaStore.Images
.
Cómo compartir archivos multimedia con otras apps
Usa el método insert()
para agregar directamente registros a MediaStore. Para obtener más información, consulta la sección Cómo agregar un elemento de la guía de almacenamiento de contenido multimedia.
Cómo compartir archivos multimedia con una app específica
Usa el componente FileProvider
de Android, como se describe en la guía Cómo configurar el uso compartido de archivos.
Cómo acceder a archivos desde código o bibliotecas que usan rutas de archivos directas
Incorpora lógica basada en las versiones de Android en las que se ejecuta tu app.
Si se ejecuta en Android 11
Usa este enfoque:
- Sigue las recomendaciones que se describen en Cómo solicitar permisos de la app y solicita el permiso
READ_EXTERNAL_STORAGE
. - Accede a los archivos mediante rutas de acceso directas.
Para obtener más información, consulta Cómo acceder a archivos usando rutas sin procesar.
Si se ejecuta en Android 10
Si tu app está orientada a Android 10 (nivel 29 de API), inhabilita el almacenamiento específico y continúa usando el enfoque para Android 9 y versiones anteriores a fin de realizar esta operación.
Si se ejecuta en Android 9 o versiones anteriores
Usa este enfoque:
- Sigue las recomendaciones que se describen en Cómo solicitar permisos de la app y solicita el permiso
WRITE_EXTERNAL_STORAGE
. - Accede a los archivos mediante rutas de acceso directas.
Cómo controlar archivos que no son multimedia
En esta sección se describen algunos de los casos prácticos comunes para controlar archivos que no son multimedia y se explica el enfoque general que tu app puede usar. En la siguiente tabla, se resume cada uno de estos casos prácticos y se incluyen vínculos a cada una de las secciones que contienen más detalles.
Caso práctico | Resumen |
---|---|
Cómo abrir un archivo de documento | Usa el mismo enfoque para todas las versiones de Android. |
Cómo migrar archivos existentes desde una ubicación de almacenamiento heredado | Migra los archivos al almacenamiento específico cuando sea posible. Inhabilita el almacenamiento específico para Android 10 cuando sea necesario. |
Cómo compartir contenido con otras apps | Usa el mismo enfoque para todas las versiones de Android. |
Cómo almacenar en caché archivos que no son multimedia | Usa el mismo enfoque para todas las versiones de Android. |
Cómo abrir un archivo de documento
Usa el intent ACTION_OPEN_DOCUMENT
para pedirle al usuario que elija un archivo para abrir mediante el selector del sistema. Si deseas filtrar los tipos de archivos que el selector del sistema presenta al usuario, puedes usar setType()
o EXTRA_MIME_TYPES
.
Por ejemplo, puedes usar el siguiente código para encontrar todos los archivos PDF, DDT y TXT:
Kotlin
startActivityForResult( Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "*/*" putExtra(Intent.EXTRA_MIME_TYPES, arrayOf( "application/pdf", // .pdf "application/vnd.oasis.opendocument.text", // .odt "text/plain" // .txt )) }, REQUEST_CODE )
Java
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] { "application/pdf", // .pdf "application/vnd.oasis.opendocument.text", // .odt "text/plain" // .txt }); startActivityForResult(intent, REQUEST_CODE);
Cómo migrar archivos existentes desde una ubicación de almacenamiento heredado
Se considera que un directorio es una ubicación de almacenamiento heredado si no es un directorio específico de la app o un directorio público compartido. Si tu app crea o consume archivos en una ubicación de almacenamiento heredado, te recomendamos que migres los archivos a ubicaciones a las que se pueda acceder con almacenamiento específico y realizar los cambios necesarios para trabajar con archivos en este tipo de almacenamiento.
Cómo mantener el acceso a la ubicación de almacenamiento heredado para la migración de datos
Tu app debe mantener el acceso a la ubicación de almacenamiento heredado para migrar cualquier archivo de apps a ubicaciones a las que se pueda acceder con almacenamiento específico. El enfoque que debes usar depende del nivel de la API de destino de tu app.
Si tu app se orienta a Android 11
Usa la marca
preserveLegacyExternalStorage
para conservar el modelo de almacenamiento heredado, de modo que tu app pueda migrar los datos de un usuario cuando este actualice a la nueva versión orientada a Android 11.Para continuar, inhabilita el almacenamiento específico de modo que tu app pueda seguir accediendo a tus archivos en la ubicación de almacenamiento heredado, en dispositivos Android 10.
Si tu app se orienta a Android 10
Inhabilita el almacenamiento específico para que sea más fácil mantener el comportamiento de tu app en todas las versiones de Android.
Cómo migrar los datos de la app
Cuando tu app esté lista para la migración, usa el siguiente enfoque:
- Verifica si los archivos de trabajo de tu app se encuentran en el directorio
/sdcard/
o en alguno de sus subdirectorios. - Transfiere cualquier archivo privado de la app desde su ubicación actual en
/sdcard/
al directorio que muestra el métodogetExternalFilesDir()
. - Transfiere cualquier archivo no multimedia compartido desde su ubicación actual en
/sdcard/
a un subdirectorio, específico de la app, del directorioDownloads/
. - Quita los directorios de almacenamiento heredado de tu app del directorio
/sdcard/
.
Cómo compartir contenido con otras apps
Para compartir los archivos de tu app con otra app, usa un FileProvider
. En el caso de las apps que necesitan compartir archivos entre sí, recomendamos que uses un proveedor de contenido para cada app y, luego, que sincronices los datos a medida que se agregan a la colección.
Cómo almacenar en caché archivos que no son multimedia
El enfoque que debes usar depende del tipo de archivos que necesitas almacenar en caché.
- Archivos pequeños o que contienen información sensible: usa
Context#getCacheDir()
. - Archivos grandes o que no contienen información sensible: usa
Context#getExternalCacheDir()
.
Cómo inhabilitar temporalmente el almacenamiento específico
Antes de que tu app sea totalmente compatible con el almacenamiento específico, puedes inhabilitarla de forma temporal con uno de los siguientes métodos:
- Orienta la app a Android 9 (nivel 28 de API) o versiones anteriores.
Si la orientas a Android 10 (nivel 29 de API) o versiones posteriores, establece el valor de
requestLegacyExternalStorage
entrue
, en el archivo de manifiesto de tu app:<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10 or higher. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Si deseas probar cómo se comporta una app que se orienta a Android 9 o versiones anteriores cuando usas almacenamiento específico, puedes establecer el valor de requestLegacyExternalStorage
en false
. Si realizas pruebas en un dispositivo Android 11, también puedes usar marcas de compatibilidad de apps para probar el comportamiento de tu app con o sin almacenamiento específico.