文件系统是android一个重要的部分。我们需要保存app的一些数据。或者我们需要用到系统的一些数据,如相册等。那么就需要对文件系统有一定的了解。 android文件系统有一个非常让人困惑的地方,就是获取的文件名和路径可能是不确定的。例如下面的代码,这个代码是非常常用的。但这个代码在不同的android版本可能出现的结果不同。
Environment.getExternalStorageDirectory()
可能出现下面的结果。
/storage/emulated/0
/mnt/sdcard
/storage/sdcard
storage和sdcard的区别
这里有一个非常困惑的问题,就是storage和sdcard有什么区别?在SDK19(android4.4)开始,android系统就封禁了sd卡。转而变成了内置sd卡(不可简单更换),或者叫内部存储器也行。原因也非常的简单,因为允许用户自己换sd卡似乎不太安全。sd卡五花八门,对系统兼容性和稳定性都有非常大的影响。换成内置也是理所当然。 如下面SDK16的文件目录,/sdcard(root目录下)链接的地址实际上是/mmt/sdcard(注意看sdcard文件夹有个箭头的小图标,表示是软链接)。虽然也有/storage目录,但/storage是个空目录。
再看看SDK19的目录结构,就看出了明显不同。/sdcard链接的是/storage/sdcard,这里并没有直接删除/sdcard,而是改了链接的目标地址,可能也是考虑兼容性问题吧。 值得一提的是/mnt/sdcard实际上也是链接到了/storage/sdcard 对于开发者来说,不需要关系getExternalStorageDirectory()获取到的到底是那个目录,我们更关心的无非是他的子目录,也就是下面这些常见目录。
外部存储和内部存储
现在要说说什么是外部存储和内部存储。其实这两个概念非常的简单,/data/data目录下的空间就是内部存储。在getExternalStorageDirectory方法的文档也有说明,外部的同义词是share(共享)。例如/sdcard/Android/data,注意,这里有个容易混淆的地方。不管是sd卡还是内部存储卡,其实都是外部存储(外部存储和内部存储并不是物理概念,而是目录的功能概念)。外部存储的一个最大的特定就是共享,别的应用都能修改你的app的存储在外部存储的数据。也就是外部数据是不安全的。 总的来说,外部存储是对于app共享的,内部存储对于app是独占的。
/data/data和/sdcard/Android/data目录的共同点和区别
共同点: app被卸载的时候/sdcard/Android/data和/data/data的数据会被清除。(一定要刷新(Synchronize)文件系统!!!点开关闭是没有用的,并且Synchronize只能刷新当前文件夹,换了一个文件夹需要重新刷新)
从上面的文件结构可以发现,这两个目录下都可以存放app的数据,那么这两个文件有什么区别呢? 区别: 1./sdcard/Android/data属于外部存储。/data/data属于内部存储。 2…别的app能修改/sdcard/Android/data下其它app的数据。别的app不能修改/data/data目录下不是自己的数据。
Context提供的文件操作方法
内部存储操作方法
主要有getCacheDir(),getFilesDir()和getCodeCacheDir(), getSharedPreferences()
接下来要介绍三个Context的方法。这三个方法都是对于内部存储的,也就是/data/data目录。非常有意思的是,这三个方法都是不需要读写权限的,也不需要在清单文件中声明权限,因为app私有目录本身就已经有读写权限了。 getCacheDir(): 获取/data/data/app包名/cache文件夹,默认已经存在。在这个文件夹下面的读写操作都不需要申请读写权限,因为默认已经有了。 getFilesDir(): 获取/data/data/app包名/files文件夹,默认已经存在。在这个文件夹下面的读写操作都不需要申请读写权限,因为默认已经有了。 getCodeCacheDir(): SDK21才有的方法。获取/data/data/app包名/code_cache文件夹,没有会创建。在这个文件夹下面的读写操作都不需要申请读写权限,因为默认已经有了。 getSharedPreferences(): SharedPreferences我们非常熟悉。所产生的文件在/data/data/shared_prefs目录下,没有会创建,不需要读写权限。 getDataDir(): 获取/data/app/app包名 目录。需要SDK24,并且需要root权限,一般是用不到的。 getObbDir: 获取/sdcard/Android/obb/app包名。需要读写权限。
外部存储操作方法
和内部存储操作方法非常类似,只是这些方法都是在/sdcard/Android/data目录下,在这些目录下面的读写操作是需要读写权限的,但是调用这些方法本身不需要读写权限。 getExternalCacheDir(): 读取/sdcard/Android/data/app包名/cache目录。没有创建。卸载删除。 getExternalCacheDirs(): 和getExternalCacheDir相比,可以返回多个sd卡的/sdcard/Android/data/app包名/cache目录,不过这种情况不常见。而且需要最少SDK19。 getExternalFilesDir(String type): 这个方法非常的有用。可以传一个type参数对应下面的目录文件名。例如Environment.DIRECTORY_DCIM。表示DCIM这个目录,也就是相册目录。 getExternalFilesDirs(String type): 同getExternalFilesDir(String type),只是可以返回多个sd卡的内容。需要SDK19。
getExternalMediaDirs(): 返回sdcard/Android/data/app包名/media目录。需要SDK21一般用不到。
Environment提供的获取目录方法
Environment类也提供了几个获取非常常用的目录的方法。 getExternalStorageDirectory: 前面已经提到,可以获取外部存储的根目录。可能有下面的结果。这个方法在android10废弃,取代的是Context的getExternalFilesDir(String type)
/storage/emulated/0
/mnt/sdcard
/storage/sdcard
getExternalStorageState: 获取外部存储的状态,这个方法没有跟着废弃。一般返回MOUNTED,也可能是下面的值。一般用不到。
* @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED},
* {@link #MEDIA_UNMOUNTED}, {@link #MEDIA_CHECKING},
* {@link #MEDIA_NOFS}, {@link #MEDIA_MOUNTED},
* {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED},
* {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
getRootDirectory: 返回/system目录。
getDataDirectory: 返回/data目录。 getDownloadCacheDirectory: 返回/cache目录。
|