es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Migración completa de datos en relación al almacenamiento de ámbito en Android 11 y la compatibilidad con versiones < Android 10.

Android 11 ha vuelto obsoletas casi todas mis aplicaciones debido a la actualización del almacenamiento controlado.
De acuerdo, empezaré diciendo lo siguiente:

Opción #1 – android:requestLegacyExternalStorage=”true” no funcionó para mí, a pesar de que todavía estoy apuntando al sdk 29.

Opción #2 – tampoco funcionó.

No importa mucho de todos modos, ya que la opción #1 solo funcionaría temporalmente y la opción #2 tendría que ser justificada al publicar en la tienda.

Ahora me deja con la Opción #3 – migrar todos mis datos al almacenamiento controlado.

Mi aplicación básicamente hace 3 cosas:

  • Copiar una carpeta llamada “Test” desde la carpeta de activos al Environment.getExternalStorageDirectory() porque necesito una ruta de tipo String.
  • Generar una imagen y escribirla en Environment.getExternalStorageDirectory().
  • Leer la imagen guardada desde Environment.getExternalStorageDirectory().

Ahora mis preguntas:

1) ¿Dado que necesito una ruta de tipo String, debo copiar la carpeta llamada “Test” desde la carpeta de activos al almacenamiento controlado? En ese caso, ¿cómo lo hago? ¿O hay otra manera?

2) ¿Cómo guardo un bitmap en el almacenamiento controlado? ¿Debo seguir este tutorial: https://www.youtube.com/watch?v=tYQ8AO58Aj0?

3) ¿Cómo leo el archivo guardado en el almacenamiento controlado?

4) Si hago todos los ajustes anteriores, ¿funcionarán para todas las versiones de Android? ¿O básicamente necesito verificar la versión de Android y usar Environment.getExternalStorageDirectory() para <10 y almacenamiento controlado para >= 10?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Como experto en TI especializado en Java, Android, Android-11, Android-Storage y Scoped-Storage, puedo responder las siguientes preguntas:

    1) Si necesitas una ruta de cadena, puedes copiar la carpeta llamada Test desde la carpeta de activos al almacenamiento con alcance limitado mediante el uso del Storage Access Framework, que te permite copiar contenido de otras aplicaciones y directorios de manera segura. Puedes utilizar el ACTION_OPEN_DOCUMENT_TREE intent para otorgar acceso al directorio y luego copiar el archivo a ese directorio.

    2) Para guardar un mapa de bits en el almacenamiento con alcance limitado, puedes utilizar la clase ContentResolver para crear un nuevo archivo y luego utilizar un OutputStream para escribir los datos del mapa de bits en el archivo. Aquí tienes un fragmento de código como referencia:

    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
    String filename = "image.jpg";
    
    ContentResolver resolver = getContentResolver();
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, filename);
    contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
    contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
    
    Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
    OutputStream outputStream = resolver.openOutputStream(uri);
    
    bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
    

    3) Para leer el archivo guardado desde el almacenamiento con alcance limitado, puedes utilizar la clase ContentResolver para consultar el proveedor y obtener la Uri del archivo. Luego, utiliza un InputStream para leer el contenido del archivo. Aquí tienes un fragmento de código como referencia:

    String filename = "image.jpg";
    String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
    String selection = MediaStore.MediaColumns.DISPLAY_NAME + " = ?";
    String[] selectionArgs = {filename};
    Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    
    ContentResolver resolver = getContentResolver();
    Cursor cursor = resolver.query(uri, projection, selection, selectionArgs, null);
    
    if (cursor != null && cursor.moveToFirst()) {
        int displayNameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
        String displayName = cursor.getString(displayNameIndex);
    
        if (displayName.equals(filename)) {
            int uriIndex = cursor.getColumnIndex(MediaStore.Images.Media._ID);
            long uriId = cursor.getLong(uriIndex);
            uri = ContentUris.withAppendedId(uri, uriId);
    
            try {
                InputStream inputStream = resolver.openInputStream(uri);
                // leer el contenido del archivo
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        cursor.close();
    }
    

    4) Si realizas todos los ajustes anteriores, funcionarán en todas las versiones de Android, incluyendo Android 10 y versiones posteriores. Sin embargo, aún debes verificar la versión de Android y utilizar Environment.getExternalStorageDirectory() para versiones anteriores o Scoped Storage para versiones más recientes para garantizar la compatibilidad con versiones anteriores.

Comments are closed.