保存到sdcard的图像未出现在Android的Gallery应用中


92

我将图像保存到sdcard中,直到我拔下sdcard并将其返回之前,它才出现在Gallery应用程序中。

您知道为什么会这样吗?

似乎Gallery应用程序具有一些在文件保存时未更新的缓存...

实际上,我也想在Gallery应用程序中打开刚刚保存的图像,但没有成功,
是我对此问题的疑问。


1
在本教程中,已逐步回答了这个问题: stackoverflow.com/questions/30506301/…–
Takermania

Answers:



85

一个更简单的解决方案是使用静态便捷方法scanFile()

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

this您的活动(或任何上下文)在哪里,仅当您使用非标准文件扩展名时才需要mime类型,null而对于可选的回调则为mime类型(在这种简单情况下我们不需要)。


2
当场,别人(和谷歌)提供的广播方法,很少起作用)。
克里斯·詹金斯(Chris.Jenkins)2013年

2
这在较早的Android版本〜4.0中对我有效,但现在在4.3+中似乎不起作用。图像未显示在图库应用程序中。
hooby3dfx 2014年

太好了!您可以使用以下内容获取上下文:Android.App.Application.Context
2016年

在棉花糖中工作
Hitesh Sahu'1

66

我对原始问题以及可能存在此问题的其他人的回答:

我遇到了同样的问题,我保存在SD卡中的应用程序中的图像没有立即显示在图库中。经过一番搜索后,我发现在“保存到sdcard”代码之后插入了这一行代码,以解决该问题:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

我们需要使用媒体扫描仪才能使用此广播吗?我正在使用另一种方法在图库中显示图像。当我在保存按钮上使用sendBroadcast上面的按钮时,我的画廊没有使用新图像更新!

4
它很旧,但是可能对某人有帮助-更具体的路径:sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse(“ file://” + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES))))); 此方法(此答案,不仅是我的评论)在模拟器上不起作用。在真实设备上测试。

我相信已接受的答案提供了正确的方法。但是,如果您尝试支持API <= 7,那么这是一个很好的备用。
Amr Mostafa

您的答案对其他设备很有帮助。当我尝试扫描我的Application文件夹时,它在HTC上不起作用。它不会显示新添加的图像。
MobileEvangelist

6
Android 4.4或更高版本似乎不再支持此功能。在这种情况下,将引发权限异常。
rsp1984

13

您还可以按意图将图像添加到媒体库,查看示例代码以了解其完成方式:

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

你好 这种方法将图像添加到MediaStore中,我已经通过检查返回的内容确认了它,Uri但是问题是插入的图像未在图库中显示。我已经检查了画廊的开头和结尾。您能否建议任何方法以使插入的图像立即显示在图库中?
Shajeel Afzal 2015年

12

刷新图库,包括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())));
}

在KitKat(Android 4.4.4,API 19)中,第一个条件“ IF”语句中的代码对我来说很好用。
亚历克斯

8

这是MediaScannerConnection的代码:

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

newfile是新文件/已保存文件的File对象。


2
谢谢您的回答。实际上,很久以前我已经完成了这个项目……我什至不记得我使用过什么解决方案。其他用户可能会发现你的解决方案帮助,如果您还需要提供执行MyMediaConnectorClient...
迈克尔·凯斯勒

是的-目前,我对此感到非常头疼。请张贴:)
史蒂夫

是的,我不清楚流程应该如何-纠正我在哪里出错,我可以使用MediaScannerConnection更新SDCAARD信息,以便用相机拍照并将新文件传递到MSC中,现在就可以访问文件了与连接扫描仪客户端一起使用?
史蒂夫

流程是:您拍摄一张照片,将其保存到sdcard中,然后更新扫描仪,以便更新文件系统以在设备库中查看保存的照片。如果您不使用扫描仪执行此操作,则在画廊中的下一台设备重启后,您会看到您的照片。
2010年


6

让您的活动实现“ MediaScannerConnectionClient”并将其添加到您的活动中:

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

嗨!如果我们知道Uri图像的图像,该怎么办,例如:content://media/external/images/media/1231778
Shajeel Afzal

6

与我一起工作

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

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));

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

我想保存位于外部存储器中的动画gif文件,并且具有以下路径,即/storage/emulated/0/Android/data/<PackageName>/files/<FolderName>/xyz.gif。现在,我想将此文件保存/复制到“图片库”并在此处显示。这该怎么做。
Zia Ur Rahman

3

在这里,我分享了可以以位图的形式加载图像并将该图像保存在应用程序名称文件夹中的sdcard画廊中的代码。您应该按照以下步骤

  1. 首先下载图像位图



     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. 另请在您的AndroidManifest.xml文件中提供以下权限。


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


  1. 这是用Activty编写的完整代码,我们要在其中执行此任务。



     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. 希望它可以解决您的整个问题。

3
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

似乎不适用于KITKAT。它将引发权限拒绝异常并使应用程序崩溃。为此,我做了以下工作,

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

希望能帮助到你。


2

保存图像后使用

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

3
这有效,但这不是最佳解决方案。您正在欺骗系统,以为SD卡将被(重新)安装,并可能迫使重新扫描整个SD卡。当您现在要添加文件时,MediaScanner.scanFile(..)是最佳解决方案。
pocmo 2012年

1
此搜索所有图像。而且它涉及许多不必要的数据处理,当我们只在画廊中显示单个图像时,这些数据处理可能是不相关的。
拉胡尔·拉斯托吉

2

我的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();
    }
}

0

您需要授予“图库”应用程序的权限。只需长按主屏幕中的图库应用程序图标,然后点击屏幕顶部弹出的“ APP INFO”(应用程序信息)。这样做会显示图库应用程序设置。现在进入“权限”选项卡,并通过切换启用存储和摄像机权限。现在转到您的本机图库应用程序,您将获得保存的图像。


0

如果您的图库中的图像没有显示,而是在Midle中显示404类型的位图,这也可以解决您的问题。请在您的图片中添加我代码中的标签,因为必须有一些元数据才能在图库中显示图片。

      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;

0

试试这个,它将广播有关创建的新图像的信息,因此您的图像可见。在画廊内。 photoFile替换为新创建图像的实际文件路径

private void galleryAddPicBroadCast() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        Uri contentUri = Uri.fromFile(photoFile);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.