您好我正在尝试通过启动扫描来刷新图库。对于运行Kitkat及更高版本的设备,我正在使用mediascannerconnection。但mediaScannerConnection需要绝对路径才能进行扫描。我所拥有的是 DocumentFile ,它似乎没有任何方法来获取它的绝对路径。
以下是我正在使用的代码:
要获得使用新的棒棒糖API写入文件夹的权限 - >将所选URI保存到全局变量--->要隐藏的逻辑(创建/删除“.nomedia”文件)。
// Calling folder selector.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, 42);
..............
@SuppressLint("NewApi") @Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (resultCode == RESULT_OK && requestCode == 42) {
Uri treeUri = resultData.getData();
getContentResolver().takePersistableUriPermission(treeUri,
// Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION |
Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
path = treeUri.getPath();
}
}
..........
public void hide(boolean hide){
DocumentFile pickedDir = DocumentFile.fromTreeUri(this,Uri.parse(path));
if(hide){
if(pickedDir.findFile(".nomedia")==null){
pickedDir.createFile(null, ".nomedia");
tellgallery(pickedDir.findFile(".nomedia").getUri().getPath());
}
}
else{
DocumentFile filetodelete = pickedDir.findFile(".nomedia");
if(filetodelete!=null){
filetodelete.delete();
tellgallery(filetodelete.getPath());
}
}
}
上面的代码完美无缺,可以在所需的文件夹中创建/删除“.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而不是实际路径。
< / LI>非常感谢任何帮助。
答案 0 :(得分:0)
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.parse("file://" + Environment.getExternalStorageDirectory())));
答案 1 :(得分:0)
如您所知,删除不会触发媒体扫描,而DocumentFile
Uri不适用于MediaScanner
,因此在删除文件之前,您必须查询{{1}为了一个有效的路径。我所做的是遍历所有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));
}
}
数组列表将包含需要从MediaScanner中清除的所有尾随路径。所以我做了另一个循环,要求MediaScanner删除所有 end 的条目具有相同的值:
segmentsToDelete
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);
}
调用将返回已删除行的数量,因此您可以在其中放置一个断言以确保它始终返回1.如果由于某种原因文档从未进入mediascanner,则可以返回较少。 .delete()
方法是一个自定义函数,用于确保SQLITE like pattern matching与不正确的路径不匹配:
escapedLike()
当然,如果要删除整个目录,上述操作也是一样的。在这种情况下,您不需要运行循环,您可以先在DocumentFile上为目录调用static String escapedLike(@NonNull String text)
{
return text.replace("%", "\\%").replace("_", "\\_");
}
,然后在构建删除查询时,使用尾随.delete()
作为sql {{ 1}}参数应返回大量删除(文件在媒体扫描程序中注册的数量)。
使用%
匹配而不是精确完整路径的原因是因为从LIKE
获得的先前值永远不会匹配完整路径。像LIKE
这样的DocumentFile
数据库稍后将返回类似E25A-3848:Pictures/appname/images/foo.jpg
的内容。很遗憾,删除不会在内部调用MediaScanner ......