1、背景

在开发过程中我们都会使用到手机的内部缓存、外部缓存。但有些开发者对这两个存储区域理解还够透彻,以为手机内置的存储卡(不可手机移除)就是内部存储,
可插拔的SD卡就是外部存储,其实这些理解都是有误的。这个知识点本人也重复看过好几次,但每次看完,过一段时间就会忘记,于是打算对这一知识点做个总结,也可当成学习笔记分享给大家。
主要分为下面两点进行分析:

  • Android设备文件系统的目录结构
  • 内部存储和外部存储的区别

2、 Android文件系统目录结构

很多同学都使用Window系统,对Window文件系统的目录结构也比较熟悉。Window使用的文件系统是NTFS,NTFS文件系统可把一个物理机械硬盘划分为四个逻辑分区,每个分区对应一个盘符,如:C盘、D盘、E盘、F盘。
分区的目的是为了便于管理文件。每个盘符在用户看来是相互独立的四块磁盘,每个盘符都是一个根节点,如下图所示:

Android系统的内核使用的是Linux内核, 所以Android的文件目录结构和Linux系统的文件目录结构类似,Linux系统和Window系统属于不同的操作系统,所以它们所使用的文件系统也是不一样的,
那对磁盘的管理方式也是不一样的,这就造成了Android设备的文件目录结构和Window系统设备的文件目录结构不一样的原因。
现在我们就来大致了解一下Android文件系统的目录结构,以及几个重要的文件目录。
Android系统使用虚拟文件系统(VFS), VFS的目录是以/为根节点,根节点下又有不同的节点。而我们的物理存储设备就是挂载都这些节点上,如下图所示:

  1. /data/data/ apk的安装目录。 如:百度地图的安装路径是/data/data/com.baidu.com/ 注意:该目录需要获取root权限才能查看
  2. /system/ 存放系统应用的apk文件,即手机厂商预安装应用的apk文件 (手机厂商只需把需要预安装的apk放在该节点的相应路径下,android系统就会自己解压并安装该apk)
  3. /storage/ 该节点是内置存储卡和外置SD卡的挂载点,/storage/emulated/0/是内置存储卡挂载点, /storage/sdcard1是外置SD卡挂载点(不同的设备挂载节点不一样,有些设备可能会挂载到/mnt/节点)。

3、内部存储和外部存储的区别

一般来说,现在的国产手机都会有两个存储装置,一个就是内置的手机设备中不可手动拆卸的存储卡,我们称之为内置存储卡,另一个是可手动插拔外置存储卡,我们称之为外置SD卡。
对于Android开发者来说只和外部存储和内部存储打交道,Android提供的开发接口也只是获取内部存储和外部存储的目录地址。而对开发者屏蔽了内置存储卡和外置SD卡。
所以很多同学都的理解就是:内置存储卡是内部存储, 外置SD卡 是外部存储。 这样的理解是不正确的。

以下是我个人的理解:
内置存储卡 和外置SD卡 是不同物理存储装置上的划分,一个是内置到设备上,一个是在插在SD卡卡槽上。
而内部存储 和外部存储 以是否是应用的安装目录来划分,内部存储 是在应用的安装目录下,外部存储 在应用的安装目录外。
一个划分是物理上的划分,一个是逻辑上的划分,所以内置存储卡 不是内部存储 ,外置SD卡 也不是外部存储 。

  • 内部存储:
    /data/data/目录下都是已安装的应用程序的安装目录, 该目录下包含的文件都是以包名作为文件名的目录,如我测试demo的安装目录为:/data/data/com.bgl.storage/。
    内部存储的文件是应用的私有文件,其他应用(和用户)不能访问这些文件。每个应用访问自己的内部存储是不需要权限的。 当用户卸载应用时,这些文件也会被移除。
    context.getDir(String name, String mode)可创建并返回一个内部存储的文件,mode用于指示文件的创建模式,指定为MODE_PRIVATE 将会把文件设为应用的私有文件。
    其他可用模式包括:MODE_APPEND、MODE_WORLD_READABLE和 MODE_WORLD_WRITEABLE。

注:自 API 级别 17 以来,常量 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 已被弃用。从 Android N 开始,
使用这些常量将会导致引发 SecurityException。这意味着,面向 Android N 和更高版本的应用无法按名称共享私有文件,
尝试共享“file://”URI 将会导致引发FileUriExposedException。 如果您的应用需要与其他应用共享私有文件,则可以将 FileProvider 与 FLAG_GRANT_READ_URI_PERMISSION 配合使用。

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

  • 外部存储:

