La imagen, guardada en la tarjeta SD, no aparece en la aplicación Galería de Android

93

Guardo una imagen en la tarjeta sd y no aparece en la aplicación Galería hasta que saco la tarjeta sd y la devuelvo.

¿Tienes idea de por qué es así?

Parece que la aplicación Galería tiene un caché que no se actualiza al guardar el archivo ...

En realidad, también quiero abrir la imagen recién guardada en la aplicación Galería y no tengo éxito con eso.
Esta es mi pregunta sobre este problema.

Michael Kessler
fuente
1
Esta pregunta ha sido respondida paso a paso en este tutorial: stackoverflow.com/questions/30506301/…
Takermania

Respuestas:

45

El sistema escanea la tarjeta SD cuando está montada para encontrar nuevos archivos de imagen (y otros). Si está agregando un archivo mediante programación, puede usar esta clase:

http://developer.android.com/reference/android/media/MediaScannerConnection.html

hackbod
fuente
4
Nota al margen: aunque la pregunta se refiere a la adición de archivos, MediaScannerConnection no proporciona una solución para la eliminación de archivos, ni siquiera cuando se solicita escanear la carpeta principal de un archivo eliminado.
AlikElzin-kilaka
86

Una solución más simple es utilizar el método de conveniencia estático scanFile () :

File imageFile = ...
MediaScannerConnection.scanFile(this, new String[] { imageFile.getPath() }, new String[] { "image/jpeg" }, null);

dónde thisestá su actividad (o cualquier contexto), el tipo mime solo es necesario si está utilizando extensiones de archivo no estándar y nulles para la devolución de llamada opcional (que no necesitamos para un caso tan simple).

darrenp
fuente
2
Spot on, el método de transmisión que proporcionan otros (y Google), rara vez funciona).
Chris.Jenkins
2
Esto me funcionaba en versiones anteriores de Android ~ 4.0, pero ahora en 4.3+ no parece funcionar. Las imágenes no se muestran en la aplicación de la galería.
hooby3dfx
Perfecto ! Puede obtener contexto con: Android.App.Application.Context
jug
Trabajó en malvavisco
Hitesh Sahu
66

Mi respuesta a la pregunta original y a cualquier otra persona que pueda tener este problema:

Estaba teniendo el mismo problema, las imágenes en mi aplicación que las personas guardaban en la tarjeta SD no aparecían en su Galería de inmediato. Después de buscar, encontré esta línea de código insertada después de mi código 'guardar en tarjeta sd' que solucionó el problema:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
ShadowGod
fuente
¿Necesitamos usar el escáner de medios para poder usar esta transmisión? Estoy usando otro método para mostrar imágenes en mi galería. Cuando estoy usando sendBroadcast arriba en el botón Guardar, haga clic en mi galería no se actualiza con la nueva imagen
cambio
4
Es antiguo pero esto puede ayudar a alguien - una ruta más específica: sendBroadcast (new Intent (Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file: //" + Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_PICTURES)))); Este método (esta respuesta, no solo mi comentario) no funciona en el emulador. Prueba en dispositivo real.
Creo que la respuesta aceptada ofrece la forma correcta de hacerlo. Pero si está tratando de admitir API <= 7, esta es una buena alternativa.
Amr Mostafa
Su respuesta es útil para otros dispositivos. No funciona en HTC, cuando intento escanear la carpeta de mi aplicación. No muestra la imagen recién agregada.
MobileEvangelist
6
Parece que ya no es compatible con Android 4.4 o superior. En este caso, se lanzará una excepción de permiso.
rsp1984
13

También puede agregar una imagen a la Galería de medios por intención, eche un vistazo al código de ejemplo para ver cómo se hace:

ContentValues image = new ContentValues();

image.put(Images.Media.TITLE, imageTitle);
image.put(Images.Media.DISPLAY_NAME, imageDisplayName);
image.put(Images.Media.DESCRIPTION, imageDescription);
image.put(Images.Media.DATE_ADDED, dateTaken);
image.put(Images.Media.DATE_TAKEN, dateTaken);
image.put(Images.Media.DATE_MODIFIED, dateTaken);
image.put(Images.Media.MIME_TYPE, "image/png");
image.put(Images.Media.ORIENTATION, 0);

 File parent = imageFile.getParentFile();
 String path = parent.toString().toLowerCase();
 String name = parent.getName().toLowerCase();
 image.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
 image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
 image.put(Images.Media.SIZE, imageFile.length());

 image.put(Images.Media.DATA, imageFile.getAbsolutePath());

 Uri result = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
Janusz
fuente
Hola. Este método agrega la imagen al MediaStore, lo he confirmado al verificar la devolución Uripero el problema es que la imagen insertada no se muestra en la galería. He comprobado tanto al principio como al final de la galería. ¿Puede sugerir algún método para que la imagen insertada se muestre en la galería inmediatamente?
Shajeel Afzal
12

Actualización de la galería que incluye Android KITKAT

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
}
else
{
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}
AtanuCSE
fuente
El código que está dentro de la primera condición con la declaración "IF" funciona bien para mí en KitKat (Android 4.4.4, API 19).
Alex
8

Aquí está el código para MediaScannerConnection:

MyMediaConnectorClient client = new MyMediaConnectorClient(newfile);
MediaScannerConnection scanner = new MediaScannerConnection(context, client);
client.setScanner(scanner);
scanner.connect();

newfile es el objeto Archivo de su archivo nuevo / guardado.

3dmg
fuente
2
Gracias por su respuesta. En realidad, ya terminé este proyecto hace mucho tiempo ... ni siquiera recuerdo cuál fue la solución que usé. Otros usuarios podrían encontrar útil su solución si también proporciona la implementación de MyMediaConnectorClient...
Michael Kessler
sí, estoy teniendo verdaderos dolores de cabeza con esto en este momento. Por favor publique :)
Steve
Sí, no tengo muy claro cómo debería ser el flujo -Corregirme dónde estoy equivocado Puedo usar MediaScannerConnection para actualizar la información SDCAARD, así que tomo una foto con la cámara y paso el nuevo archivo al MSC y ahora puedo acceder al archivo con un cliente de escáner de conexión?
Steve
El flujo es: tomas una foto, la guardas en tu tarjeta SD y luego realizas la actualización del escáner, para que el sistema de archivos se actualice para ver tu foto guardada en la galería del dispositivo. Si no hace eso con el escáner, verá su foto después de que el siguiente dispositivo se reinicie en la galería.
3dmg
7

