Reputation: 209
I have granted permission to write external and removable storages. But I still can't write everywhere on the sd card on Android 7.
Intent intent = storageVolume.createAccessIntent(null);
startActivityForResult(intent, 989);
;
RxPermissions.getInstance(getActivity())
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.subscribe(granted -> {
if (!granted) return;
showAlternativeDirectoryChooser();//success
}, throwable -> {
});
Here is the code of folder creation:
DocumentFile documentFile = DocumentFile.fromFile(dir);
DocumentFile test = documentFile.createDirectory("test_folder");
test == null
Upvotes: 3
Views: 2136
Reputation: 593
You cannot use :
DocumentFile documentFile = DocumentFile.fromFile(dir);
Becouse its not a SAF valid Uri.
If you dont want to use ACTION_OPEN_DOCUMENT_TREE or ACTION_OPEN_DOCUMENT to get an Uri, you can convert FILE to Uri (SAF) using the following method valid from API19(Android4.4-Kitkat) to API28(Android8-Oreo). The returned Uri's are the same that return the dialog and its valid for API 28 security restrictions (SAF permissions), if you want to access external removable storage outside your application...
/**
* Ing.N.Nyerges 2019 V2.0
*
* Storage Access Framework(SAF) Uri's creator from File (java.IO),
* for removable external storages
*
* @param context Application Context
* @param file File path + file name
* @return Uri[]:
* uri[0] = SAF TREE Uri
* uri[1] = SAF DOCUMENT Uri
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static Uri[] getSafUris (Context context, File file) {
Uri[] uri = new Uri[2];
String scheme = "content";
String authority = "com.android.externalstorage.documents";
// Separate each element of the File path
// File format: "/storage/XXXX-XXXX/sub-folder1/sub-folder2..../filename"
// (XXXX-XXXX is external removable number
String[] ele = file.getPath().split(File.separator);
// ele[0] = not used (empty)
// ele[1] = not used (storage name)
// ele[2] = storage number
// ele[3 to (n-1)] = folders
// ele[n] = file name
// Construct folders strings using SAF format
StringBuilder folders = new StringBuilder();
if (ele.length > 4) {
folders.append(ele[3]);
for (int i = 4; i < ele.length - 1; ++i) folders.append("%2F").append(ele[i]);
}
String common = ele[2] + "%3A" + folders.toString();
// Construct TREE Uri
Uri.Builder builder = new Uri.Builder();
builder.scheme(scheme);
builder.authority(authority);
builder.encodedPath("/tree/" + common);
uri[0] = builder.build();
// Construct DOCUMENT Uri
builder = new Uri.Builder();
builder.scheme(scheme);
builder.authority(authority);
if (ele.length > 4) common = common + "%2F";
builder.encodedPath("/document/" + common + file.getName());
uri[1] = builder.build();
return uri;
}
Then you can call the permissions using something like this:
context.grantUriPermission(context.getPackageName(), uri, Intent
.FLAG_GRANT_READ_URI_PERMISSION | Intent
.FLAG_GRANT_WRITE_URI_PERMISSION);
context.getContentResolver().takePersistableUriPermission(uri, Intent
.FLAG_GRANT_READ_URI_PERMISSION | Intent
.FLAG_GRANT_WRITE_URI_PERMISSION);
Upvotes: 1
Reputation: 9645
Android delivers the Uri you need to use in onActivityResult
. That Uri is not necessarily related, at all, to the path you're trying to access. You cannot guess it. You have to actually use the Uri you're given.
If you call DocumentFile.fromFile
or Uri.parse
, then you are wrong.
Upvotes: 0