Android Q (10) 请求访问所有存储的权限。范围存储
Posted
技术标签:
【中文标题】Android Q (10) 请求访问所有存储的权限。范围存储【英文标题】:Android Q (10) ask permission to get access all storage. Scoped storage 【发布时间】:2019-12-18 07:52:22 【问题描述】:在 android 10 中,需要访问存储的应用需要请求访问具体路径的权限。但是文件资源管理器等应用程序可以请求访问根存储的权限,并获得对所有存储的读/写权限。这就是我想要做的。
根据 Android,我们必须为此使用 ACTION_OPEN_DOCUMENT_TREE
。我遇到的问题是一切似乎都是正确的,但没有授予应用程序权限。
private void askAndroid10Perm()
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
在这里,用户可以看到 Android 文件树,并在选择主存储的情况下,单击以授予权限。 “它将允许 - 应用程序名称 - 完全访问当前存储在此位置下的所有文件,以及存储在此处的任何未来内容”-> 允许
然后:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode)
case REQUEST_CODE_OPEN_DOCUMENT_TREE:
if (resultCode == Activity.RESULT_OK)
Uri treeUri = data.getData();
int takeFlags = data.getFlags();
takeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
Log.i("TAG", "takePersistableUriPermission: " + treeUri);
this.getContentResolver().takePersistableUriPermission(treeUri, takeFlags);
日志:
采取PersistableUriPermission: content://com.android.externalstorage.documents/tree/primary%3A
那么应用程序仍然没有访问root的权限。
打开失败:EACCES(权限被拒绝)
我当然有:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
由用户授予。
【问题讨论】:
我不认为你可以在 Android Q 中拥有 root 访问权限 我测试过的一些应用程序通过范围存储具有此访问权限。例如“Solid explorer”应用。 是的,我知道。我曾问过类似的问题,CommonWare 对我说这是因为那些公司拥有的工程师。我知道,他的回答没那么有用。 root 访问是什么意思? 访问设备存储文件。显示默认文件资源管理器预装应用程序的相同文件。我不是在谈论系统根文件。已安装设备、外部 sd 卡和内部存储的根目录。 【参考方案1】:在清单中添加一行
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true" //Add this Line
android:label="@string/app_name">
---------<Activity, Sevices or Recivers>----------
</application>
【讨论】:
工作就像一个魅力! 这只是暂时的,见developer.android.com/training/data-storage/… 那只花了我 3 个小时的生命……谢谢 D_K 在 android 11 中它不再工作了。那么,我们如何才能访问 android 11 上的完整存储访问权限呢?有什么想法吗? 您必须使用适用于 Android 11 或更高版本的 MediaStore 请注意:developer.android.com/training/data-storage/use-cases【参考方案2】:您必须在 AndroidManifest.xml 中添加这一行
android:requestLegacyExternalStorage="true"
【讨论】:
【参考方案3】:问题是我使用 File 对象来访问文件,但只有当我们使用 DocumentFile 对象来操作文件时,权限才有效。
使用 DocumentFile 而不是 File 解决。
使用 DocumentFile 有多个缺点,例如性能,以及您无权访问 apache 公共库,但没有其他选择。
【讨论】:
File(path)、file.delete()、mkdirs() 不能在 android Q 上运行吗?范围存储有什么变化? 有一些用于 java 的库,例如,您可以在“文件”对象中复制、剪切或压缩目录。 DocumentFile 不存在此库。 文件 API 在 android 10 中不适用于共享存储中不属于您的应用的文件。 developer.android.com/training/data-storage/shared/…【参考方案4】:使用Simple Storage 可能会更简单。您可以向用户请求存储完全访问权限:
class MainActivity : AppCompatActivity()
private val storageHelper = SimpleStorageHelper(this)
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnRequestStorageAccess.setOnClickListener
storageHelper.requestStorageAccess()
storageHelper.onStorageAccessGranted = requestCode, root ->
// do stuff
它适用于 Android 10 及更高版本。无需在清单文件中添加android:requestLegacyExternalStorage="true"
。
【讨论】:
【参考方案5】:(不适用于 ANDROID 11)将此添加到应用程序的清单文件中,以便您的应用程序如下所示:
<application
android:requestLegacyExternalStorage="true"
对于 android 11 我确实喜欢这个
ContextWrapper cw = new ContextWrapper(mContext);
String fullPath =cw.getExternalFilesDir(Environment.DIRECTORY_MUSIC).toString();
File directory = cw.getExternalFilesDir(Environment.DIRECTORY_MUSIC);
在这里查看https://www.programmersought.com/article/50766505696/
【讨论】:
以上是关于Android Q (10) 请求访问所有存储的权限。范围存储的主要内容,如果未能解决你的问题,请参考以下文章