扫描Android SD卡的新文件

我的应用程序允许用户将图像保存到他们的SD卡。 但是我不知道如何才能使它出现在画廊,直到你卸载并重新安装SD卡。 我已经search了几天这个问题,但不知道如何使其自动出现。 我发现这个链接,但我不知道如何使用这个类。 这是我用来保存文件。 在try catch块的底部是我想扫描SD卡的新媒体。

FileOutputStream outStream = null; File file = new File(dirPath, fileName); try { outStream = new FileOutputStream(file); bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream); outStream.flush(); outStream.close(); } catch { ... } 

如果有人能指出我正确的方向,我将不胜感激。

我已经尝试了很多不同的方法来触发MediaScanner,这些都是我的结果。

SendBroadcast

最简单和天真的解决scheme。 它包含从您的代码执行以下指令:

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

但是,由于缺less所需的权限,这不再适用于KitKat设备。


MediaScannerWrapper

正如这里发布的(每MediaScannerConnection的答案),它包含了一个MediaScannerConnection实例,以便通过特定的目录触发scan()方法。 这个方法已经被certificate在4.3和更低版本下工作正常,但是对于KitKat(4.4+)仍然没有运气。


FileWalker

试图克服MediaStore没有承诺更新其数据库的许多Play商店应用程序之一是ReScan SD 。 它发送了很多不同的广播:

  sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file://" + Environment.getExternalStorageDirectory()))); sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable"))); sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable/SD"))); sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable/MicroSD"))); sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///mnt/Removable/MicroSD"))); sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///mnt"))); sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///storage"))); sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri.parse("file:///Removable"))); 

并尝试通过在基本目录的每个文件上手动触发scan()方法来支持KitKat。 不幸的是,这是非常耗费CPU时间的,所以不推荐。


“贝壳的方式”

在某些情况下似乎与KitKat一起工作的唯一的东西是通过adb shell发送广播。 所以,这个片段允许你以编程的方式做到这一点:

 Runtime.getRuntime().exec("am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://" + Environment.getExternalStorageDirectory()); 

这更像是一种黑客行为,但目前是我能想到的最好的方式。


底线

上面的每个解决scheme实际上都适用于所有不是KitKat的东西。 这是因为,由于贾斯汀 ,一个错误已经发现并发布给官方的追踪器 。 这意味着,直到错误消除之前,我们没有真正的KitKat支持。

哪一个使用? 其中,我将使用MediaScannerWrapper解决scheme和shell-ish方法(最后一个)。

由于我发布的最后一个答案显然不是一个合适的方法,我在这里find了另一种方法。 你基本上创build一个包装类,初始化它,然后调用scan()方法。 非常有用的职位。 让我知道这是不是合适的。

使用MediaScannerConnection:

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

由于多层次的asynchronous调用,可能会有点痛苦,所以对于API 8(Froyo)来说,有一个辅助函数:

http://developer.android.com/reference/android/media/MediaScannerConnection.html#scanFile(android.content.Context,java.lang.String [],java.lang.String [],android.media.MediaScannerConnection。 OnScanCompletedListener)

您也可以通过发送广播来明确地调用媒体扫描器。

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

您可以使用MediaStore.Images.Media.insertImage将项目插入到图库中。

这是强制扫描的另一种方法:

 context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,"uri to file")); 

然后系统将触发ACTION_MEDIA_SCANNER_FINISHED广播,以便您可以使用BroadcastReceiver

为了能够接收ACTION_MEDIA_SCANNER_FINISHED广播,intentfilter应该包含数据scheme:

 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_FINISHED); intentFilter.addDataScheme("file"); context.registerReceiver(mMediaScannerFinishReceiver, intentFilter); 

来自doc:

公共静态最终stringACTION_MEDIA_SCANNER_SCAN_FILE

在API级别1中添加广播操作:请求媒体扫描器扫描文件并将其添加到媒体数据库。 该文件的path包含在Intent.mData字段中。

公共静态最终stringACTION_MEDIA_SCANNER_FINISHED

在API级别1中添加广播操作:媒体扫描器已完成扫描目录。 Intent.mData字段包含扫描目录的path。