hay una aplicación en el emulador que dice: 'Herramientas de desarrollo'

haga clic en eso y seleccione 'Escaneo de medios' .. todas las imágenes serán escaneadas

Abhishek Susarla
fuente
Es bueno saberlo, la única forma que conocía antes de que
dijeras
6

Deje que su actividad implemente 'MediaScannerConnectionClient' y agregue esto a su actividad:

private void startScan() 
{ 
    if(conn!=null) conn.disconnect();  
    conn = new MediaScannerConnection(YourActivity.this,YourActivity.this); 
    conn.connect(); 
} 

@Override 
public void onMediaScannerConnected() { 
    try{
        conn.scanFile(yourImagePath, "image/*");
       } catch (java.lang.IllegalStateException e){
       }
}

@Override 
public void onScanCompleted(String path, Uri uri) { 
    conn.disconnect(); 
} 
TOMKA
fuente
¡Hola! ¿Qué pasa si conocemos el Uride la imagen, por ejemplo:content://media/external/images/media/1231778
Shajeel Afzal
6

este trabajo conmigo

File file = ..... // Save file

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
usuario3245604
fuente
4
 File folderGIF = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/newgif2");    //path where gif will be stored
success = folderGIF.mkdir();    //make directory
 String finalPath = folderGIF + "/test1.gif";  //path of file
.....
/* changes in gallery app if any changes in done*/
 MediaScannerConnection.scanFile(this,
                    new String[]{finalPath}, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            Log.i("ExternalStorage", "Scanned " + path + ":");
                            Log.i("ExternalStorage", "-> uri=" + uri);
                        }
                    });
Khyati Fatania
fuente
Quiero guardar un archivo gif animado que se encuentra en un almacenamiento externo y tengo la ruta, es decir, / storage / emulated / 0 / Android / data / <PackageName> / files / <FolderName> /xyz.gif. Ahora quiero guardar / copiar este archivo en la Galería de imágenes y mostrarlo allí. Como hacer esto.
Zia Ur Rahman
3

