扫描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。