在特定path(文件夹)上触发mediascanner,如何?

我有这个类:

import android.content.Context; import android.media.MediaScannerConnection; import android.net.Uri; import android.util.Log; public class MediaScannerWrapper implements MediaScannerConnection.MediaScannerConnectionClient { private MediaScannerConnection mConnection; private String mPath; private String mMimeType; // filePath - where to scan; // mime type of media to scan ie "image/jpeg". // use "*/*" for any media public MediaScannerWrapper(Context ctx, String filePath, String mime){ mPath = "/sdcard/DCIM/Camera"; mMimeType = "jpg"; mConnection = new MediaScannerConnection(ctx, this); } // do the scanning public void scan() { mConnection.connect(); } // start the scan when scanner is ready public void onMediaScannerConnected() { mConnection.scanFile(mPath, mMimeType); Log.w("MediaScannerWrapper", "media file scanned: " + mPath); } public void onScanCompleted(String path, Uri uri) { // when scan is completes, update media file tags } } 

如何在其他课堂上使用它? 我不知道如何正确地使用类,我试过但没有任何工作。 我做错了什么,但我不知道是什么,有人可以帮助我。

故事

在Android 4.4之前,我们可以发送广播来触发媒体扫描器在任何特定的文件或文件夹,甚至在存储的根。 但是从4.4 KitKat,这已经被Android开发者修复了。

我为什么说固定? 原因很简单。 在根目录上使用MEDIA_MOUNTED发送广播非常昂贵。 运行Media Scanner是一项昂贵的操作,当用户在存储和深层文件夹结构中获得大量文件时,情况会变得更糟。

在Android 4.4之前

保持直线和简单。 如果您在Android 4.4之前定位您的应用 但请记住,除非绝对必要,否则不要在根目录中使用它。

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

从Android 4.4

有两种方法给你。

我)第一个是非常类似于前面的例子,但可能无法有效地工作,也不build议。

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

ii)现在,让我们继续讨论这个问题最值得推荐和最有效的解决scheme。

在Stringtypes的ArrayList中添加已更新的文件的文件path,如下所示

 ArrayList<String> toBeScanned = new ArrayList<String>(); toBeScanned.add(item.getFilePath()); 

现在,您需要运行MediaScannerConnection类的scanFile()静态方法,并传递包含已更新且需要介质扫描的所有文件的列表的String数组。

您也可以让侦听程序在完成单个文件的扫描时作出响应。

 String[] toBeScannedStr = new String[toBeScanned.size()]; toBeScannedStr = toBeScanned.toArray(toBeScannedStr); MediaScannerConnection.scanFile(getActivity(), toBeScannedStr, null, new OnScanCompletedListener() { @Override public void onScanCompleted(String path, Uri uri) { System.out.println("SCAN COMPLETED: " + path); } }); 

嘿,我发现如何用一个非常简单的代码来做到这一点。

只需调用这一行代码:

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

这应该触发mediascanner。

在Android中,媒体扫描器使用内容数据库来跟踪设备上存在的所有媒体内容。

当Android启动时,mediascanner服务启动并运行整个外部存储,以查找是否有任何新的媒体内容,

  • 它将该媒体内容的条目添加到内容数据库中
  • 内容数据库中的每个条目都包含媒体内容的元数据,如名称,date,文件大小,文件types等。
  • 因此,当您对媒体内容进行修改时,您还需要更新内容数据库。
  • 如果内容数据库没有更新,则其他应用程序也将无法访问该特定的媒体内容。
  • 运行媒体扫描程序只是更新内容数据库

而不是运行媒体扫描器,您可以自己更新内容数据库,它应该解决问题。

以下是关于如何使用内容parsing器插入,删除和更新的解释 。 (search“插入,更新和删除数据”部分)

编辑:这个答案有一个示例代码。 检查Janusz的答案。

  File file = new File(absolutePath); Uri uri = Uri.fromFile(file); Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri); sendBroadcast(intent); 
 private void galleryAddPic() { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); File f = new File(mCurrentPhotoPath); Uri contentUri = Uri.fromFile(f); mediaScanIntent.setData(contentUri); this.sendBroadcast(mediaScanIntent); } 

参考: http : //developer.android.com/training/camera/photobasics.html#TaskGallery

Add the Photo to a Gallery部分

正如@Aritra Roy的回答,我决定对这个问题做一个实验。 我在这里得到的是:

  • Intent.ACTION_MEDIA_MOUNTED和Intent.ACTION_MEDIA_SCANNER_SCAN_FILE可以接受单个文件的path,所以sendBroadcast(新的Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.parse(filePath))); 或者sendBroadcast(新的Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse(filePath))); 将是有效的。
  • 如果您在Kitkat或更高版本上使用带有Intent.ACTION_MEDIA_MOUNTED的单独文件path,则应用程序仍然会崩溃
  • 如果您在低于Kitkat的设备上使用Intent.ACTION_MEDIA_SCANNER_SCAN_FILE或MediaScannerConnection,则您的应用程序不会强制closures,但该方法只是无法正常工作。

从那个实验中,我认为最好的处理方法是

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { MediaScannerConnection.scanFile(context, new String[]{imagePath}, null, new MediaScannerConnection.OnScanCompletedListener() { public void onScanCompleted(String path, Uri uri) { //something that you want to do } }); } else { context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + imagePath))); } 

让我知道如果我错过了什么