我正在尝试使用DocumentFile(由于Storage Access Framework)在创建文件之前检查文件是否存在。但是DocumentFile().fromTreeUri()
删除了可能的Uri中不存在的部分,这将导致DocumentFile().exists()
始终返回true,无论它是否存在。
我创建了一个简单的例子来说明我的观点。首先,我们要求用户选择一个目录:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Ask the user for the source folder
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, 100);
}
在响应时,我们将/fictionalFile
添加到路径(因此使其成为不存在的文件),然后检查它是否存在:
public void onActivityResult(int requestCode, int resultCode, Intent resultData)
{
if (resultCode == RESULT_OK)
{
if(requestCode == 100)
{
Uri fictionalURI = Uri.parse(resultData.getData()+"/fictionalFile");
DocumentFile fictionalFile = DocumentFile.fromTreeUri(this, fictionalURI);
Log.i("STORAGE", "FICTIONAL URI: "+fictionalURI);
Log.i("STORAGE", "FICTIONAL DOCUMENTFILE URI: "+fictionalFile.getUri());
if(fictionalFile.exists())
{
Log.i("STORAGE", "Fictional file exists");
}
}
}
}
但是,当在虚构的Uri上运行DocumentFile.fromTreeUri()时,伪造的“ / fictionalfile”部分会丢失,这将导致DocumentFile.exists()函数返回true,如下面的LogCat所示: / p>
I /存储:虚假URI:content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/fictionalFile
I /存储:虚构文档文件URI:content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/document/17FA-1C18%3AFileSync%2Ftarget
I /存储:虚构文件存在
(在上面的示例中,我使用的是SD卡,因此使用了长路径名)
还有另一种方法来检查是否存在尚未创建的DocumentFile吗?用例是将文件从目录A复制到目录B时,我想在开始传输之前检查目录B中是否已经存在该文件。
更新:我现在意识到使用DocumentFile.fromTreeUri()
是错误的,应该使用DocumentFile.fromSingleUri()
。这会有所帮助,但是在新文件上运行.exists()
时,我得到的是W/DocumentFile: Failed query: java.lang.UnsupportedOperationException: Unsupported Uri content://com.android.externalstorage.documents/tree/17FA-1C18%3AFileSync%2Ftarget/fictionalFile
。有什么想法吗?
public void onActivityResult(int requestCode, int resultCode, Intent resultData)
{
if (resultCode == RESULT_OK)
{
if(requestCode == 100)
{
Uri fictionalURI = Uri.parse(resultData.getData()+"/fictionalFile");
DocumentFile fictionalFile = DocumentFile.fromSingleUri(this, fictionalURI);
Log.i("STORAGE", "FICTIONAL URI: "+fictionalURI);
Log.i("STORAGE", "FICTIONAL DOCUMENTFILE URI: "+fictionalFile.getUri());
if(fictionalFile != null && fictionalFile.exists())
{
Log.i("STORAGE", "Fictional file exists");
}
}
}
}
答案 0 :(得分:1)
假设treeUri
为Uri
返回的ACTION_OPEN_DOCUMENT_TREE
,使用treeUri
将DocumentFile
包裹在fromTreeUri()
中,然后调用{{1 findFile()
上的}}提供您正在寻找的显示名称(例如DocumentFile
)。如果返回fictionalFile
,则没有与显示名称匹配的文件。
IOW:
null
不过请注意,“显示名称”不一定是文件名。
答案 1 :(得分:1)
就我而言,当我在coroutineWorker中使用applicationContext检查DocumentFile.fromSingleUri(context, media.fileUri)?.exists() == true
时,从外部应用程序(例如,在文件管理器中)删除文件时,DocumentProvider始终返回true。
问题已通过uri.isFileExist(context)
import android.content.Context
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
fun DocumentFile?.isFile() = this?.isFile ?: false
fun DocumentFile?.isExists() = this?.exists() ?: false
fun DocumentFile?.getLength() = this?.length() ?: 0
fun DocumentFile?.isFileExist() = isFile() && isExists() && getLength() > 0
fun Uri.isFileExist(context: Context) =
DocumentFile.fromSingleUri(context, this).isFileExist()