保存到 sd 卡的图像不会出现在 Android 图库应用中

Posted

技术标签:

【中文标题】保存到 sd 卡的图像不会出现在 Android 图库应用中【英文标题】:Image, saved to sdcard, doesn't appear in Android's Gallery app 【发布时间】:2010-01-31 01:41:00 【问题描述】:

我将图像保存到 sdcard 中,但直到我取出 sdcard 并将其返回后,它才会出现在 Gallery 应用程序中。

你知道为什么会这样吗?

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

实际上,我也想在图库应用程序中打开刚刚保存的图像,但没有成功 this 是我关于这个问题的问题。

【问题讨论】:

本教程已逐步回答了这个问题:***.com/questions/30506301/… 【参考方案1】:

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

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

this 是您的活动(或任何上下文),mime 类型仅在您使用非标准文件扩展名时才是必需的,null 用于可选回调(我们不需要这么简单的案例)。

【讨论】:

发现,其他人(和谷歌)提供的广播方法,很少起作用)。 这在早期的 android 版本 ~4.0 中对我有用,但现在在 4.3+ 中似乎不起作用。图片未显示在图库应用中。 完美!您可以通过以下方式获取上下文:Android.App.Application.Context 曾在棉花糖中工作【参考方案2】:

我对原始问题和其他任何可能遇到此问题的人的回答:

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

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

【讨论】:

我们是否需要使用媒体扫描仪才能使用此广播?我正在使用另一种方法在我的画廊中显示图像。当我在保存按钮上使用上面的 sendBroadcast 时,单击我的图库未使用新图像更新! 它很旧,但这可能对某人有所帮助-更具体的路径: sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)) ));这种方法(这个答案,不仅仅是我的评论)在模拟器上不起作用。在真机上测试。 我相信接受的答案提供了正确的方法。但如果您尝试支持 API 您的回答对其他设备有帮助。当我尝试扫描我的应用程序文件夹时,它不适用于 HTC。它不显示新添加的图像。 Android 4.4 或更高版本似乎不再支持此功能。这种情况下会抛出权限异常。【参考方案3】:

系统在安装 SD 卡时扫描它以查找任何新的图像(和其他)文件。如果您以编程方式添加文件,则可以使用此类:

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

【讨论】:

旁注:虽然问题涉及文件添加,但 MediaScannerConnection 不提供文件删除解决方案 - 即使在请求扫描已删除文件的父文件夹时也不提供。【参考方案4】:

您也可以按意图将图片添加到媒体库,请查看示例代码以了解它是如何完成的:

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 确认了这一点,但问题是插入的图像未显示在图库中。我检查了画廊的开头和结尾。您能否建议任何方法以使插入的图像立即显示在图库中?【参考方案5】:

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

【讨论】:

第一个条件whitin“IF”语句中的代码在KitKat(Android 4.4.4,API 19)中对我来说很好。【参考方案6】:

这是 MediaScannerConnection 的代码:

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

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

【讨论】:

感谢您的回答。实际上,我很久以前就已经完成了这个项目......我什至不记得我使用过的解决方案是什么。如果您还提供MyMediaConnectorClient 的实现,其他用户可能会发现您的解决方案很有帮助... 是的 - 我现在对此感到非常头疼。请张贴:) 是的,我不太清楚流程应该如何 - 纠正我的错误 我可以使用 MediaScannerConnection 更新 SDCAARD 信息,以便我用相机拍照并将新文件传递到MSC,现在我可以使用连接扫描器客户端访问文件了吗? 流程是:您拍摄一张照片,将其保存到您的 SD 卡,然后更新扫描仪,以便更新文件系统以在设备图库中查看您保存的照片。如果您不使用扫描仪执行此操作,您会在图库中的下一个设备重新启动后看到您的照片。【参考方案7】:

模拟器中有一个应用程序显示 - 'Dev Tools'

单击它并选择“媒体扫描”.. 将扫描所有图像

【讨论】:

很高兴知道,在你说之前我知道的唯一方法就是重启手机:)【参考方案8】:

让您的活动实现“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【参考方案9】:

跟我一起工作

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

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

【讨论】:

【参考方案10】:
 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//files//xyz。 gif。现在我想将此文件保存/复制到图片库并在那里显示。如何做到这一点。【参考方案11】:

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

    先下载图片位图
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;
    还请在您的 AndroidManifest.xml 文件中提供以下权限。
uses-permission android:name="android.permission.INTERNET" uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    这是用 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();
    希望它能解决您的全部问题。

【讨论】:

【参考方案12】:
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)));

希望对你有帮助。

【讨论】:

【参考方案13】:

保存图片后使用这个

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

【讨论】:

这可行,但它不是最好的解决方案。您正在欺骗系统认为 SD 卡将被(重新)安装并可能强制重新扫描整个 SD 卡。 MediaScanner.scanFile(..) 是您现在要添加的文件时的最佳解决方案。 此搜索所有图像。它涉及大量不必要的数据处理,当我们只有一张图片要显示在图库中时,这些数据处理可能无关紧要。【参考方案14】:

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

【讨论】:

【参考方案15】:

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

【讨论】:

【参考方案16】:

如果您在图库中的图像未显示,这也将解决您的问题,而它们可能会在中间显示 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;

【讨论】:

【参考方案17】:

试试这个,它会广播一个创建的新图像,让你的图像可见。画廊内。 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);
    

【讨论】:

以上是关于保存到 sd 卡的图像不会出现在 Android 图库应用中的主要内容,如果未能解决你的问题,请参考以下文章

Android HTTP下载文件并保存到本地或SD卡

捕获图像并将其存储到 SD 卡的新文件夹中

Android - 将图像从 URL 保存到 SD 卡

Android:尝试将图像保存到 SD 卡时应用程序退出

从android寻呼机将图像保存到sd卡

扫描 Android SD 卡以获取新文件