一、Android系统中文件
本人是通过网上技术博客和AndroidStudio自带的DeviceFileExplorer工具基础上理解整个Android系统文件基本框架。
1.1 Android应用中常用的文件目录
Android文件系统同样是基于Linux的虚拟文件系统(VFS),通过系统软件层将不同的底层硬件的差异进行差分处理,然后封装统一的接口提供给应用层开发调用的。VFC设计的好处是让可以不同类型的技术人员专注于解决特定的领域的问题,硬件驱动、操作系统、应用层开发等,分工明确可以专注于一个特定领域更有利于提供工作效率,保证整体的稳定性。个人都感觉这种宏观设计就是典型的模块化、面向对象设计思想。
在《解析Android内部存储、外部存储的区别》中看到简易的Android文件树状的图和基本介绍,感觉不错就copy来了,希望原作者不要介意。
- /data/data/package-name的安装目录。 如:百度地图的安装路径是/data/data/com.baidu.com/ 注意:该目录需要获取root权限才能查看
- /system/ 存放系统应用的apk文件,即手机厂商预安装应用的apk文件,launcher就是在这个目录下的 (手机厂商只需把需要预安装的apk放在该节点的相应路径下,android系统就会自己解压并安装该apk)
- /storage/ 该节点是内置存储卡和外置SD卡的挂载点,/storage/emulated/0/是内置存储卡挂载点, /storage/sdcard1是外置SD卡挂载点(不同的设备挂载节点不一样,有些设备可能会挂载到/mnt/节点)
1.2 Android文件系统补充知识点
- 在网上看到很多人将DeviceFileExplorer截图也贴在博文便于理解,但是个人感觉这个没有必要因为只要打开是AS连接上真机就可以看到了。
还有看到做系统开发站在Android编译的角度总结文件系统的文章,感觉很不错但是不是很明白,还好看到《Android系统文件目录结构》中对Android系统文件进行层次分明标注,于是就也copy了一下记录下来,作为备用参考知识。
|-3rdmodemnvm
|-3rdmodemnvmbkp
|-acct //系统回收站
|-uid
|-uid_0
|-bin
|-cache //缓存
|-config //配置
|-cust
|-etc
|-global
|-hw
|-xml
|-data //【内部存储】 --> Environment.getDataDirectory()
|-app //存放用户安装的软件
|-data //存放用户安装的所有程序,包含/system/app 和 /data/app 和 /mnt/asec中装的软件
|-android
|-com.test.demo //应用程序的内部存储目录,卸载时自动清除
|-app_textures // --> Context.getDir(String name, int mode)
|-app_webview // --> Context.getDir(String name, int mode)
|-cache //缓存,不需要额外的权限;当该文件夹超额时,系统将自动删除该目录中的文件 --> context.getCacheDir()
|-code_cache
|-databases //数据库
|-files //不需要额外的权限 --> context.getFilesDir()
|-file1 // --> Context.getFileStreamPath("file1")
|-shared_prefs //sharedPrefrences配置文件
|-.xml 配置文件
|-system //安装app时的注册表配置
|-local
|-tmp
|-user
|-0
|-com.test.demo //文件系统目录的绝对路径,所有属于该应用程序的私有文件都存储在文件系统中 (minsdk 21) --> context.getDataDir()
|-cache //
|-code_cache //保存应用程序代码缓存文件的目录路径 (minsdk 21) --> context.getCodeCacheDir()
|-databases //
|-files //
|-no_backup //不会自动备份到远程存储的应用程序文件的路径 (minsdk 21) --> context.getNoBackupFilesDir()
|-dev //设备文件,Linux系统常规文件夹,里面的文件很多都是设备模拟的文件系统
|-blkio
|-background
|-foreground
|-block
|-input
|-dload
|-eng
|-etc //系统配置文件
|-bluetooth
|-init
|-logo
|-log
|-mnt //挂载点
|-proc //运行时文件
|-product
|-app
|-etc
|-lib
|-media
|-res
|-root
|-sdcard
|-amap
|-Android
|-data //应用程序包 同上面的/data/data/com.test.demo
|-media
|-dcim
|-camera //照片以及视频
|-download //下载的文件,存放.apk包
|-logo
|-movies
|-musics
|-pictures //屏幕截屏
|-sandbox
|-storage //【外部存储】
|-sdcard0 //文件管理器看到的文件 下面的目录跟 /sdcard/目录下的文件目录一样 --> Environment.getExternalStorageDirectory()
|-Android //
|-data //同上面的/data/data/
|- com.test.demo
|-cache //系统不会时刻监测这里的数据,有可能不会自动清除 --> context.getExternalCacheDir()
|-files // --> context.getExternalFilesDir
|-file1 // --> Context.getExternalFilesDir("file1")
|-obb // --> context.getObbDir()
|-DCIM // --> Environment.getExternalStoragePublicDirectory("DCIM")
|-backups
|-baidu
|-Download
|-self
|-sys //Linux 内核文件
|-system // 包含系统的framework、组件、字体播放器等系统自带的资源配置;常用开发工具tcpdump/sqlite3
|-app //系统自带的应用程序, .apk包
|-bin //存放用户常用的工具程序
|-build.prop //记录了系统的设置和改变,类似于/etc中的文件
|-etc //存放了系统中几乎所有的配置文件,根目录下的/etc链结于此,比如APN接入点设置等核心配置,Bluetooth...
|-modules //存放内核模块(主要是fs和net)和模块配置文件
|-fonts //字体库
|-framework //.jar包,系统核心文件
|-init.rc //一个初始化脚本,用于将/system/modules和/system/xbin挂载为cramfs,避免系统被无意破坏
|-lib //.so包,系统底层类库,框架层的实现文件
|-usr //用户文件夹,包含共享、键盘布局、时间区域文件等
|-media //.ogg音频文件
|-audio //系统默认铃声
|-alarms //闹钟
|-animationsounds //开关机动画
|-notificatinos //短信或提示音
|-rignstones //来电铃声
|-ui //界面音效,比如键盘敲击声
|-video //
|-xbin //系统管理工具
|-theme
|-vendor
|-version
二、Android应用文件存储区域
Android系统在应用层按照逻辑上划分为两个文件存储区域:内部存储空间和外部存储空间。但是开发者根据Android系统提供文件接口进行数据读写操作,最终实现还是要在通过物理介质存储的,所以接下来先从易于理解的存储硬件开始逐步到最后基本开发应用认识做基本记录。
2.1 物理存储与逻辑划分
Android物理存储基本认识
本质上讲一部Android智能手机也是冯·诺依曼结构计算机,既Android智能机中同样是有CPU、内存、磁盘、输入输出等基本组件。Android智能手机厂家都有内置的存储磁盘(Google文档叫内置的非易失性内存),否则它就运行不起来的。
目前国内Android智能手机厂家也基本上保留MicroSD卡卡槽支持扩展,Android中扩展MicroSD卡和内置存储磁盘同样在冯诺依曼计算机结构中都是的磁盘的角色,只是在物理空间上存储位置不一样而已,可以类比PC机磁盘和移动硬盘。
从"大哥大"到"功能机"到"山寨机"再到现在智能机整个过程中一直就伴随有“内存卡/Micro SD卡"。那就从SD卡开始数一下常见错误认识:
- 有人错误以为Android的外部存储的物理存储空间就是指SD卡;
- 当然普通人基本上都没有完全搞明白内存和磁盘关系,有把内存卡当成内存的。
Android应用程序的开发者并不需要完全掌握并理解Android智能机的物理磁盘与底层系统处理逻辑,因为正如上文中所讲的基于Linux的虚拟文件系统(VFS)的Android在应用层屏蔽了内置存储卡和外置SD卡的关系,既同样Api在存储位置选择与实现由系统代码决定。开发者只需要调用Android提供文件接口实现业务需要即可,但是用户需要清楚哪些那个Api存储文件是可能会随SD卡缺失而丢失,哪些是只和APP有关系。
2.2 Android文件逻辑划分
所有 Android 设备都有两个文件存储区域:内部存储空间和外部存储空间。现在,很多设备将永久性存储空间划分为单独的“内部”和“外部”分区。因此,即使没有可移动存储媒介,这两种存储空间也始终存在,并且无论外部存储空间是否可移动,这两种存储空间的 API 行为都是相同的。由于外部存储空间可能是可移动的,因此这两种选项之间存在一些差异。
内部存储空间 | 外部存储空间 |
1.始终提供 ; 2.只有应用本身才可以访问保存到此处的文件。 3.如果用户卸载您的应用,系统会从内部存储空间中移除您应用的所有文件 | 1.并非始终提供,因为用户可以将外部存储空间装载为 USB 存储设备,也可以在某些情况下将其从设备中移除 ; 2. 全局可读,因此保存到此处的文件可能在您的控制范围之外被读取。 3.如果用户卸载您的应用,系统会从此处移除您应用的文件(仅当您通过 getExternalFilesDir() 将这些文件保存到目录中)。 |
/data/data/package_name/…… | /storage/…… |
Google文档的建议
- 如果开发者希望确保用户和其他应用都无法访问您的文件,最好使用内部存储空间。
- 对于不需要访问限制的文件以及您希望与其他应用共享或允许用户通过计算机访问的文件,外部存储空间是最佳位置。
- 注意:尽管应用默认安装到内部存储空间中,但您可以通过在清单中指定 android:installLocation 属性将应用安装到外部存储空间中。如果要安装的 APK 非常大且外部存储空间比内部存储空间大得多,则用户会倾向于使用此选项。
2.3 Android开发文件基本API
内部存储 internal Storage
内部存储 位于应用包名相同的目录下,既属于内部存储的文件,与应用相关联,当应用卸载之后,内部存储中的这些文件也被删除。
内部存储空间十分有限,因而显得可贵,而且,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。所以对于内部存储空间,需要合理使用。
内部存储的几个基本知识点
- App应用中不需要任何系统权限即可读取和写入这些方法返回的内部目录;
- 内部存储函数一般都是需要Context来获取和操作;
- App中Shared Preferences、SQLite数据库、WebView 缓存信息以及App内部缓存file均属于内部存储,且目录为data/data/package_name/;
- getFreeSpace() 和getTotalSpace() 分别提供存储卷中的当前可用空间和总空间,不引发 IOException
获取合适的File对象:当存储在内部存储时,可用通过下面方法:
Context getFilesDir(): 返回应用程序的内部files目录的File对象。
Context getCacheDir():返回一个应用程序内部临时文件目录的File对象,这个临时文件在不需要时会被删除,在系统可用存储很低时也会被系统删除。
//打开指定文件 流
//输出流
String filename = "fileName";
byte[] fileContent = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(fileContents.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
获取存储文件夹
其他详细可以直接查看Google文档 内部存储
三、Android应用开发文件存储区域