L'image, enregistrée sur sdcard, n'apparaît pas dans l'application Galerie d'Android

93

J'enregistre une image sur la carte SD et elle n'apparaît pas dans l'application Galerie tant que je n'ai pas retiré la carte SD et l'ai renvoyée.

Avez-vous une idée de pourquoi?

On dirait que l'application Galerie a un cache qui n'est pas mis à jour lors de l'enregistrement du fichier ...

En fait, je souhaite également ouvrir l'image qui vient d'être enregistrée dans l'application Galerie et je n'ai aucun succès avec
cela, c'est ma question à propos de ce problème.

Michael Kessler
la source
1
Cette question a reçu une réponse étape par étape dans ce tutoriel: stackoverflow.com/questions/30506301
...

Réponses:

45

Le système scanne la carte SD lorsqu'elle est montée pour trouver de nouveaux fichiers image (et autres). Si vous ajoutez un fichier par programme, vous pouvez utiliser cette classe:

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

hackbod
la source
4
Note latérale: bien que la question se réfère à l'ajout de fichiers, MediaScannerConnection ne fournit pas de solution pour la suppression de fichiers - même pas lors d'une demande d'analyse du dossier parent d'un fichier supprimé.
AlikElzin-kilaka
86

Une solution plus simple consiste à utiliser la méthode de commodité statique scanFile () :

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

thisest votre activité (ou quel que soit le contexte), le type mime n'est nécessaire que si vous utilisez des extensions de fichier non standard et le nullest pour le rappel optionnel (dont nous n'avons pas besoin dans un cas aussi simple).

Darrenp
la source
2
Spot on, la méthode de diffusion que d'autres (et Google) fournissent, fonctionne très rarement).
Chris.Jenkins
2
Cela fonctionnait pour moi dans les versions antérieures d'Android ~ 4.0, mais maintenant dans 4.3+ ne semble pas fonctionner. Les images ne s'affichent pas dans l'application Galerie.
hooby3dfx
Parfait! Vous pouvez obtenir le contexte avec: Android.App.Application.Context
jug
Travaillé en guimauve
Hitesh Sahu
66

Ma réponse à la question initiale et à toute autre personne susceptible d'avoir ce problème:

J'avais le même problème, les images dans mon application que les personnes enregistrées sur la carte SD n'apparaissaient pas immédiatement dans leur galerie. Après quelques recherches, j'ai trouvé cette ligne de code insérée après mon code `` enregistrer sur la carte SD '' qui a résolu le problème:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
OmbreDieu
la source
devons-nous utiliser un scanner multimédia pour pouvoir utiliser cette diffusion? J'utilise une autre méthode pour afficher des images dans ma galerie. Lorsque j'utilise ci-dessus sendBroadcast sur le bouton Enregistrer, cliquez sur ma galerie n'est pas mise à jour avec la nouvelle image!
modifier
4
C'est vieux mais cela peut aider quelqu'un - un chemin plus spécifique: sendBroadcast (new Intent (Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file: //" + Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_PICTURES)))); Cette méthode (cette réponse, pas seulement mon commentaire) ne fonctionne pas sur l'émulateur. Testez sur un appareil réel.
Je crois que la réponse acceptée offre la bonne façon de procéder. Mais si vous essayez de prendre en charge l'API <= 7, c'est une bonne solution de rechange.
Amr Mostafa
Votre réponse est utile pour les autres appareils. Cela ne fonctionne pas sur HTC, lorsque j'essaye de scanner mon dossier Application. Il ne montre pas l'image nouvellement ajoutée.
MobileEvangelist
6
Cela ne semble plus pris en charge sur Android 4.4 ou supérieur. Une exception d'autorisation sera levée dans ce cas.
rsp1984
13

Vous pouvez également ajouter une image à la galerie multimédia par intention, jetez un œil à l'exemple de code pour voir comment cela est fait:

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
la source
Salut. Cette méthode ajoute l'image au MediaStore, je l'ai confirmée en vérifiant le retour Urimais le problème est que l'image insérée ne s'affiche pas dans la galerie. J'ai vérifié à la fois au début et à la fin de la galerie. Pouvez-vous suggérer une méthode pour que l'image insérée s'affiche immédiatement dans la galerie?
Shajeel Afzal
12

Actualisation de la galerie, y compris 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
la source
Le code qui est à l'intérieur de la première condition avec l'instruction "IF" fonctionne très bien pour moi dans KitKat (Android 4.4.4, API 19).
Alex
8

Voici le code de MediaScannerConnection:

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

newfile est l'objet File de votre nouveau fichier / enregistré.

3dmg
la source
2
Merci pour votre réponse. En fait, j'ai déjà terminé ce projet il y a longtemps ... Je ne me souviens même pas quelle était la solution que j'ai utilisée. D'autres utilisateurs pourraient trouver votre solution utile si vous fournissez également l'implémentation de MyMediaConnectorClient...
Michael Kessler
oui - j'ai de vrais maux de tête avec ça en ce moment. S'il vous plaît poster :)
Steve
Oui, je ne suis pas vraiment clair sur la manière dont le flux doit être avec avec un client de scanner de connexion?
Steve
Le flux est le suivant: vous prenez une photo, enregistrez-la sur votre carte SD, puis effectuez la mise à jour du scanner, de sorte que le système de fichiers soit mis à jour pour voir votre photo enregistrée dans la galerie de périphériques. Si vous ne faites pas cela avec le scanner, vous verrez votre photo après le redémarrage de l'appareil suivant dans la galerie.
3dmg
7

il y a une application dans l'émulateur qui dit - 'Dev Tools'

cliquez dessus et sélectionnez 'Balayage média'. toutes les images seront numérisées

Abhishek Susarla
la source
bon à savoir, le seul moyen que je savais avant de dire cela est de redémarrer le téléphone :)
mishkin
6

