Android文件存储使用参考
可能遇到的问题
android系统自身自带有存储,另外也可以通过sd卡来扩充存储空间。前者好比pc中的硬盘,后者好移动硬盘。 前者空间较小,后者空间大,但后者不一定可用。 开发应用,处理本地数据存取时,可能会遇到这些问题:
- 需要判断sd卡是否可用: 占用过多机身内部存储,容易招致用户反感,优先将数据存放于sd卡;
应用数据存放路径,同其他应用应该保持一致,应用卸载时,清除数据:
- 标新立异在sd卡根目录建一个目录,招致用户反感
- 用户卸载应用后,残留目录或者数据在用户机器上,招致用户反感
需要判断两者的可用空间: sd卡存在时,可用空间反而小于机身内部存储,这时应该选用机身存储;
- 数据安全性,本应用数据不愿意被其他应用读写;
- 图片缓存等,不应该被扫描加入到用户相册等媒体库中去。
基本操作
使用外部存储,需要的权限,在
AndoridManifest.xml
中:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
从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;
}
}
存储的用量情况
根据系统用户不同,所能占用的存储空间大小也有不同
在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 Context.getFileStreamPath(""):
/data/data/com.srain.cube.sample/files Context.getFileStreamPath("file1"):
/data/data/com.srain.cube.sample/files/file1
外部存储:通过
Context.getExternalFilesDir(String type)
,type
为空字符串时获取.type
系统指定了几种类型:Environment.DIRECTORY_MUSIC
Environment.DIRECTORY_PICTURES
...
示例:
Context.getExternalCacheDirs():
/storage/sdcard0/Android/data/com.srain.cube.sample/files Context.getExternalFilesDir(Environment.DIRECTORY_MUSIC)
/storage/sdcard0/Android/data/com.srain.cube.sample/files/Music
$cacheDir / $filesDir
安全性在内部存储中,
$cacheDir
,$filesDir
是app安全的,其他应用无法读取本应用的数据,而外部存储则不是。在外部存储中,这两个文件夹其他应用程序也可访问。
在外部存储中,
$filesDir
中的媒体文件,不会被当做媒体扫描出来,加到媒体库中。$cacheDir / $filesDir
同级目录在内部存储中:通过
Context.getDir(String name, int mode)
可获取和$filesDir
/$cacheDir
同级的目录目录的命名规则为
app_ + name
, 通过mode可控制此目录为app私有还是其他app可读写。示例:
Context.getDir("dir1", MODE_PRIVATE):
Context.getDir: /data/data/com.srain.cube.sample/app_dir1
特别注意, 对于外部存储,获取
$cacheDir
或者$filesDir
及其下的路径在API level 8 以下,或者空间不足,相关的方法获路径为空时,需要自己构造。
@TargetApi(VERSION_CODES.FROYO)
public static File getExternalCacheDir(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO)) {
File path = context.getExternalCacheDir(); // In some case, even the sd card is mounted,
// getExternalCacheDir will return null
// may be it is nearly full.
if (path != null) {
return path;
}
} // Before Froyo or the path is null,
// we need to construct the external cache folder ourselves
final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/";
return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir);
}
- 数据缓存:
Android文件存储使用参考的更多相关文章
- Android 文件存储浅析
最近做的一个需求和文件存储有关系.由于之前没有系统梳理过,对文件存储方面的知识一直很懵懂.趁着周末有时间,赶紧梳理一波. 这首从网上找到的一张图,很好的概括了外部存储和内部存储. 下面我们再来具体介绍 ...
- android文件存储位置切换
最近有个需求,助手的google卫星地图和OpenCycleMap下载的离线地图数据,要能够在内置存储和外置存储空间之间切换,因为离线瓦片数据非常大,很多户外用户希望将这些文件存储在外置TF卡上,不占 ...
- Android文件存储
文件存储是Android中最基本的一种数据存储方式,它不读存储的内容进行任何的格式化处理,所有数据原封不动的保存在文件之中.如果想用文件存储的方式保存一些较为复杂的数据,就需要定义一套自己的格式规范, ...
- android: 文件存储
数据持久化就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑 关机的情况下,这些数据仍然不会丢失.保存在内存中的数据是处于瞬时状态的,而保存在 存储设备中的数据是处于持久状态的,持久化 ...
- 转:Android文件存储路径getFilesDir()与getExternalFilesDir的区别
作为一个开发者,我们经常需要通过缓存一些文件到SD卡中,常见的方式就是,通过: File sdCard = Environment.getExternalStorageDirectory(); 获取S ...
- android 文件存储&SharedPreferences
一.文件存储 文件存储主要是I/O流的操作,没什么好说的,需要注意的是保存文件的各个目录. 下面为常用的目录: public static File getInFileDir(Context cont ...
- 程序员带你学习安卓开发系列-Android文件存储
这是程序员带你学习安卓开发系列教程.本文章致力于面向对象程序员可以快速学习开发安卓技术. 上篇文章:.Net程序员快速学习安卓开发-布局和点击事件的写法 主要讲解了布局和点击事件的写法. 上篇文章补充 ...
- Android 文件存储 和 权限管理
转载请标明出处: :http://blog.csdn.net/huaiyiheyuan/article/details/52473984 android SD卡主要有两种存储方式 Internal . ...
- Android数据存储之Android 6.0运行时权限下文件存储的思考
前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以 ...
随机推荐
- AsyncTask详解
http://blog.csdn.net/liuhe688/article/details/6532519 在Android中实现异步任务机制有两种方式,Handler和AsyncTask. Hand ...
- 提高mindmanager 8的启动速度
提高mindmanager 8的启动速度一连串 发布于:2010-01-13 18:12不少人抱怨mindmanager 8的启动速度较慢,用以下办法配置一下就能解决:1.进入mindmanager ...
- 元素“Button”不是已知元素。原因可能是网站中存在编译错误,或者缺少web.config文件
最近开发的时候ASP控件都有波浪下划线,提示不是已知元素,搞得挺郁闷的.虽然不影响变异,不过就是不爽. 折腾N久...... 解决了,把FramWork平台换成3.5,问题解决,不知道为啥,求大神指点 ...
- 远程监控 – 应用程序运行状况测量 CSF 博客
在远程监控基础知识和故障排除中,我们探讨了 Windows Azure 平台提供的基础指标.信息源.工具和脚本,介绍了有关监控和应用程序运行状况的基本原则.我们演示了如何利用这些基本原则对在 Wind ...
- 图像处理库的比较:OpenCV,FreeImage,CImg,CxImage
1.对OpenCV 的印象:功能十分的强大,而且支持目前先进的图像处理技术,体系十分完善,操作手册很详细,手册首先给大家补计算机视觉的知识,几乎涵盖了近10年内的主流算法: 然后将图像格式和矩阵运算, ...
- VirtualBox详细教程
转自:http://bbs.kafan.cn/thread-358294-1-1.html 1.Sun xVM VirtualBox简介 VirtualBox官方网站:http://www.virtu ...
- android 开发代码被黑客破译有那么容易吗?
很多程序员辛辛苦苦开发出的android开发代码,很容易就被黑客翻译了. Google似乎也发现了这个问题,从SDK2.3开始我们可以看到在android-sdk-windows\tools\下面多了 ...
- Weinre - 远程调试工具
Weinre 代表Web Inspector Remote,是一种远程调试工具.借助于网络,可以在PC上直接调试运行在移动设备上的远程页面,中文意思是远程Web检查器,有了Wei ...
- Effective C++ 条款18
让接口easy被正确使用,不easy被误用 如题目,我们自己的程序接口是面向用户的,程序的目的不可是解决这个问题,并且要让用户easy使用.所以.必须保证我们的程序接口具有非常强的鲁棒性. 怎么保证接 ...
- 自定义Toast样式-两行文本居中显示
toast可以设置自定义的view和显示位置.下面是一个简单的例子,复杂些的就是改变其布局文件就可以了. /** * @author BMR * @ClassName: ToastWithTwoTex ...