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

Android 为什么从外部存储器读取文件不需要读取外部存储器权限请求?,android,android-permissions,android-external-storage,android-storage,Android,Android Permissions,Android External Storage,Android Storage,我正在模拟器上测试我的应用程序。我有一个导出功能,可以在外部存储器的下载目录中创建并写入文件。我还有一个导入功能,从外部存储器的下载目录中读取文件 发件人: 如果设备运行的是Android 5.1或更低版本,或者你的应用程序的目标SDK是22或更低版本:如果你在清单中列出了一个危险的权限,用户在安装应用程序时必须授予该权限;如果他们不授予该权限,则系统根本不会安装该应用程序 如果设备运行的是Android 6.0或更高版本,并且您的应用程序的目标SDK为23或更高版本:应用程序必须在清单中列出权

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

发件人:

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

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

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

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

以下是我的清单的代码片段:

<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" />
我从上面的代码段中读取文件的代码段(exportFile只是onActivityResult中的URI):


谢谢

你知道,Android运行时权限是分组的,因为你已经在清单中申请了写外部存储权限,所以没有必要申请读外部存储权限。它们都是同一组。

有一个很好的解释

读取外部存储

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


简而言之,读取外部存储只在果冻豆(16级)时存在。因此,除非您使用的是Jelly Bean手机并设置开发者选项“保护USB存储”,否则这不会是一个问题

你好,阿兰杰特,谢谢你的意见。我确实意识到,如果我请求写入外部存储,我不必在清单中声明读取外部存储,这就是我没有这样做的原因。我指的是“应用程序必须在清单中列出权限,并且它必须在应用程序运行时请求它所需的每个危险权限。”我没有提到这一点。你好,Prokash,谢谢你的输入。但是,即使我的导出功能在运行时请求访问权限,我也从未经历过该过程,因此在运行时不会请求任何权限。当我测试时,模拟器没有授予任何权限,我还显式删除了清单中的权限,并且当我尝试导入时,在没有清单中声明的权限和运行时请求的权限的情况下,它仍然可以工作。顺便说一句,按预期从清单中删除权限禁用了我的导出功能(写入外部存储器),而不是导入功能(从外部存储器读取)
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("text/*");
            startActivityForResult(intent, GET_FILE_RESULT_CODE);
    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) {...}