在某些时候为Android开发时,我有一个指向用户先前选择的通知声音文件的Uri。此文件可能位于内部或外部存储上。是否存在通用方法(适用于所有API级别)以检查此Uri是指向外部存储还是内部存储?
为什么我需要这个?好吧,谷歌在API23中引入新的权限政策后,我遇到了以下问题。如果Uri指向内部存储,我的应用程序不必获得访问该Uri的READ_EXTERNAL_STORAGE权限。但是,如果Uri指向位于外部存储器上的某个声音文件,则应用程序必须具有READ_EXTERNAL_STORAGE权限才能访问该文件。
所以我想根据Uri的来源显示不同的对话框。
答案 0 :(得分:1)
他们把它放在developer.android.com的方式:
内部存储
将私有数据存储在设备内存中。外部存储
将公共数据存储在共享外部存储上。
所以内部意味着“由您的应用拥有,因此对其他第三方应用无法读取”(与系统应用相比)并且始终位于设备内存中,而外部存储表示“所有人都可读”并存储在任何地方。
如果你的应用以某种方式(安装或下载)导致铃声保存在内部存储上,则不需要任何权限。
另一方面,如果铃声在共享公共内存中,则需要READ_EXTERNAL_STORAGE才能访问它。
当要求用户授予权限时,它取决于目标SDK以及当前API级别:
SecurityException
修改强> 为了使事情变得更复杂,有一种“内部”外部存储。该文档称之为“app-private”数据。 如果查询来自第三方应用程序,则不会被MediaStore内容提供商访问,但对于拥有READ_EXTERNAL_STORAGE权限的所有应用程序,它都是可读的。
您的应用程序将始终能够访问此类型的存储,例如使用ContextCompat.getExternalFilesDirs(),它将返回内置设备内存和SD卡(如果存在)的路径。
但不应指望Uri像绝对路径(例如参见Commonsware blog)
相反,对于MediaStore.Audio.Media.EXTERNAL_CONTENT_URI MediaStore.Audio.Media.INTERNAL_CONTENT_URI,建议您使用ContentResolver query。
如果您从查询内部内容开始,则不需要权限。如果找不到该文件,则可能已将其删除,或者SD卡可能已被删除。或者它存储在“公共”外部存储器中,如果您没有权限,则根本不会获得任何信息......
因此,您可以检查权限状态(SecurityException
,如果您的目标是API级别23或更高,ContextCompat.checkSelfPermission()
定位较低的API级别),如果您有权限,请查询PermissionChecker.checkSelfPermission()
并根据结果显示一个对话框。