Android - get a DocumentFile with write access for any path to the file on the SD card (with already obtained sd card permission)

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; } 
+5
source share
1 answer

to reply to @AndiMar (March 21), I just check if it exists on the internal storage if there is 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(); } 
0
source

Source: https://habr.com/ru/post/1245837/


All Articles