Laissez votre activité implémenter 'MediaScannerConnectionClient' et ajoutez ceci à votre activité:

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
la source
Salut! Que faire si nous connaissons le Uride l'image, par exemple:content://media/external/images/media/1231778
Shajeel Afzal
6

ce travail avec moi

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

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
user3245604
la source
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
la source
Je veux enregistrer un fichier gif animé qui se trouve dans un stockage externe et j'ai le chemin, c'est-à-dire / stockage / émulé / 0 / Android / data / <PackageName> / files / <FolderName> /xyz.gif. Maintenant, je veux enregistrer / copier ce fichier dans la galerie d'images et y afficher. Comment faire cela.
Zia Ur Rahman
3

Ici, je partage du code qui peut charger une image sous forme de bitmap et enregistrer cette image sur la galerie sdcard dans le dossier du nom de l'application. Vous devez suivre ces étapes

  1. Téléchargez d'abord l'image bitmap



     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. Veuillez également fournir l'autorisation suivante dans votre fichier AndroidManifest.xml.


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


  1. Voici tout le code écrit dans Activty dans lequel nous voulons effectuer cette tâche.



     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. J'espère que cela pourra résoudre tout votre problème.
VISHNU GARG
la source
3
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

Ne semble pas fonctionner sur KITKAT. Il lève une exception de refus d'autorisation et plante l'application. Donc pour cela, j'ai fait ce qui suit,

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)));

J'espère que ça aide.

Muhammad Riyaz
la source
2

Utilisez ceci après avoir enregistré l'image

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
Deepu
la source
3
Cela fonctionne mais ce n'est pas la meilleure solution. Vous trompez le système en lui faisant croire que la carte SD serait (re) montée et forcerait peut-être une nouvelle analyse de la carte SD entière. MediaScanner.scanFile (..) est la meilleure solution lorsque vous avez maintenant le fichier que vous souhaitez ajouter.
pocmo
1
Cette recherche pour toutes les images. Et cela implique beaucoup de traitements de données inutiles qui peuvent ne pas être pertinents lorsque nous n'avons qu'une seule image à afficher dans la galerie.
Rahul Rastogi
2

Mon code pour 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();
    }
}
Marian
la source
0

Vous devez accorder des autorisations à l'application Galerie. Appuyez simplement longuement sur l'icône de l'application de la galerie dans l'écran d'accueil et appuyez sur `` INFO APP '' qui apparaît en haut de l'écran. Cela affichera les paramètres de l'application de la galerie. Maintenant, allez dans l'onglet Permissions et activez le stockage, les autorisations de la caméra en le basculant. Maintenant, accédez à votre application de galerie native et vous obtiendrez vos images enregistrées.

Devanshu Jain
la source
0

Cela résoudra également votre problème si votre image dans la galerie ne s'affiche pas à la place, elle pourrait afficher une image bitmap de type 404 au milieu. s'il vous plaît ajouter les balises qui sont dans mon code avec votre image car il doit y avoir des méta-données afin d'afficher l'image dans la galerie.

      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
la source
0

Essayez celui-ci, il diffusera sur une nouvelle image créée, afin que votre image soit visible. à l'intérieur d'une galerie. photoFile replace par le chemin de fichier réel de l'image nouvellement créée

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
la source