注意:由于Android6.0+支持多用户,所以,在4.1.2 返回路径 /data/data/com.xxx.xxx/
请自动看做 6.0 下的/data/user/0/com.xxx.xxx/目录

外部文件存储

最容易混淆的是外部存储,如果说pc上也要区分出外部存储和内部存储的话,那么自带的硬盘算是内部存储,U盘或者移动硬盘算是外部存储,因此我们很容易带着这样的理解去看待安卓手机,认为机身固有存储是内部存储,而扩展的T卡是外部存储。比如我们任务16GB版本的Nexus 4有16G的内部存储,普通消费者可以这样理解,但是安卓的编程中不能,这16GB仍然是外部存储。

所有的安卓设备都有外部存储和内部存储,这两个名称来源于安卓的早期设备,那个时候的设备内部存储确实是固定的,而外部存储确实是可以像U盘一样移动的。但是在后来的设备中,很多中高端机器都将自己的机身存储扩展到了8G以上,他们将存储在概念上分成了”内部internal” 和”外部external” 两部分,但其实都在手机内部。所以不管安卓手机是否有可移动的sdcard,他们总是有外部存储和内部存储。最关键的是,我们都是通过相同的api来访问可移动的sdcard或者手机自带的存储(外部存储)。

自定义外部存储Environment

注意在AndoridManifest.xml中声明存储权限请求,6.0以上的系统要动态请求

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

  • static File getDataDirectory()获得android /data的目录。
  • static File getExternalStorageDirectory()获取Android的/storage/emulated/0目录也是就/sdcard目录
  • static File getExternalStoragePublicDirectory(String type)根据类型来获取sdcard上的目录如type为Environment.DIRECTORY_MUSIC时,路径为/storage/emulated/0/Music
  • static File getRootDirectory()获得android的/system目录。
  • static File getDownloadCacheDirectory()这个指的是/cache这么目录

规范化外部存储

应用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的。

大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中。

这样当该应用被卸载后,这些数据还保留在SDCard中,留下了垃圾数据。

如果你想让你的应用被卸载后,与该应用相关的数据也清除掉,该怎么办呢?

通过context.getExternalFilesDir()方法可以获取到 sdcard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据

通过context.getExternalCacheDir()方法可以获取到 sdcard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据

如果使用上面的方法,当你的应用在被用户卸载后,sdcard/Android/data/你的应用的包名/ 这个目录下的所有文件都会被删除,不会留下垃圾信息。

而且上面二个目录分别对应 设置->应用->应用详情里面的”清除数据“与”清除缓存“选项

路径的规律图如下

一般地,通过ContextEnvironment相关的方法获取文件存取的路径。

通过这两个类可获取各种路径,如图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
+- /data ---> Environment.getDataDirectory()
| |
| |
| +- data/com.adorkable.sample
| |
| |
| +- files ---> context.getFilesDir()
| | |
| | +- file1 ---> context.getFileStreamPath("file1")
| | |
| | +- file2 --->context.openFileOutput("file2")
| |
| +- cache ---> context.getCacheDir()
| |
| +- app_$name ---> context.getDir(String name, int mode)
| |
| +- shared_prefs ---> context.getSharedPreferences()
|
|
+- /storage/sdcard0 ---> Environment.getExternalStorageDirectory()
|
|- Music --->Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)
|
+- dir1 --->Environment.getExternalStoragePublicDirectory("dir1")
|
+- Andorid/data/com.adorkable.sample【注:这里是包名】
|
|
+- files ---> context.getExternalFilesDir("")
| |
| +- file1 ---> context.getExternalFilesDir("file1")
| |
| +- Music ---> context.getExternalFilesDir(Environment.Music)
| |
| +- Picture ---> context.getExternalFilesDir(Environment.Picture)
| |
| +- ...
|
|
+- cache --->context.getExternalCacheDir()
|
+- 其他