In my application, I get permission to write to sd-card using the following intent. If the user selects the sd card folder from the system file explorer, then I have write access to the SD card.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); intent.putExtra("android.content.extra.SHOW_ADVANCED", true); startActivityForResult(intent, 42);
After that, I can modify the files on the SD card using the DocumentFile class. But I had a 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 if I already have sd card permission.
So, I wrote a method published at the end of my question to get a DocumentFile that returns true on .canWrite (). But itβs slow ... And also very bad! There must 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. This is just weird. Can anyone 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; }