Java 使用MediaScanner连接刷新库,文档文件URI从TreeUri获得,用于棒棒糖版本

Java 使用MediaScanner连接刷新库,文档文件URI从TreeUri获得,用于棒棒糖版本,java,uri,android-5.0-lollipop,android-mediascanner,documentfile,Java,Uri,Android 5.0 Lollipop,Android Mediascanner,Documentfile,您好,我正在尝试通过启动扫描刷新库。对于运行Kitkat和更高版本的设备,我使用mediascannerconnection。但是mediaScannerConnection需要绝对路径进行扫描。我拥有的是一个文档文件,它似乎没有任何方法来获取它的绝对路径 下面是我正在使用的代码: 要获得使用新棒棒糖API写入文件夹的权限-->将选定URI保存到全局变量-->要隐藏的逻辑(创建/删除“.nomedia”文件) 上述代码工作正常,在所需文件夹中创建/删除“.nomedia”文件 现在,当我试图告诉

您好,我正在尝试通过启动扫描刷新库。对于运行Kitkat和更高版本的设备,我使用mediascannerconnection。但是mediaScannerConnection需要绝对路径进行扫描。我拥有的是一个文档文件,它似乎没有任何方法来获取它的绝对路径

下面是我正在使用的代码:

要获得使用新棒棒糖API写入文件夹的权限-->将选定URI保存到全局变量-->要隐藏的逻辑(创建/删除“.nomedia”文件)

上述代码工作正常,在所需文件夹中创建/删除“.nomedia”文件

现在,当我试图告诉画廊,该文件夹的文件已更改。Gallery无法选择更改

下面是刷新/请求扫描的代码

private void tellgallery(String path) {
    pathtonomedia = path;
    if(path!=null){
    if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
        mediaScannerConnection = new MediaScannerConnection(con,mediaScannerConnectionClient);
        mediaScannerConnection.connect();
    }
      else{
            this.sendBroadcast(new Intent(
            Intent.ACTION_MEDIA_MOUNTED,
            Uri.parse("file://" + path)));
      }
    }

}
MediaScanner类如下所示:

private MediaScannerConnectionClient mediaScannerConnectionClient = 
        new MediaScannerConnectionClient() {

        @Override
        public void onMediaScannerConnected() {
            mediaScannerConnection.scanFile(pathtonomedia, null);              
        }

        @Override
        public void onScanCompleted(String path, Uri uri) {
            if(path.equals(pathtonomedia))
                mediaScannerConnection.disconnect();

        }
    };
但是代码不会刷新库,我仍然可以在库中看到文件夹。不过,系统刷新后,文件夹可能会在10到20分钟后消失

最后我想要的是

  • 我是否可以获取DocumentFile实例的路径?。这样我就可以直接将它传递到mediascanner路径

  • 或者有没有其他方法可以让我们请求扫描棒棒糖中的特定文件夹。特定文件夹在SDCARD中,我只知道它的URI,而不知道它的实际路径


非常感谢您的帮助。

您试过这个吗?这在许多情况下都有效。它在调用MediaScannerConnection后对我有效,这应该可以扫描整个SD卡

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

正如您所注意到的,删除不会触发媒体扫描,
DocumentFile
Uri不适用于
MediaScanner
,因此在删除文件之前,您必须查询
MediaScanner
以获得有效路径。我要做的是遍历所有
DocumentFile
对象,并对它们调用
.getLastPathSegment()
。这将返回如下值:

E25A-3848:Pictures/appname/images/foo.jpg
在我的测试中,这个值总是有一个冒号,将一些特定于设备的值与路径的尾部分隔开。如果用户选择一个内部存储器而不是
E25A-3838
,他们将得到一个类似
primary
的单词,但这并不相关。重要的是,您希望得到冒号后面的任何内容,因此我通过需要删除的文档进行如下迭代:

String temp = document.getUri().getLastPathSegment();
final int lastColon = temp.lastIndexOf(":");
if (lastColon > 0) {
    boolean deletionSuccess = document.delete();
    if (deletionSuccess) {
        Log.d(TAG, "Deleted " + document.getUri());
        segmentsToDelete.add(temp.substring(lastColon + 1));
    }
}
循环完成后,文档将消失,
segmentsToDelete
数组列表将包含需要从MediaScanner中清除的所有后续路径。因此,我执行另一个循环,要求MediaScanner删除以相同值结尾的所有条目:

final Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
for (String lastPathSegment : segmentsToDelete) {
    final int result = contentResolver.delete(uri,
        MediaStore.MediaColumns.DATA + " LIKE ? ESCAPE '\\'",
        new String[]{"%" + escapedLike(lastPathSegment)}
    );
    Log.d(TAG, "Media deletion for " + lastPathSegment + " was " + result);
}
.delete()
调用将返回已删除的行数,因此您可以在其中放置一个断言,以确保它始终返回1。如果由于某种原因文档从未进入mediascanner,则返回的可能会更少。
escapedLike()
方法是一个自定义函数,用于确保与不正确的路径不匹配:

static String escapedLike(@NonNull String text)
{
    return text.replace("%", "\\%").replace("_", "\\_");
}
当然,如果您想删除整个目录,上述方法也同样适用。在这种情况下,您不需要运行循环,您可以首先对目录的文档文件调用
.delete()
,然后在构建删除查询时,对sql
LIKE
参数使用一个尾随的
%
,该参数应返回大量删除(在介质扫描仪中注册的文件数)


之所以使用
LIKE
匹配而不是精确的完整路径,是因为从
DocumentFile
获得的上一个值永远不会匹配完整路径。类似于
E25A-3848:Pictures/appname/images/foo.jpg
的内容稍后将由
MediaScanner
数据库返回,如
/storage/sdcard1/Pictures/appname/images/foo.jpg
。很遗憾,删除操作没有在内部调用MediaScanner…

是的,我目前正在生产版本中使用它,但这在kitkat以上的版本中不起作用。新版本中不允许发送广播。。
static String escapedLike(@NonNull String text)
{
    return text.replace("%", "\\%").replace("_", "\\_");
}