标签:
转自:http://www.liaohuqiu.net/cn/posts/storage-in-android/
android系统自身自带有存储,另外也可以通过sd卡来扩充存储空间。前者好比pc中的硬盘,后者好移动硬盘。 前者空间较小,后者空间大,但后者不一定可用。 开发应用,处理本地数据存取时,可能会遇到这些问题:
应用数据存放路径,同其他应用应该保持一致,应用卸载时,清除数据:
需要判断两者的可用空间: sd卡存在时,可用空间反而小于机身内部存储,这时应该选用机身存储;
数据安全性,本应用数据不愿意被其他应用读写;
图片缓存等,不应该被扫描加入到用户相册等媒体库中去。
从API 19 / Andorid 4.4 / KITKAT开始,不再需要显式声明这两个权限,除非要读写其他应用的应用数据(
$appDataDir
)
判断sd卡可用:
/**
* Check if the primary "external" storage device is available.
*
* @return
*/
public static boolean hasSDCardMounted() {
String state = Environment.getExternalStorageState();
if (state != null && state.equals(Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}
根据系统用户不同,所能占用的存储空间大小也有不同
使用外部存储,需要的权限,在AndoridManifest.xml
中:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
在API level 9及其以上时,
File
对象的getFreeSpace()
方法获取系统root用户可用空间;
getUsableSpace()
取非root用户可用空间
当有多个存储可用时获取磁盘用量,根据当前系统情况选用合适的存储。
根据系统存储用量,合理设定app所用的空间大小;运行时,也可做动态调整。
在API level 9及其以上的系统,可直接调用File
对象的相关方法,以下需自行计算:
@TargetApi(VERSION_CODES.GINGERBREAD)
public static long getUsableSpace(File path) {
if (path == null) {
return -1;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
return path.getUsableSpace();
} else {
if (!path.exists()) {
return 0;
} else {
final StatFs stats = new StatFs(path.getPath());
return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
}
}
}
一般地,通过Context
和 Environment
相关的方法获取文件存取的路径。
通过这两个类可获取各种路径,如图:
($rootDir)
+- /data -> Environment.getDataDirectory()
| |
| | ($appDataDir)
| +- data/com.srain.cube.sample
| |
| | ($filesDir)
| +- files -> Context.getFilesDir() / Context.getFileStreamPath("")
| | |
| | +- file1 -> Context.getFileStreamPath("file1")
| | ($cacheDir)
| +- cache -> Context.getCacheDir()
| |
| +- app_$name ->(Context.getDir(String name, int mode)
|
| ($rootDir)
+- /storage/sdcard0 -> Environment.getExternalStorageDirectory()
| / Environment.getExternalStoragePublicDirectory("")
|
+- dir1 -> Environment.getExternalStoragePublicDirectory("dir1")
|
| ($appDataDir)
+- Andorid/data/com.srain.cube.sample
|
| ($filesDir)
+- files -> Context.getExternalFilesDir("")
| |
| +- file1 -> Context.getExternalFilesDir("file1")
| +- Music -> Context.getExternalFilesDir(Environment.Music);
| +- Picture -> ... Environment.Picture
| +- ...
|
| ($cacheDir)
+- cache -> Context.getExternalCacheDir()
|
+- ???
下面介绍这些路径的特性以及使用中需要注意的细节:
根目录($rootDir
):
/data
, 通过Environment.getDataDirectory()
获取外部存储路径: /storage/sdcard0
(也有类似 /mnt/ 这样的),通过Environment.getExternalStorageDirectory()
获取
示例:
Environment.getDataDirectory():
/data
Environment.getExternalStorageDirectory():
/storage/sdcard0
应用数据目录($appDataDir
)
$appDataDir = $rootDir/data/$packageName
,$appDataDir = $rootDir/Andorid/data/$packageName
在这些目录下的数据,在app卸载之后,会被系统删除,我们应将应用的数据放于这两个目录中。
外部存储中,公开的数据目录。 这些目录将不会随着应用的删除而被系统删除,请斟酌使用:
Environment.getExternalStorageDirectory():
/storage/sdcard0
// 同 $rootDir
Environment.getExternalStoragePublicDirectory(""):
/storage/sdcard0
Environment.getExternalStoragePublicDirectory("folder1"):
/storage/sdcard0/folder1
应用数据目录下的目录
一般的在$appDataDir下,会有两个目录:
数据缓存:$cacheDir = $appDataDir/cache
:
Context.getCacheDir()
, 机身内存不足时,文件会被删除外部存储:Context.getExternalCacheDir()
外部存储没有实时监控,当空间不足时,文件不会实时被删除,可能返回空对象
示例:
Context.getCacheDir():
/data/data/com.srain.cube.sample/cache
Context.getExternalCacheDir():
/storage/sdcard0/Android/data/com.srain.cube.sample/cache
文件目录 $filesDir = $appDataDir/files
:
内部存储:通过Context.getFilesDir()
获取
Context.getFileStreamPath(String name)
返回以name
为文件名的文件对象,name
为空,则返回$filesDir
本身
示例:
Context.getFilesDir():
/data/data/com.srain.cube.sample/files
标签:
原文地址:http://www.cnblogs.com/spring87/p/4853560.html