为什么不需要READ_EXTERNAL_STORAGE权限请求从外部存储读取文件?

时间:2017-05-09 02:53:27

标签: android android-permissions android-external-storage android-storage

我正在模拟器上测试我的应用。我有一个导出功能,我在其中创建并写入外部存储器下载目录中的文件。我还有一个导入功能,我从外部存储的下载目录中读取一个文件。

来自Android documentation

  

如果设备运行的是Android 5.1或更低版本,或者您的应用的目标SDK为22或更低:如果您在清单中列出了危险权限,则用户必须在安装应用时授予权限;如果他们没有授予权限,系统根本不会安装应用程序。

     

如果设备运行的是Android 6.0或更高版本,并且您的应用的目标SDK为23或更高:应用必须列出清单中的权限,并且必须在应用运行时请求其所需的每个危险权限。用户可以授予或拒绝每个权限,即使用户拒绝权限请求,应用也可以继续以有限的功能运行。

我的模拟器在Android 6.0上运行,我的应用程序的目标SDK是25,因此我还必须在应用程序运行时请求它所需的每个危险权限。我这样做是为了导出功能,一切正常。但是,当我实现导入功能时,我没有在运行时请求权限。奇怪的是,我仍然可以从外部存储器的权限中读取,而不需要在运行时请求和授予READ_EXTERNAL_STORAGE。根据此Android documentation,READ_EXTERNAL_STORAGE属于危险权限。

要验证,我确保在开始使用该功能之前禁用权限,并在完成后,我再次验证仍未授予权限。虽然我对这种行为感到满意,因为它在没有我在运行时请求许可的情况下工作,但根据文档我不相信这种行为是预期的。这就是为什么我想知道是什么导致了这个问题,并在我发布应用程序的任何更改之前找出问题。

这是我的清单的代码片段:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

我选择要读取的文件的代码片段:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("text/*");
            startActivityForResult(intent, GET_FILE_RESULT_CODE);

我读取上面代码片段中选择的文件的代码片段(exportFile只是来自onActivityResult的URI):

    BufferedReader br;
    try {
        br = new BufferedReader(new InputStreamReader(context.getContentResolver().openInputStream(exportFile)));
        String line;
        // Skip first header line
        br.readLine();
        while ((line = br.readLine()) != null) {...}

谢谢!

2 个答案:

答案 0 :(得分:2)

有一个很好的解释here

  

<强> READ_EXTERNAL_STORAGE

     

提供对外部存储的受保护读取访问。在Android 4.1中   默认情况下所有应用程序仍具有读访这将改变   在将来的版本中要求应用程序明确请求   使用此权限读取访问权限。如果你的申请已经   请求写访问权限,它也会自动获得读访问权限。   有一个新的开发人员选项可以打开读访问限制,   让开发人员根据Android的方式测试他们的应用程序   表现在将来。

简而言之, READ_EXTERNAL_STORAGE 仅存在于Jelly Bean(级别16)。因此,除非您使用Jelly Bean手机并设置开发人员选项&#34; 保护USB存储空间&#34;它不会成为一个问题。

答案 1 :(得分:0)

您知道,Android运行时权限已经分组,因为您已经在清单中申请了WRITE_EXTERNAL_STORAGE权限,因此无需申请READ_EXTERNAL_STORAGE权限。这两个权限都属于同一组。