如何检查Uri是指外部还是内部存储?

时间:2016-06-29 04:24:15

标签: android uri

在某些时候为Android开发时,我有一个指向用户先前选择的通知声音文件的Uri。此文件可能位于内部或外部存储上。是否存在通用方法(适用于所有API级别)以检查此Uri是指向外部存储还是内部存储?

为什么我需要这个?好吧,谷歌在API23中引入新的权限政策后,我遇到了以下问题。如果Uri指向内部存储,我的应用程序不必获得访问该Uri的READ_EXTERNAL_STORAGE权限。但是,如果Uri指向位于外部存储器上的某个声音文件,则应用程序必须具有READ_EXTERNAL_STORAGE权限才能访问该文件。

所以我想根据Uri的来源显示不同的对话框。

1 个答案:

答案 0 :(得分:1)

他们把它放在developer.android.com的方式:

  

  • 内部存储
          将私有数据存储在设备内存中。
  •   
  • 外部存储
          将公共数据存储在共享外部存储上。
  • 所以内部意味着“由您的应用拥有,因此对其他第三方应用无法读取”(与系统应用相比)并且始终位于设备内存中,而外部存储表示“所有人都可读”并存储在任何地方。

    如果你的应用以某种方式(安装或下载)导致铃声保存在内部存储上,则不需要任何权限。

    另一方面,如果铃声在共享公共内存中,则需要READ_EXTERNAL_STORAGE才能访问它。

    当要求用户授予权限时,它取决于目标SDK以及当前API级别:

  • 运行 5.1或更早版本的设备:
    必须在安装时授予权限,且无法撤销
  • 运行 6.0+(= API级别23)且目标API级别22或更低级别的设备:
    必须在安装时授予权限,以后可以撤消权限,不{{1如果app尝试继续而不询问,但当然某些部分可能会失败(Content Provider查询可能会返回null等)。
  • 运行 6.0+(= API级别23)且目标API级别23或更高级别的设备:
    权限不必在安装时授予,可以在以后撤销,应用必须要求获得权限,并且如果它尽管缺少权限而尝试继续,则会遇到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()并根据结果显示一个对话框。