分为内部存储和外部存储。
目录 /data/data/包名。
应用删除后会被主动删除。
只有当前应用可访问。
Log.v(TAG,"内部目录");
Log.v(TAG , Environment.getDataDirectory().getAbsolutePath() ); //根目录
Log.v(TAG , getFilesDir().getAbsolutePath());
Log.v(TAG , getCacheDir().getAbsolutePath());
输出结果为:
12-26 20:14:04.881 11336-11336/? V/MainActivity: 内部目录
12-26 20:14:04.881 11336-11336/? V/MainActivity: /data
12-26 20:14:04.881 11336-11336/? V/MainActivity: /data/data/com.touch.www.android.coolreader/files
12-26 20:14:04.881 11336-11336/? V/MainActivity: /data/data/com.touch.www.android.coolreader/cache
如果您想要缓存一些数据,而不是永久存储这些数据,应该使用 getCacheDir() 来打开一个 File,它表示您的应用应该将临时缓存文件保存到的内部目录。
需要注意的是:
当设备的内部存储空间不足时,Android 可能会删除这些缓存文件以回收空间。 但您不应该依赖系统来为您清理这些文件, 而应该始终自行维护缓存文件,使其占用的空间保持在合理的限制范围内(例如 1 MB)。 当用户卸载您的应用时,这些文件也会被移除。
如果想查看内部目录文件
,开发中查看内部目可使用此种方法,规避权限问题:
###### adb shell
###### run-as 包名
然后就可以使用 ls之类的命令查看内部存储结构。
下面是一个在内部文件中写入的方法。openFileOutput()是系统提供的方法。
String str = "hello world\n";
String FILENAME = "hello_file";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = openFileOutput(FILENAME, MODE_PRIVATE);
fileOutputStream.write(str.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
外部存储是在SD卡或者手机rom分出来的部分区域里。
目录为 /storage/emulated/0/Android/data/包名/
或者/storage//Android/data/ 之类
外部存储是不安全的,任何应用都可以访问你在外部存储中的文件。
访问外部目录:
Log.v(TAG, Environment.getExternalStorageDirectory().getAbsolutePath());
Log.v(TAG, getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath());
输出为:
12-26 20:14:04.881 11336-11336/? V/MainActivity: 外部目录
12-26 20:14:04.881 11336-11336/? V/MainActivity: /storage/emulated/0
12-26 20:14:04.891 11336-11336/? V/MainActivity: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files/Pictures
其中 通过getExternalStorageDirectory访问得到的是外部存储的根目录。在根目录下建立的文件,是不会随着app的移除而被删除的。
如果你想保存照片之类的东西,并且想使得文件不随着你的app的移除而移除,可使用:
getExternalStoragePublicDirectory() 方法获取表示外部存储设备上相应目录的 File。 该方法使用指定您想要保存以便它们可以与其他公共文件在逻辑上组织在一起的文件类型的参数,比如 DIRECTORY_MUSIC 或 DIRECTORY_PICTURES。
例如,您可以使用以下方法来创建个人相册的目录:
public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
通过getExternalFilesDir(XXX)得到或者建立的目录 会随着app的移除而被删除。
下面是一些有用的方法。
/* 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;
}
如果您事先知道您将保存的数据量,您可以查出是否有足够的可用空间,而无需调用 getFreeSpace() 或 getTotalSpace() 引起 IOException。这些方法分别提供目前的可用空间和存储卷中的总空间。 此信息也可用来避免填充存储卷以致超出特定阈值。
但是,系统并不保证您可以写入与 getFreeSpace() 指示的一样多的字节。如果返回的数字比您要保存的数据大小大出几 MB,或如果文件系统所占空间不到 90%,则可安全继续操作。否则,您可能不应写入存储。
保存您的文件之前,您无需检查可用空间量。 您可以尝试立刻写入文件,然后在 IOException 出现时将其捕获。 如果您不知道所需的确切空间量,您可能需要这样做。 例如,如果在保存文件之前通过将 PNG 图像转换成 JPEG 更改了文件的编码,您事先将不知道文件的大小。
您应始终删除不再需要的文件。删除文件最直接的方法是让打开的文件参考自行调用 delete()。
myFile.delete();
如果文件保存在内部存储中,您还可以请求 Context 通过调用 deleteFile() 来定位和删除文件:
myContext.deleteFile(fileName);
注:当用户卸载您的应用时,Android 系统会删除以下各项:
您保存在内部存储中的所有文件
您使用 getExternalFilesDir() 保存在外部存储中的所有文件。
但是,您应手动删除使用 getCacheDir() 定期创建的所有缓存文件并且定期删除不再需要的其他文件。
有时,已分配某个内部存储器分区用作外部存储的设备可能还提供了 SD 卡槽。
和更低版本的这类设备时,getExternalFilesDir() 方法将仅提供内部分区的访问权限,而您的应用无法读取或写入 SD 卡。如果您希望在支持 Android 4.3 和更低版本的同时访问两个可能的位置,请使用支持库中的静态方法 ContextCompat.getExternalFilesDirs()
可通过调用 getExternalFilesDirs() 来同时访问两个位置,该方法将会返回包含各个位置条目的 File 数组。 数组中的第一个条目被视为外部主存储;除非该位置已满或不可用,否则应该使用该位置。在 Android 4.3 和更低版本中,此方法也会返回一个 File 数组,但其中始终仅包含一个条目。
Log.v(TAG, "其他");
Log.v(TAG , getExternalFilesDir(null).getAbsolutePath());
File[] files = getExternalFilesDirs(null);
int i = 0;
for(File file : files){
if(file != null){
Log.v(TAG + (i++), file.getAbsolutePath());
}
}
Log.v(TAG, "V4支持包");
File[] filesV4 = ContextCompat.getExternalFilesDirs(this, null);
int j = 0;
for(File file : filesV4){
if(file != null){
Log.v(TAG + (j++), file.getAbsolutePath());
}
}
输出结果:
当设置rom上的分区 为 外部主存储的时候
12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity: 其他
12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files
12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity0: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files
12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity1: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files
12-27 18:00:23.751 18365-18365/com.touch.www.android.coolreader V/MainActivity: V4支持包
12-27 18:00:23.753 18365-18365/com.touch.www.android.coolreader V/MainActivity0: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files
12-27 18:00:23.753 18365-18365/com.touch.www.android.coolreader V/MainActivity1: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files
当设置SD卡为外部主存储的时候:
12-27 18:09:07.905 10676-10676/com.touch.www.android.coolreader V/MainActivity: 其他
12-27 18:09:07.906 10676-10676/com.touch.www.android.coolreader V/MainActivity: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files
12-27 18:09:07.906 10676-10676/com.touch.www.android.coolreader V/MainActivity0: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files
12-27 18:09:07.906 10676-10676/com.touch.www.android.coolreader V/MainActivity1: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files
12-27 18:09:07.906 10676-10676/com.touch.www.android.coolreader V/MainActivity: V4支持包
12-27 18:09:07.907 10676-10676/com.touch.www.android.coolreader V/MainActivity0: /storage/emulated/0/Android/data/com.touch.www.android.coolreader/files
12-27 18:09:07.907 10676-10676/com.touch.www.android.coolreader V/MainActivity1: /storage/2289-D6D9/Android/data/com.touch.www.android.coolreader/files
通过这个测试可以发现,getExternalFilesDir(null)返回的是主要外部存储的路径,不能保证是SD卡的路径还是rom上的路径。