存储访问框架:撤销树权限后保留文件权限
Storage Access Framework: keep file permissions after revoke tree permissions
在应用程序中,用户使用 ACTION_OPEN_DOCUMENT_TREE
意图通过 SAF 选择目录,用户可以在其中创建各种文件。
问题是当用户更改工作目录(始终使用 SAF)时,对这些文件的访问权限将丢失。如何保持 ACTION_CREATE_DOCUMENT
或 ACTION_OPEN_DOCUMENT
之类的访问权限?
这是我的代码
- 选择目录
private void showDirectoryPicker() {
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
i.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(i, 12345);
}
- 处理结果
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) return;
mDir = data.getData();
grantUriPermission(getPackageName(), mDir, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(mDir, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
- 创建文件
mFile = DocumentFile.fromTreeUri(getContext(), mDir).createFile("text/plain", "some file.txt").getUri();
- 现在如果用户更改工作目录,我会释放旧目录的权限,所以:
getContentResolver().releasePersistableUriPermission(mDir, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
revokeUriPermission(mDir, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
mDir = null;
// ask for another dir
showDirectoryPicker();
一旦我重新启动应用程序并尝试打开在旧目录中创建的文件,我得到:
java.lang.SecurityException: No persistable permission grants found for UID <<<uid>>> and Uri 0 @ <<<file uri>>>
示例:
DocumentFile file = DocumentFile.fromSingleUri(getContext(), mFile);
if (file.getName() == null) {
// permissions lost
} else {
// do something
}
如何处理?或者只保留目录权限直到应用程序被卸载???
简单的解决方案是在您完成该树中的所有内容之前不释放权限授予。用户更改他们将用于 future 操作的树不会改变您使用他们想要用于 past 操作的树的需要,至少对于那些您仍然持有 Uri
值的内容。
您可以尝试向旧树中的各个内容请求单独的 Uri
授权,然后释放对旧树的权限授予。我从来没有尝试过这个,所以我不知道它是否会起作用。这是我能想到的最优雅的许可解决方案,因为您没有比实际需要更多的权利。
在应用程序中,用户使用 ACTION_OPEN_DOCUMENT_TREE
意图通过 SAF 选择目录,用户可以在其中创建各种文件。
问题是当用户更改工作目录(始终使用 SAF)时,对这些文件的访问权限将丢失。如何保持 ACTION_CREATE_DOCUMENT
或 ACTION_OPEN_DOCUMENT
之类的访问权限?
这是我的代码
- 选择目录
private void showDirectoryPicker() {
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
i.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(i, 12345);
}
- 处理结果
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) return;
mDir = data.getData();
grantUriPermission(getPackageName(), mDir, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(mDir, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
- 创建文件
mFile = DocumentFile.fromTreeUri(getContext(), mDir).createFile("text/plain", "some file.txt").getUri();
- 现在如果用户更改工作目录,我会释放旧目录的权限,所以:
getContentResolver().releasePersistableUriPermission(mDir, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
revokeUriPermission(mDir, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
mDir = null;
// ask for another dir
showDirectoryPicker();
一旦我重新启动应用程序并尝试打开在旧目录中创建的文件,我得到:
java.lang.SecurityException: No persistable permission grants found for UID <<<uid>>> and Uri 0 @ <<<file uri>>>
示例:
DocumentFile file = DocumentFile.fromSingleUri(getContext(), mFile);
if (file.getName() == null) {
// permissions lost
} else {
// do something
}
如何处理?或者只保留目录权限直到应用程序被卸载???
简单的解决方案是在您完成该树中的所有内容之前不释放权限授予。用户更改他们将用于 future 操作的树不会改变您使用他们想要用于 past 操作的树的需要,至少对于那些您仍然持有 Uri
值的内容。
您可以尝试向旧树中的各个内容请求单独的 Uri
授权,然后释放对旧树的权限授予。我从来没有尝试过这个,所以我不知道它是否会起作用。这是我能想到的最优雅的许可解决方案,因为您没有比实际需要更多的权利。