DocumentFile.fromFile 5.0+
DocumentFile.fromFile on 5.0+
在我的测试中,我发现使用 fromFile
创建的任何 DocumentFile
在 5.0+ 上的任何写入(createFile
、createDirectory
等)都会失败,即使您从 SAF 获得 root 权限。
这是预期的行为吗?
如果 fromFile
仅用于 <5.0 兼容性,我真的希望他们在文档中已经明确了这一点。
因此 fromFile
生成了一个 RawDocumentFile
,它似乎只是简单地包装了一个文件。我不明白这将如何提供 File
本身不具备的任何额外写入权限,无论 SAF 许可如何,所以我要说 fromFile
应该仅作为向后兼容性(<4.4) 工厂。我已经提交了一个增强请求来更新文档来解释这一点。
如果你不想使用ACTION_OPEN_DOCUMENT_TREE或ACTION_OPEN_DOCUMENT来获取Uri,你可以使用以下方法将FILE转换为Uri(SAF)从 API19(Android4.4-Kitkat) 到 API28(Android8-Oreo) 有效:
/**
* 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;
}
在我的测试中,我发现使用 fromFile
创建的任何 DocumentFile
在 5.0+ 上的任何写入(createFile
、createDirectory
等)都会失败,即使您从 SAF 获得 root 权限。
这是预期的行为吗?
如果 fromFile
仅用于 <5.0 兼容性,我真的希望他们在文档中已经明确了这一点。
因此 fromFile
生成了一个 RawDocumentFile
,它似乎只是简单地包装了一个文件。我不明白这将如何提供 File
本身不具备的任何额外写入权限,无论 SAF 许可如何,所以我要说 fromFile
应该仅作为向后兼容性(<4.4) 工厂。我已经提交了一个增强请求来更新文档来解释这一点。
如果你不想使用ACTION_OPEN_DOCUMENT_TREE或ACTION_OPEN_DOCUMENT来获取Uri,你可以使用以下方法将FILE转换为Uri(SAF)从 API19(Android4.4-Kitkat) 到 API28(Android8-Oreo) 有效:
/**
* 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;
}