外部存储可以是外置SD卡 ,也可以是内置存储卡 的部分分区。 外部存储可分为公共目录和私有目录
在Android4.4以前读取或写入外部存储(包括公共目录和私有目录)的文件,必须获取 READ_EXTERNAL_STORAGE 或 WRITE_EXTERNAL_STORAGE 系统权限。 如下:

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

但从Android 4.4 开始,操作私有目录不再需要 READ_EXTERNAL_STORAGE 或 WRITE_EXTERNAL_STORAGE 权限。
因此如果我们的应用只使用到外部存储中的私有目录的话,可通过添加 maxSdkVersion 属性来声明,只需在较低版本的 Android 中请求该权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"   android:maxSdkVersion="18" />

注意:如果操作外部存储的公共目录,我们还是需要申请 READ_EXTERNAL_STORAGE 或 WRITE_EXTERNAL_STORAGE 权限。

私有目录属于应用私有,但这些私有数据是可以被其它应用访问和修改的(前提是知道应用私有目录的地址)。
当用户卸载应用时,此目录及其内容将被删除。此外,系统媒体扫描程序不会读取这些目录中的文件,因此不能从 MediaStore 内容提供程序访问这些文件。
因此,如果你正在处理的文件不适合其他应用使用(例如仅供您的应用使用的图形纹理或音效),则应该存储在外部存储上的私有存储目录。
私有目录 的获取方式如下:

注意:如果用户在计算机上装载了外部存储或移除了介质,则外部存储可能变为不可用状态。所有应用都能读取和写入放置在外部存储上的文件,并且用户可以移除这些文件。

在使用外部存储执行任何工作之前,应始终调用 getExternalStorageState() 以检查介质是否可用。介质可能已装载到计算机,处于缺失、只读或其他某种状态。
例如,以下是可用于检查可用性的几种方法:

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {String state = Environment.getExternalStorageState();if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;}
    return false;
}/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {String state = Environment.getExternalStorageState();if (Environment.MEDIA_MOUNTED.equals(state) ||Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        return true;}
    return false;
}

有些设备支持外插SD卡,所以这类设备的外部存储由内置存储卡分区和外置SD卡组成:
在Android4.3及以下的系统,只能通过Context.getExternalFilesDir(type)来获取外部存储在内置存储卡分区上的私有目录地址,而无法获取到外部存储在外置SD卡上的地址。
从Android4.4开始,你可以通过Context.getExternalFilesDirs(type)获取一个File数组,File数组中就包含了内置存储卡分区和外置SD卡的私有目录地址。
如果您希望在支持 Android 4.3 和更低版本的同时访问两个可能的位置,请使用兼容库中的静态方法 ContextCompat.getExternalFilesDirs()。

4、总结

  • Android系统使用的是虚拟文件系统(VFS),VFS提供了供存储设备挂载的节点。同一个存储设备经过分区后,不同的分区可以挂载到不同的节点上,如手机的内置存储卡。
  • 使用内部存储是不需要权限的,内部存储属于应用的私有存储区域,其它应用不可访问,当应用被卸载时,内部存储中的文件也会被删除。
  • 外部存储分为公共目录和私有目录,外部存储是可以全局访问的,但需要申请权限:
    1. Android4.4以前访问私有目录和公共目录都需要申请 WRITE_EXTERNAL_STORAGE 权限
    2. Android4.4以后访问私有目录不需要申请权限,但公共目录是需要申请 WRITE_EXTERNAL_STORAGE 权限
  • 自 API 级别 17 以来,常量 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 已被弃用。从 Android N 开始,使用这些常量将会导致引发 SecurityException。
  • 如果缓存的数据量比较大,请不要保存到内存存储中,如果想保存可共享给其它应用的数据,请保存到外部存储的公共目录中。
  • 设置项的Clear Data 和Clear cache两个选项,这两个都是情况应用的缓存数据,具体区别如下:
    1. Clear Data清理的是外部存储中的应用私有目录下的file文件夹
    2. Clear Cache清理的是外部存储中的应用私有目录下的cache文件夹

