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

4
我正在模拟器上测试我的应用程序。我有一个导出功能,其中我创建并写入外部存储下载目录中的文件。我还有一个导入功能,其中我从外部存储下载目录读取文件。
来自Android文档
如果设备运行Android 5.1或更低版本,或者您的应用程序的目标SDK为22或更低版本:如果在清单中列出了危险权限,则用户必须在安装应用程序时授予权限;如果他们不授予权限,则系统根本不会安装该应用程序。
如果设备运行Android 6.0或更高版本,并且您的应用程序的目标SDK为23或更高版本:应用程序必须在清单中列出权限,并且在应用程序运行时必须请求每个需要的危险权限。用户可以授予或拒绝每个权限请求,即使用户拒绝权限请求,应用程序也可以继续以有限的功能运行。
我的模拟器运行在Android 6.0上,我的应用程序的目标SDK是25,因此在应用程序运行时,我必须请求每个需要的危险权限。对于导出功能,我已经这样做了,一切正常工作。然而,在实现导入功能时,我没有在运行时请求权限。奇怪的是,我仍然能够读取外部存储的权限,而不需要在运行时请求和授予READ_EXTERNAL_STORAGE权限。根据 Android文档,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个回答

3

这里有一个很好的解释(链接)

READ_EXTERNAL_STORAGE

提供对外部存储的受保护读取访问权限。在Android 4.1中,默认情况下所有应用程序仍具有读取访问权限。在将来的版本中,这将会更改,要求应用程序明确请求使用此权限进行读取访问。如果您的应用程序已经请求了写入访问权限,则它也会自动获得读取访问权限。有一个新的开发者选项可以打开读取访问限制,供开发者测试其应用程序针对Android未来行为的反应。

简而言之,READ_EXTERNAL_STORAGE仅存在于Jelly Bean(Level 16)及其以上版本。因此,除非您使用的是Jelly Bean手机并设置了开发者选项“保护USB存储”,否则不会有问题。


你好Prokash,感谢你的意见。但是,尽管我的导出功能在运行时请求访问权限,但我从未经历过这个过程,因此在运行时不会请求任何权限。在我的测试中,模拟器没有授予任何权限,我还明确在清单中删除了权限,并且当我尝试导入时,仍可以正常工作,而无需在清单中声明权限和在运行时请求权限。 - Charles Li
顺便提一下,从清单中删除权限确实禁用了我的导出功能(写入外部存储),但并没有禁用导入功能(读取外部存储)。 - Charles Li

0
你知道吗?Android Runtime Permissions是分组的。因为你在清单文件中已经申请了WRITE_EXTERNAL_STORAGE权限,所以无需再申请READ_EXTERNAL_STORAGE权限。它们都属于同一组。

1
嗨alanjet,感谢你的建议。我确实意识到如果我请求WRITE_EXTERNAL_STORAGE权限,就不需要在清单文件中声明READ_EXTERNAL_STORAGE权限,这就是为什么我没有声明它的原因。我指的是“应用程序必须在清单文件中列出权限,并且在应用程序运行时必须请求每个危险权限。”对于导入操作,我没有这样做。 - Charles Li

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接