Aquí estoy compartiendo un código que puede cargar una imagen en forma de mapa de bits y guardar esa imagen en la galería de tarjetas SD en la carpeta del nombre de la aplicación. Debes seguir estos pasos

  1. Descargar mapa de bits de imagen primero



     private Bitmap loadBitmap(String url) {
        try {
            InputStream in = new java.net.URL(url).openStream();
            return BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
       }


  1. También proporcione el siguiente permiso en su archivo AndroidManifest.xml.


    uses-permission android:name="android.permission.INTERNET" 
    uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"


  1. Aquí está el código completo que está escrito en Activty en el que queremos realizar esta tarea.



     void saveMyImage(String appName, String imageUrl, String imageName) {

            Bitmap bmImg = loadBitmap(imageUrl);
            File filename;
            try {
                String path1 = android.os.Environment.getExternalStorageDirectory()
                        .toString();
                File file = new File(path1 + "/" + appName);
                if (!file.exists())
                    file.mkdirs();
                filename = new File(file.getAbsolutePath() + "/" + imageName
                        + ".jpg");
                FileOutputStream out = new FileOutputStream(filename);
                bmImg.compress(Bitmap.CompressFormat.JPEG, 90, out);
                out.flush();
                out.close();
                ContentValues image = new ContentValues();
                image.put(Images.Media.TITLE, appName);
                image.put(Images.Media.DISPLAY_NAME, imageName);
                image.put(Images.Media.DESCRIPTION, "App Image");
                image.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
                image.put(Images.Media.MIME_TYPE, "image/jpg");
                image.put(Images.Media.ORIENTATION, 0);
                File parent = filename.getParentFile();
                image.put(Images.ImageColumns.BUCKET_ID, parent.toString()
                        .toLowerCase().hashCode());
                image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, parent.getName()
                        .toLowerCase());
                image.put(Images.Media.SIZE, filename.length());
                image.put(Images.Media.DATA, filename.getAbsolutePath());
                Uri result = getContentResolver().insert(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
                Toast.makeText(getApplicationContext(),
                        "File is Saved in  " + filename, Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }


  1. Espero que pueda resolver todo tu problema.
VISHNU GARG
fuente
3
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

No parece funcionar en KITKAT. Lanza una excepción de denegación de permiso y bloquea la aplicación. Entonces, para esto, hice lo siguiente,

String path = mediaStorageDir.getPath() + File.separator
                    + "IMG_Some_name.jpg";
CameraActivity.this.sendBroadcast(new Intent(
                             Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri
                            .parse("file://" + path)));

Espero eso ayude.

Muhammad Riyaz
fuente
2

Use esto después de guardar la imagen

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
Deepu
fuente
3
Esto funciona pero no es la mejor solución. Está engañando al sistema para que piense que la tarjeta SD sería (re) montada y posiblemente forzaría a escanear toda la tarjeta SD. MediaScanner.scanFile (..) es la mejor solución cuando tiene ahora el archivo que desea agregar.
pocmo
1
Esta búsqueda de todas las imágenes. E implica una gran cantidad de procesamiento de datos innecesario que puede ser irrelevante cuando solo tenemos una imagen para mostrar en la galería.
Rahul Rastogi
2

Mi código para MyMediaConnectorClient:

public class MyMediaConnectorClient implements MediaScannerConnectionClient {

    String _fisier;
    MediaScannerConnection MEDIA_SCANNER_CONNECTION;

    public MyMediaConnectorClient(String nume) {
        _fisier = nume;
    }

    public void setScanner(MediaScannerConnection msc){
        MEDIA_SCANNER_CONNECTION = msc;
    }

    @Override
    public void onMediaScannerConnected() {
        MEDIA_SCANNER_CONNECTION.scanFile(_fisier, null);
    }

    @Override
    public void onScanCompleted(String path, Uri uri) {
        if(path.equals(_fisier))
            MEDIA_SCANNER_CONNECTION.disconnect();
    }
}
Mariana
fuente
0

Debe otorgar permisos a la aplicación Galería. Simplemente mantenga presionado el ícono de la aplicación de la galería en la pantalla de inicio y toque 'INFORMACIÓN DE LA APLICACIÓN' que aparece en la parte superior de la pantalla. Al hacerlo, se mostrará la configuración de la aplicación de la galería. Ahora vaya a la pestaña Permisos y habilite el almacenamiento, los permisos de la cámara alternándolos. Ahora vaya a su aplicación de galería nativa y obtendrá las imágenes guardadas.

Devanshu Jain
fuente
0

Esto también resolverá su problema si su imagen en la galería no se muestra en su lugar, podrían mostrar un mapa de bits de tipo 404 en el medio. agregue las etiquetas que están en mi código con su imagen porque debe haber algunos metadatos para mostrar la imagen en la galería.

      String resultPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES)+ 
      getString(R.string.directory) + System.currentTimeMillis() + ".jpg";

       new File(resultPath).getParentFile().mkdir();

        try {
            OutputStream fileOutputStream = new FileOutputStream(resultPath);
            savedBitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
        savedBitmap.recycle();

        File file = new File(resultPath);
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE, "Photo");
        values.put(MediaStore.Images.Media.DESCRIPTION, "Edited");
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis ());
        values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
        values.put(MediaStore.Images.ImageColumns.BUCKET_ID, file.toString().toLowerCase(Locale.US).hashCode());
        values.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, file.getName().toLowerCase(Locale.US));
        values.put("_data", resultPath);

        ContentResolver cr = getContentResolver();
        cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);




        return  resultPath;
Mubashir Murtaza
fuente
0

Pruebe este, se transmitirá sobre una nueva imagen creada, para que su imagen sea visible. dentro de una galería. photoFile reemplazar con la ruta del archivo real de la imagen recién creada

private void galleryAddPicBroadCast() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        Uri contentUri = Uri.fromFile(photoFile);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }
Anand Saggam
fuente