问题
In my app I gain sd card write permission using the following intent. If the user selects the sd card folder from the system file explorer then I have sd card write access.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
startActivityForResult(intent, 42);
After that I am able to modify files in th sd card using the DocumentFile class. But I'm having problem getting a DocumentFile for a random file path.
Document.fromFile(new File(path));
Document.fromSingleUri(Uri.fromFile(new File(path)));
both return a DocumentFile object that returns false on .canWrite(). Even though I allready have sd card permission.
So I wrote the method posted in the end of my question to get a DocumentFile that returns true on .canWrite(). But this is slow...And also feels very wrong! There has to be a better way to do this. I also wrote a method that returns the same string as
String docFileUriString = docFile.getUri().toString();
for any file, where docFile is the DocumentFile that is returned by the method below. But
DocumentFile.fromTreeUri(Uri.parse(docFileUriString ));
returns a DocumentFile that points to the root of the sd card instead of the DocumentFile path. Which is just weird. Can someone suggest a more elegant solution?
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));}
else{docFile = docFile.findFile(pathInRootDocParts.get(i)); }
}
}
if(docFile!=null && docFile.canWrite()){
return docFile;
}else{
return null;
}
}
}
return null;
}
回答1:
to respond to @AndiMar (21 Mar), I just check if it exists on internal storage, if it does no need to worry.
try {
if (sourcefile.toString().contains(Environment.getExternalStorageDirectory().toString())) {
if (sourcefile.exists()) {
sourcefile.delete();
}
} else {
FileUtilities fio = new FileUtilities();
DocumentFile filetodelete = fio.getDocumentFileIfAllowedToWrite(sourcefile, context);
if (filetodelete.exists()) {
filetodelete.delete();
}
}
} catch (Exception e) {
e.printStackTrace();
}
来源:https://stackoverflow.com/questions/36242311/android-get-documentfile-with-write-access-for-any-file-path-on-sd-card-havin