解析Android内部存储、外部存储的区别相关推荐

  1. android 源码分析 内置 sd storage,Android开罐头———外部存储与内部存储完全解析...

    context.getExternalFilesDir(),Environment.getExternalStorageDirectory(),傻傻分不清?到底什么算安卓手机的external sto ...

  2. HDU-安卓程序开发之简单存储/内部存储/外部存储 捉虫

    前言 大三上学期可以说是各工科学生课最难最多的一学期了,又因下学期大家普遍需要找工作,所以都压力比较大吧- 安卓作为我本学期选的五门专业课中学的最认真的(因为每周都有布置作业),所以我对它相对比较了解 ...

  3. Android 数据存储---外部存储(SD卡)

    使用外部存储实现数据持久化,这里的外部存储一般就是指的是sdcard.使用sdcard存储的数据,不限制只有本应用访问,任何可以有访问Sdcard权限的应用均可以访问,而Sdcard相对于设备的内部存 ...

  4. 【Android 逆向】Android 系统文件分析 ( 外部存储设备文件 | sbin 命令程序目录 | dev 字符设备目录 )

    文章目录 一.外部存储设备文件 二.sbin 命令程序目录 三.dev 字符设备目录 一.外部存储设备文件 /sdcard 文件是一个链接 , 相当于快捷方式 , 其实际的目录是 /storage/s ...

  5. android 存储无法写入,在Android中的外部存储中写入文件

    我想在外部存储sdCard中创建一个文件并写入它.我已经通过互联网搜索并尝试但没有得到结果,我已经在Android Manifest文件中添加了权限,我在模拟器上这样做,我正在尝试下面的代码和获取ER ...

  6. Android 8.0 中如何读取内部和外部存储以及外置SDcard

    最近碰到询问我这个读取SDcard的问题, 很久没有看这部分了,所以大致看了一下, 顺便记录一下.在Android 8.0上做了测试. 一般的Android App能读取的存储空间主要有三种: app ...

  7. android Q版本外部存储问题以及获取空间大小问题

    Q版本: 1.在manifest 文件中添加权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_ST ...

  8. Android开发--文件系统中的内部存储和外部存储最全解析 附文件数据保存操作封装

    文件存储 前言 文件存储 内存 内部存储 外部存储 内部存储操作 API 读写操作 外部存储操作 公共目录 私有目录 私有文件 私有缓存 文件各种操作封装 前言 众所周知,数据存储在每个应用中都会用到 ...

  9. android internal storage 路径,内部存储InternalStorage和外部存储ExternalStorage-Android

    > 一个是清除缓存,另一个是清除数据;内部存储InternalStorage,外部存储ExternalStorage 彻底理解android中的内部存储与外部存储- http://blog.cs ...

最新文章

  1. linux下gdb所有实用方法
  2. Windows sever 2008
  3. 第二十一讲 任务的删除
  4. 在线白板,基于socket.io的多人在线协作工具
  5. hdu (欧拉函数+容斥原理) GCD
  6. OpenStack的部署T版(四)——Placement组件
  7. webbrowser 访问iframe拒绝访问_Win10系统下Documents and Settings系统文件夹拒绝访问解决方法...
  8. 对中级Linux用户有用的20个命令
  9. kettle下载安装使用教程
  10. Error: new BigNumber() not a base 16 number
  11. 华氏温度和摄氏温度的转换-C语言
  12. HTTP 出现304情况及详解
  13. zmud之自动解谜:不用数据库实现自动解谜的原理。
  14. 云桌面及桌面虚拟化的功能
  15. 使用头文件winbase.h的错误
  16. ZYNQ从放弃到入门(八)-PS和PL交互
  17. 科技公司将跳过IPO直接接受机构融资
  18. viper4android md,【超级街霸4安卓版】超级街霸4安卓完整移植版游戏下载-街机中国...
  19. hls m3u8文件学习分析
  20. 按键控制步进电机转速(led闪烁)学习心得

热门文章

  1. java发送QQ群邮件,Java使用腾讯企业邮箱 、javamail 、 SSL 发送邮件/群发
  2. 插曲一下:很多程序员会遇到的脱发问题
  3. 用晚餐瘦身是最好的方法
  4. 打造「可盈利个人品牌」终极指南,8个步骤开始建立你的个人品牌吧!
  5. C#开发技术 计算器(二进制、八进制、十进制)
  6. java中常用的数学函数
  7. 河北大学计算机学院李珍,电气学院教师暑期参加2019年河北省高校智慧教学暨“金课”建设研讨会...
  8. 宫廷心计服务器修复,3月25日停服版本更新公告
  9. 最全RAID( RAID 0、RAID 1、RAID 5、RAID 10 ······) 以及它们的优缺点以及原理解析
  10. 【翻译】StreamDM:基于Spark Streaming的高级数据挖掘 StreamDM: Advanced Data Mining in Spark Streaming