我想将文件从内部存储复制或移动到 SD 卡。我通过存储访问框架 (SAF) 和DocumentFile类来做到这一点...
复制是基于流的,DocumentFile并且没有像File设置上次修改日期的类的功能。
我知道,我将文件移动/复制到 SD 卡,所以我知道我创建了一个本地文件。有了这些信息,是否有可能以某种方式更新基础文件的最后修改日期DocumentFile?
似乎您无法在不丢失上次修改日期的情况下将文件从内部存储移动/复制到 SD 卡...
阅读 - 工作
public long lastModified(DocumentFile file, Context context)
{
long lastModified = 0;
final Cursor cursor = context.getContentResolver().query(file.getUri(), null, null, null, null);
try
{
if (cursor.moveToFirst())
lastModified = cursor.getLong(cursor.getColumnIndexOrThrow(DocumentsContract.Document.COLUMN_LAST_MODIFIED));
}
finally
{
cursor.close();
}
return lastModified;
}
Run Code Online (Sandbox Code Playgroud)
写作 - 不工作
public boolean setLastModified(DocumentFile file, Context context, long time)
{
ContentValues updateValues = new ContentValues();
updateValues.put(DocumentsContract.Document.COLUMN_LAST_MODIFIED, time);
int updated = …Run Code Online (Sandbox Code Playgroud) 在我的应用程序中,我使用以下意图获得SD卡写入权限.如果用户从系统文件资源管理器中选择sd卡文件夹,那么我有SD卡写访问权限.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
startActivityForResult(intent, 42);
Run Code Online (Sandbox Code Playgroud)
之后,我可以使用DocumentFile类修改SD卡中的文件.但我在获取随机文件路径的DocumentFile时遇到问题.
Document.fromFile(new File(path));
Document.fromSingleUri(Uri.fromFile(new File(path)));
Run Code Online (Sandbox Code Playgroud)
两者都返回一个DocumentFile对象,该对象在.canWrite()上返回false.即使我已经获得SD卡许可.
所以我编写了在我的问题末尾发布的方法,以获得一个在.canWrite()上返回true的DocumentFile.但这很慢......而且感觉非常错误!必须有更好的方法来做到这一点.我还写了一个返回相同字符串的方法
String docFileUriString = docFile.getUri().toString();
Run Code Online (Sandbox Code Playgroud)
对于任何文件,其中docFile是由下面的方法返回的DocumentFile.但
DocumentFile.fromTreeUri(Uri.parse(docFileUriString ));
Run Code Online (Sandbox Code Playgroud)
返回一个DocumentFile,它指向sd卡的根,而不是DocumentFile路径.这很奇怪.有人可以提出更优雅的解决方案吗?
public static DocumentFile getDocumentFileIfAllowedToWrite(File file, Context con){
List<UriPermission> permissionUris = con.getContentResolver().getPersistedUriPermissions();
for(UriPermission permissionUri:permissionUris){
Uri treeUri = permissionUri.getUri();
DocumentFile rootDocFile = DocumentFile.fromTreeUri(con, treeUri);
String rootDocFilePath = FileUtil.getFullPathFromTreeUri(treeUri, con);
if(file.getAbsolutePath().startsWith(rootDocFilePath)){
ArrayList<String> pathInRootDocParts = new ArrayList<String>();
while(!rootDocFilePath.equals(file.getAbsolutePath())){
pathInRootDocParts.add(file.getName());
file = file.getParentFile();
}
DocumentFile docFile = null;
if(pathInRootDocParts.size()==0){
docFile = DocumentFile.fromTreeUri(con, rootDocFile.getUri());
}
else{
for(int i=pathInRootDocParts.size()-1;i>=0;i--){
if(docFile==null){docFile = rootDocFile.findFile(pathInRootDocParts.get(i));} …Run Code Online (Sandbox Code Playgroud) 对于Android,以下代码返回一个Uri,可用于创建与目录对应的DocumentFile。
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_CUSTOM_FOLDER);
Run Code Online (Sandbox Code Playgroud)
由于库的许多方法都需要一个参数为 java.io.File,我想知道是否可以从 DocumentFile 中获取 java.io.File。
例如,返回的文档树 Uri treeUri 如下:
treeUri.getPath():/tree/primary:DCIM/deeper/evendeeper
treeUri.toString(): content://com.android.externalstorage.documents/tree/primary%3ADCIM%2Fdeeper%2Fevendeeper
Run Code Online (Sandbox Code Playgroud)
有没有办法得到RandomAccessFile一个给定的DocumentFile?
我知道可以通过输入一个InputStream getUri
InputStream inputStream = getContentResolver().openInputStream(DocumentFile.getUri());
Run Code Online (Sandbox Code Playgroud)
但我需要一个 RandomAccessFile
谢谢你的帮助,
延
我正在尝试使用 DocumentFile(由于存储访问框架)在创建文件之前检查文件是否存在。但是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);
}
Run Code Online (Sandbox Code Playgroud)
在响应时,我们添加/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");
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试递归地遍历 Android DocumentFile 树,但无法获取要为子文件夹返回的文件列表。当我在文件夹 URI 上尝试 listFiles() 时,每次都会返回根文件列表。
为什么这不起作用?
package com.example.usbfoldertest;
import androidx.appcompat.app.AppCompatActivity;
import androidx.documentfile.provider.DocumentFile;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "USBFolderTest";
private static final int RQS_OPEN_DOCUMENT_TREE = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, RQS_OPEN_DOCUMENT_TREE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == RESULT_OK && requestCode == RQS_OPEN_DOCUMENT_TREE){
Uri uriTree = data.getData(); …Run Code Online (Sandbox Code Playgroud) 我使用DocumentFile检查文件元数据和存在.这是如此实现的:
DocumentFile df = DocumentFile.fromSingleUri(context, uri);
boolean exists = df.exists();
Run Code Online (Sandbox Code Playgroud)
该文件的uri以前工作过,直到我有意在文件系统中手动删除该文件,以查看应用程序将如何反应.现在这个堆栈跟踪出现在App中:
03-14 11:33:08.559 27087-27097/? E/DatabaseUtils: Writing exception to parcel
java.lang.IllegalArgumentException: Failed to determine if primary:Download/thefile.txt is child of primary:Download: java.io.FileNotFoundException: Missing file for primary:Download/thefile.txt at /storage/emulated/0/Download/thefile.txt
at com.android.externalstorage.ExternalStorageProvider.isChildDocument(ExternalStorageProvider.java:326)
at android.provider.DocumentsProvider.enforceTree(DocumentsProvider.java:198)
at android.provider.DocumentsProvider.query(DocumentsProvider.java:489)
at android.content.ContentProvider.query(ContentProvider.java:1017)
at android.content.ContentProvider$Transport.query(ContentProvider.java:238)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112)
at android.os.Binder.execTransact(Binder.java:453)
03-14 11:33:08.561 27046-27419/packagename W/DocumentFile: Failed query: java.lang.IllegalArgumentException: Failed to determine if primary:Download/thefile.txt is child of primary:Download: java.io.FileNotFoundException: Missing file for primary:Download/thefile.txt at /storage/emulated/0/Download/thefile.txt
Run Code Online (Sandbox Code Playgroud)
它不会使App崩溃,它只是在我每次尝试使用DocumentFile时生成此堆栈跟踪.所以在最坏的情况下,这只是logcat的一个刺激因素.
我希望避免这种FileNotFoundException使用.exists() …
Android API 有DocumentFile类. 这个类有canWrite()方法。
假设我调用了这个方法并且它返回了true。还假设该对象代表“原始”文件。
现在我该如何做它所说的事情呢?
即,如何将“Hello world”文本写入该文件?
谢谢。
成像,您要检查是否存在“ /folder/subfolder/subsubfolder/test/test.txt”文件,请执行以下操作:
DocumentFile sdCard = ...; // i have already retrieved the sd card root with the users help via SAF
String path = "<SD CARD>/folder/subfolder/subsubfolder/test/test.txt";
List<String> pathParts = Arrays.asList(path.split("/"));
DocumentFile doc = sdCard;
// go through all folders, starting at sd card, to check, if the desired file exists
for (int i = 1; i < pathParts.size(); i++)
{
DocumentFile nextDoc = doc.findFile(pathParts.get(i));
if (nextDoc != null)
doc = nextDoc;
else
{
doc = null;
break;
}
}
if …Run Code Online (Sandbox Code Playgroud) 什么是完全之间的差异java.util.File和android.support.v4.provider.DocumentFile在Java中的Android?
我想让用户拿起文件夹,我的应用程序将在此文件夹中创建一个文件。所以我使用Intent.ACTION_OPEN_DOCUMENT_TREE. Google 说我需要使用 DocumentFile 而不是 File。以前我使用 File 并希望得到类似于下面代码结果的结果
FileOutputStream fs = new FileOutputStream(mFile);
Writer writer = new BufferedWriter(new OutputStreamWriter(fs));
writer.append(mContent);
Run Code Online (Sandbox Code Playgroud)
但 DocumentFile 不是文件,我不能使用 FileOutputStream。所以我用 OutputStream 写了这段代码
Uri treeUri = data.getData();
DocumentFile pickedDir = DocumentFile.fromTreeUri(MainActivity.this, treeUri);
DocumentFile mFile = pickedDir.createFile("text/plain", "Note");
OutputStream out = getContentResolver().openOutputStream(mFile.getUri());
out.write(infos.get(i).getContent().getBytes());
out.flush();
out.close();
Run Code Online (Sandbox Code Playgroud)
这段代码不会重写我的文件,而是创建另一个名为 Note(1) 所以我想知道是否有一种方法可以使用 OutputStream 重写文件,或者使用 FileOutputStream 的另一种方法,但我不知道如何使用它与 DocumentFile。
先感谢您。