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

Android 在特定路径(文件夹)上触发mediascanner,如何?,android,android-mediascanner,Android,Android Mediascanner,我上了这门课: import android.content.Context; import android.media.MediaScannerConnection; import android.net.Uri; import android.util.Log; public class MediaScannerWrapper implements MediaScannerConnection.MediaScannerConnectionClient { private Med

我上了这门课:

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 i.e. "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启动时,mediascanner服务将启动并运行整个外部存储,以查找是否有任何新的媒体内容,如果它找到了新的媒体内容

  • 它将该媒体内容的条目添加到内容数据库中
  • 内容数据库中的每个条目都包含媒体内容的元数据,如名称、日期、文件大小、文件类型等
  • 因此,当您修改媒体内容时,还需要更新内容数据库
  • 如果内容数据库未更新,则其他应用程序也将无法访问该特定媒体内容
  • 运行媒体扫描程序只是更新内容数据库
您可以自己更新内容数据库,而不是运行媒体扫描程序,它应该可以解决问题

下面是一个关于如何使用内容解析器插入、删除和更新的示例。(搜索“插入、更新和删除数据”部分)

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

嘿,我发现了如何用一个非常简单的代码来实现它

只需调用这行代码:

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

这将触发mediascanner。

故事

   File file = new File(absolutePath);
   Uri uri = Uri.fromFile(file);
   Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
   sendBroadcast(intent);
在Android 4.4之前,我们可以发送一个广播来触发任何特定文件、文件夹甚至存储根上的媒体扫描仪。但是从4.4kitkat开始,Android开发者已经修复了这个问题

我为什么说固定?原因很简单。使用安装在根目录上的媒体_发送广播非常昂贵。运行介质扫描程序是一项昂贵的操作,当用户在存储和深层文件夹结构中拥有大量文件时,情况会变得更糟

安卓4.4之前的版本

保持简单明了。如果您的目标是Android 4.4之前的应用程序。但是请记住,除非绝对必要,否则不要在根目录上使用它

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
来自安卓4.4

你有两种方法

i) 第一个与前面的示例非常相似,但可能无法有效工作,因此不推荐使用

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
ii)现在,让我们继续讨论这个问题的最推荐和最有效的解决方案

在字符串类型的ArrayList中添加已更新文件的文件路径,如下所示

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


将照片添加到图库
部分

作为@Aritra Roy的回答,我决定对这个问题进行一次实验。 我得到的是:

  • Intent.ACTION\u MEDIA\u挂载和Intent.ACTION\u MEDIA\u SCANNER\u扫描文件 可以接受单个文件路径,因此sendBroadcast(新建 Intent(Intent.ACTION\u MEDIA\u SCANNER\u SCAN\u文件,Uri.parse(filePath)); 或发送广播(新的意图(意图、行动、媒体), parse(filePath));将是有效的
  • 如果在Kitkat或更高版本上安装了Intent.ACTION\u MEDIA\u并使用单个文件路径,则应用程序仍将崩溃
  • 如果您在低于Kitkat的设备上使用Intent.ACTION\u MEDIA\u SCANNER\u SCAN\u文件或MediaScannerConnection,您的应用程序将不会强制关闭,但该方法将无法按您的意愿工作
从那个实验中,我认为最好的处理方法是

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

如果我错过了什么,请告诉我你在说什么?哦,没有找到那篇帖子,谢谢!你还可以帮我吗,我对Java中的类和诸如此类的东西很在行。你到底想做什么?用我的程序,我更改了一张图片的名称,然后当我再次尝试打开图片(同一个应用程序,没有关闭它)时,它不再重新识别图片。然而,在mediascan之后,它会重新确认它。所以我想扫描一个路径或一个文件,所以应用程序会重新确认名称的更改。谢谢,当我完成其他事情后,我会继续这样做。他补充说,我自己的答案是,刚刚发现了这个代码,更容易使用:)它会触发mediascanner,但它会扫描SD卡中的所有文件(除了那些带有.nomedia文件的文件夹)。扫描需要时间,具体取决于sd卡中的文件数量。Intent.ACTION_MEDIA_挂载将在Android 4.4+设备上中断,因为Intent现在仅限于系统应用程序。
权限拒绝:不允许发送广播Android.Intent.ACTION.MEDIA_挂载
方式ii将目录转换为文件,请参阅方式i无效(这两条评论都指向Android 5)当我将文件复制到Ringtones文件夹并让Media Scanner扫描它时,它会立即显示在声音选择器上!但是,在我的应用程序从Ringtones文件夹中删除文件后,我也让Media Scanner扫描它(
onScanCompleted()
triggers with uri=null),但是,media picker仍然显示该文件。删除该文件后,如何使media picker不再显示该文件?这应该是更合适的答案,而不是下面接受的答案,因为接受的答案不会扫描特定路径,+1ii)-在安卓7上不起作用,Nexus 5x:sendBroadcast(新意图(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,uriToMyDir));该文件夹位于内部内存的根目录中。只有使用scanFile的方法才有帮助。我将在android 7.0中突破
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);
}
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)));
}