很多好问题,让我们深入探讨。:)
你如何使用它?
以下是与 KitKat 中的存储访问框架交互的精彩教程:
https://developer.android.com/guide/topics/providers/document-provider.html#client
与 Lollipop 中的新 API 交互非常相似。要提示用户选择目录树,您可以启动如下意图:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, 42);
然后在 onActivityResult() 中,您可以将用户选择的 Uri 传递给新的 DocumentFile 帮助器类。这是一个简单的示例,列出了所选目录中的文件,然后创建一个新文件:
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (resultCode == RESULT_OK) {
Uri treeUri = resultData.getData();
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
// List all existing files inside picked directory
for (DocumentFile file : pickedDir.listFiles()) {
Log.d(TAG, "Found file " + file.getName() + " with size " + file.length());
}
// Create a new file and write into it
DocumentFile newFile = pickedDir.createFile("text/plain", "My Novel");
OutputStream out = getContentResolver().openOutputStream(newFile.getUri());
out.write("A long time ago...".getBytes());
out.close();
}
}
返回的 Uri 为DocumentFile.getUri()
足够灵活,可以与不同平台的 API 一起使用。例如,您可以使用以下方式共享它Intent.setData()
with Intent.FLAG_GRANT_READ_URI_PERMISSION
.
如果你想从本机代码访问该 Uri,你可以调用ContentResolver.openFileDescriptor()
然后使用ParcelFileDescriptor.getFd()
or detachFd()
获取传统 POSIX 文件描述符整数。
如何检查是否可以访问文件/文件夹?
默认情况下,通过存储访问框架意图返回的 Uris 是not重新启动后仍然存在。平台“提供”了持久化权限的能力,但如果你想要的话,你仍然需要“获取”权限。在上面的示例中,您可以调用:
getContentResolver().takePersistableUriPermission(treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
您始终可以通过以下方式找出您的应用程序可以访问的持久授权:ContentResolver.getPersistedUriPermissions()
API。如果您不再需要访问持久化的 Uri,可以使用以下命令释放它:ContentResolver.releasePersistableUriPermission()
.
KitKat 上有这个吗?
不可以,我们无法向旧版本的平台追溯添加新功能。
我可以查看哪些应用程序可以访问文件/文件夹吗?
目前没有 UI 显示这一点,但您可以在“授予的 Uri 权限”部分找到详细信息adb shell dumpsys activity providers
output.
如果在同一设备上为多个用户安装一个应用程序,会发生什么情况?
就像所有其他多用户平台功能一样,Uri 权限授予是按每个用户隔离的。也就是说,在两个不同用户下运行的同一应用程序没有重叠或共享的 Uri 权限授予。
权限可以撤销吗?
支持的 DocumentProvider 可以随时撤销权限,例如删除基于云的文档时。发现这些被撤销的权限的最常见方法是当它们从ContentResolver.getPersistedUriPermissions()
上文提到的。
每当清除参与授予的任一应用程序的应用程序数据时,权限也会被撤销。
是否会在选定的文件夹上递归地请求权限?
是的,ACTION_OPEN_DOCUMENT_TREE
意图使您可以递归访问现有的和新创建的文件和目录。
这是否允许多项选择?
是的,从 KitKat 开始就支持多重选择,你可以通过设置来允许它EXTRA_ALLOW_MULTIPLE
当开始你的ACTION_OPEN_DOCUMENT
意图。您可以使用Intent.setType()
or EXTRA_MIME_TYPES
缩小可以选择的文件类型:
http://developer.android.com/reference/android/content/Intent.html#ACTION_OPEN_DOCUMENT
有没有办法在模拟器上尝试新的 API?
是的,主共享存储设备应该出现在选择器中,甚至出现在模拟器上。如果您的应用程序仅使用存储访问框架来访问共享存储,则您不再需要READ/WRITE_EXTERNAL_STORAGE
权限at all并可以删除它们或使用android:maxSdkVersion
功能仅在较旧的平台版本上请求它们。
当用户更换 SD 卡时会发生什么情况?
当涉及物理介质时,底层介质的UUID(例如FAT序列号)总是被烧录到返回的Uri中。系统使用它来将您连接到用户最初选择的媒体,即使用户在多个插槽之间交换媒体也是如此。
如果用户换入第二张卡,您需要提示才能访问新卡。由于系统会记住每个 UUID 的授权,因此如果用户稍后重新插入原始卡,您将继续拥有先前授予的对原始卡的访问权限。
http://en.wikipedia.org/wiki/Volume_serial_number