Android应用如何实现支持用户选择OneDrive或Google Drive的文件夹URI?
嗨,我来帮你解决这个问题!我之前也遇到过一模一样的情况——用ACTION_OPEN_DOCUMENT_TREE调用文件夹选择器时,OneDrive、Google Drive这些云存储的文件夹死活不显示,后来调整了几个配置就搞定了,给你分享下具体步骤:
给Intent加上必要的权限标志
云存储的文件夹URI需要持久化的访问权限,所以创建Intent时一定要加上这几个关键标志,不然云存储提供商不会把它们的文件夹展示给你的应用:
如果你用的是Kotlin:val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) // 要是你需要写入权限的话就加这个Java版本的代码是这样:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // 需要写入权限时添加用Intent.createChooser包装你的选择器
有时候默认启动Intent的方式会过滤掉部分文档提供器,用createChooser就能强制显示所有支持SAF(存储访问框架)的应用,包括各种云存储APP:
Kotlin:val chooserIntent = Intent.createChooser(intent, "请选择目标文件夹") startActivityForResult(chooserIntent, REQUEST_CODE_FOLDER) // REQUEST_CODE_FOLDER是你定义的请求码,比如1001Java:
Intent chooserIntent = Intent.createChooser(intent, "请选择目标文件夹"); startActivityForResult(chooserIntent, REQUEST_CODE_FOLDER);检查权限声明是否到位
虽然Android 10(API 29)及以上用Scoped Storage,大部分场景不需要READ_EXTERNAL_STORAGE权限,但如果你的应用要兼容旧版本系统,或者需要访问云存储里的文件内容,还是要在AndroidManifest.xml里声明这个权限:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />加上
maxSdkVersion是为了避免在高版本系统里触发不必要的权限请求弹窗。持久化返回的URI权限
当用户选好云文件夹后,别忘了把权限持久化,这样后续访问这个URI时就不用再让用户重复授权了:
Kotlin:override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_FOLDER && resultCode == Activity.RESULT_OK) { data?.data?.let { treeUri -> contentResolver.takePersistableUriPermission( treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) // 接下来就可以用这个treeUri来操作文件夹里的内容啦 } } }Java:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_FOLDER && resultCode == RESULT_OK) { if (data != null && data.getData() != null) { Uri treeUri = data.getData(); getContentResolver().takePersistableUriPermission( treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION ); // 后续用treeUri访问文件夹内容即可 } } }
最后还要提醒一句:如果用户还没登录对应的云存储APP(比如OneDrive没登录账号),选择器里可能还是看不到对应的选项,这时候可以在应用里加个提示,让用户先登录相关云应用哦。
内容来源于stack exchange

