Android 内部存储/外部存储 及 读写权限

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 内部存储/外部存储 及 读写权限相关的知识,希望对你有一定的参考价值。

参考技术A

android 使用 VFS (Virtual File System) 虚拟文件系统。VFS提供了供存储设备挂载的节点,同一存储设备经过分区后,不同的分区可以挂载到不同的节点上,如手机的内置存储卡。

内置存储卡 / 外置SD卡
内部存储 / 外部存储

VFS 的目录以 / 为根节点,根节点下面又有不同的节点。物理存储设备就是挂载到这些节点上。

内部存储卡/外置SD卡 内部存储/外部存储

首先明确, 内置存储卡/外置SD卡 是在 物理层面 相对于 手机大众用户 来说的。
外置SD卡:可手动插拔的SD卡。
内置存储卡:焊接在手机内部不可拆卸的存储卡。

而, 内部存 /外部存储 是在 文件系统逻辑层面 相对于 开发者 来说的,指具体的路径。
一般针对某个应用而言的,属于该应用的存储路径叫内部存储,反之为外部存储。

路径: /data/data/package_name

/data/data/ 下都是已安装应用的目录,该目录下包含的文件都是以包名作为文件名的目录,例如 /data/data/com.sankuai.meituan

获取内部存储的方式如下:

其中,参数 mode 指创建模式,一种 4 种

注意: Android 7.0 以上 android.os.Build.VERSION.SDK_INT>=Build.VERSION_CODES.N 使用3/4 常量时,将会导致SecurityException,这意味着 不能通过名称共享私有文件
尝试共享 file://URI URI将会导致FileUriExposedException,StrictMode API政策禁止在您的应用外部公开file://URL。如果您的应用需要与其他应用共享私有文件,则可以使用 FileProvider 与 FLAG_GRANT_READ_URI_PERMISSION 配合使用。 Android 7.0 行为变更 通过FileProvider在应用间共享文件吧

外部存储,可以是 外置SD卡 或 内置存储卡的部分分区。

外部存储,分为 公共目录 和 私有目录

获取方式

检查可用性的方法:

Android 4.3 以下,只能通过 Context#getExternalFilesDir(type) 来获取外部存储在内置存储卡分区的私有目录,无法获取外置SD卡。

Android 4.3 开始,可以通过 Context#getExternalFilesDirs(type) 获取一个File数组,包含了内置存储卡分区和外置SD的私有目录地址。

可以使用兼容库的静态方法 ContextCompate.getExternalFilesDirs() 兼容 4.3。

感谢以下文章作者
解析Android内部存储、外部存储的区别

一些 Android 设备将内部存储视为 SD 卡,将外部存储视为 EXTSD

【中文标题】一些 Android 设备将内部存储视为 SD 卡,将外部存储视为 EXTSD【英文标题】:Some Android devices treat Internal Storage as SD Cards and External Storage as EXTSD 【发布时间】:2013-03-03 18:20:35 【问题描述】:

我有很多来自不同供应商的 Android 设备。

其中一些将 /mnt/sdcard 附加到内部存储,将 /mnt/extsd 附加到 外部存储(场景 1)和其他将 /mnt/sdcard 附加到外部存储(场景 2)

我认为第二种情况是标准的,因为 Android API 提供了此路径的句柄。现在的问题是,在场景 1 中,/mnt/extsd 变为 readonly,即使有 WRITE_EXTERNAL_STORAGE 权限!

这意味着我只能从实际的外部 sd 卡中读取数据而无法写入。

是否有解决方法,以便我可以写入 extsd 文件夹?

【问题讨论】:

最好向这个社区提问:android.stackexchange.com 【参考方案1】:
Environment.getExternalStorageState() returns path to internal SD mount point like "/mnt/sdcard"

Environment.getExternalStorageDirectory() 指的是设备制造商认为的“外部存储”。在某些设备上,这是可移动媒体,例如 SD 卡。在某些设备上,这是设备上闪存的一部分。在这里,“外部存储”是指“安装在主机上时通过 USB 大容量存储模式访问的东西”,至少对于 Android 2.x 及更高版本。

But the question is about external SD. How to get a path like "/mnt/sdcard/external_sd" (it may differ from device to device)?

如上所述,除了外部存储之外,Android 没有“外部 SD”的概念。

如果设备制造商选择将外部存储设备作为板载闪存并且还有 SD 卡,则您需要联系该制造商以确定您是否可以使用 SD 卡(不保证)以及使用它的规则,例如使用什么路径。

【讨论】:

【参考方案2】:

到目前为止,我发现在设备上获得写访问权的唯一解决方法是使设备生根:(

三星提供了一个清单条目的解决方法

更多详情请点击以下链接

http://www.xda-developers.com/android/android-3-2-code-inadvertently-preventing-write-access-to-external-storage/

http://www.chainfire.eu/articles/113/Is_Google_blocking_apps_writing_to_SD_cards_/

摘录:

Google 的 AOSP 代码中似乎存在一个错误,即 围绕 Android 3.2 引入,这会影响操作系统处理 USB 的方式 存储并可以防止对 SD 卡和 USB 记忆棒的写访问。 XDA 精英认可的开发者、高级版主和新闻撰稿人 Chainfire 在他的博文中总结了这个问题:

“过去,应用会请求“WRITE_EXTERNAL_STORAGE” 权限,这将授予对所有外部存储的写访问权限 (用户/组“sdcard_rw”)。这显然已更改为仅 授予对主要外部存储的写访问权限。一秒 引入了名为“WRITE_MEDIA_STORAGE”的权限,其中 将授予对其他外部存储的访问权限(用户/组 “media_rw”)。

问题是,第三方实际上不会被授予此权限 权限,仅限系统应用和设备提供的应用 制造商通常会获得此许可。有 例外,显然在某些设备上第三方应用程序将 授予此权限,但根据 AOSP 消息来源,他们是 当然不应该。”

【讨论】:

在有根设备上,你将如何解决这个问题?例如Cubieboard默认root,内部SD很小但应用程序默认无法写入外部SD【参考方案3】:

在根设备上,您可以更改 /system/etc/permissions/platform.xml 以“修复”权限问题。以下对我有用:

adb pull /system/etc/permissions/platform.xml

修改 platform.xml,使 media_rw 包含在 WRITE_EXTERNAL_STORAGE 权限中,如下所示:

<permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
   <group gid="sdcard_rw" />
   <group gid="media_rw" />
</permission>

adb push platform.xml /system/etc/permissions/platform.xml

重启设备

【讨论】:

谢谢,这是为我做的。我不明白为什么 Google 会强制执行这样的权限限制。 这是一个用户解决方案,而不是开发者解决方案。

以上是关于Android 内部存储/外部存储 及 读写权限的主要内容,如果未能解决你的问题,请参考以下文章

android系统怎么设置内部存储的访问权限

android内部存储与外部存储

Android存储及getCacheDir()getFilesDir()getExternalFilesDir()getExternalCacheDir()区别

Android——Android10的分区存储(Scoped Storage)

Android 中内部存储和外部存储的理解与应用

获取内部和外部存储信息-android