Java 使用MediaScanner连接刷新库,文档文件URI从TreeUri获得,用于棒棒糖版本
您好,我正在尝试通过启动扫描刷新库。对于运行Kitkat和更高版本的设备,我使用mediascannerconnection。但是mediaScannerConnection需要绝对路径进行扫描。我拥有的是一个文档文件,它似乎没有任何方法来获取它的绝对路径 下面是我正在使用的代码: 要获得使用新棒棒糖API写入文件夹的权限-->将选定URI保存到全局变量-->要隐藏的逻辑(创建/删除“.nomedia”文件) 上述代码工作正常,在所需文件夹中创建/删除“.nomedia”文件 现在,当我试图告诉画廊,该文件夹的文件已更改。Gallery无法选择更改 下面是刷新/请求扫描的代码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”文件 现在,当我试图告诉
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()
,然后在构建删除查询时,对sqlLIKE
参数使用一个尾随的%
,该参数应返回大量删除(在介质扫描仪中注册的文件数)
之所以使用
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("_", "\\_");
}