解析Android内部存储、外部存储的区别

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的目录是以/为根节点,根节点下又有不同的节点。而我们的物理存储设备就是挂载都这些节点上,如下图所示:

 


/data/data/ apk的安装目录。 如:百度地图的安装路径是/data/data/com.baidu.com/ 注意:该目录需要获取root权限才能查看
/system/ 存放系统应用的apk文件,即手机厂商预安装应用的apk文件 (手机厂商只需把需要预安装的apk放在该节点的相应路径下,android系统就会自己解压并安装该apk)
/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提供了供存储设备挂载的节点。同一个存储设备经过分区后,不同的分区可以挂载到不同的节点上,如手机的内置存储卡。
使用内部存储是不需要权限的,内部存储属于应用的私有存储区域,其它应用不可访问,当应用被卸载时,内部存储中的文件也会被删除。
外部存储分为公共目录和私有目录,外部存储是可以全局访问的,但需要申请权限:
Android4.4以前访问私有目录和公共目录都需要申请 WRITE_EXTERNAL_STORAGE 权限
Android4.4以后访问私有目录不需要申请权限,但公共目录是需要申请 WRITE_EXTERNAL_STORAGE 权限
自 API 级别 17 以来,常量 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 已被弃用。从 Android N 开始,使用这些常量将会导致引发 SecurityException。
如果缓存的数据量比较大,请不要保存到内存存储中,如果想保存可共享给其它应用的数据,请保存到外部存储的公共目录中。
设置项的Clear Data 和Clear cache两个选项,这两个都是情况应用的缓存数据,具体区别如下:
Clear Data清理的是外部存储中的应用私有目录下的file文件夹
Clear Cache清理的是外部存储中的应用私有目录下的cache文件夹

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android知识点整理包括但不限于以下内容: 1. Android基础知识: - Android系统架构和组件:包括应用层、应用框架层、系统运行库层和Linux内核层。 - Android应用的生命周期:包括活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供器(Content Provider)的生命周期。 - Android应用的资源管理:包括布局文件、字符串资源、图像资源等的使用和管理。 - Android应用的权限管理:包括权限的声明和请求。 2. Android界面开发: - 布局管理器:包括线性布局(LinearLayout)、相对布局(RelativeLayout)、帧布局(FrameLayout)等。 - 视图控件:包括文本视图(TextView)、按钮(Button)、图像视图(ImageView)等。 - 用户交互:包括点击事件、手势识别、触摸事件等的处理。 3. Android数据存储: - Shared Preferences:用于存储少量的键值对数据。 - SQLite数据库:用于存储结构化数据。 - 文件存储:包括内部存储外部存储的文件存储方式。 4. Android网络编程: - 网络请求:使用HttpURLConnection或HttpClient进行网络请求。 - JSON解析:使用JSONObject或GSON库解析JSON数据。 - 图片加载:使用Picasso或Glide库加载网络图片。 5. Android多媒体开发: - 音频播放:使用MediaPlayer进行音频播放。 - 视频播放:使用VideoView或ExoPlayer进行视频播放。 - 相机和相册:使用Camera或Camera2 API进行拍照和录制视频。 6. Android传感器: - 加速度传感器、光传感器、陀螺仪等的使用。 7. Android地图和定位: - 使用Google Maps API进行地图显示和定位功能的开发。 以上仅为Android知识点的概要,实际开发还涉及更多的内容。希望以上信息对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值