赞
踩
首先,App在手机上保存文件或者缓存数据时,应该遵守以下几点:
1、不要随意占用用户的内置存储。
2、不要随意在SD卡上新建目录,应该放置自己应用包名对应的扩展存储目录下,卸载App时可以被自动清除。
3、对占用的磁盘空间有上限,并按照一定的策略进行清除。
Android系统分为内部存储和外部存储,内部存储是手机系统自带的存储,一般空间都比较小,外部存储一般是SD卡的存储,空间一般都比较大,但不一定可用或者剩余空间可能不足。一般我们存储内容都会放在外部存储空间里。使用过程注意事项:
一般我们可以通过 Context 和 Environment 相关的方法获取文件存取的路径。
1)根目录
Environment.getDataDirectory(): /data
2)获取方式:
3)绝对路径
Environment.getDataDirectory(): /data //根目录
Context.getCacheDir(): /data/data/应用包名/cache
Context.getFilesDir(): /data/data/应用包名/files
Context.getFileStreamPath(""): /data/data/应用包名/files
Context.getFileStreamPath(“name”): /data/data/应用包名/files/name //name为子文件名
4)写权限:不需要申请
5)这是手机的内置存储,没有root的过的手机是无法用文件管理器之类的工具查看的。而且这些数据也会随着用户卸载App而被一起删除。这两个目录其实就对应着:
设置->应用->你的App->存储空间 下面的清除数据和清楚缓存。
1)根目录
Environment.getExternalStorageDirectory(): /storage/emulated/0
2)获取方式:
3)绝对路径
Environment.getExternalStorageDirectory(): /storage/emulated/0 //根目录
Context.getExternalCacheDir(): /storage/emulated/0/Android/data/com.learn.test/cache
Context.getExternalFilesDir(""): /storage/emulated/0/Android/data/com.learn.test/files
Context.getExternalFilesDir(“test”): /storage/emulated/0/Android/data/com.learn.test/files/test
Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES): /storage/emulated/0/Android/data/com.learn.test/files/Pictures //type为文件类型
4)写权限:
<uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE” />
<uses-permission android:name=“android.permission.READ_EXTERNAL_STORAGE” />
API < 19:需要申请
API >= 19:不需要申请
从 API 19 / Andorid 4.4 / KITKAT 开始,不再需要显式声明这两个权限,除非要读写其他应用的应用数据($appDataDir)
5)既然是SD卡上的目录,那么是可以被其他的应用读取到的,所以这个目录下,不应该存放用户的敏感信息。同上面一样的,这里的文件会随着App卸载而被删除,也可以由用户手动在设置界面里面清除。
1)获取方式
2)绝对路径:SDCard/你设置的文件夹名字/
Environment.getExternalStorageDirectory(): /storage/emulated/0
Environment.getExternalStoragePublicDirectory(""): /storage/emulated/0
Environment.getExternalStoragePublicDirectory(“test”): /storage/emulated/0/test
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES): /storage/emulated/0/Pictures
3)写权限:需要申请
4)这些目录的内容不会随着应用的卸载而消失,如果我们的App需要存储一些公共的文件,甚至希望下载下来的文件即使在我们的App被删除之后,还可以被其他App使用,那么就可以使用这个目录。这个目录是始终需要申请SD写入权限的。
我们可以在外部存储上新建任意文件夹,不过在6.0及之后的系统需要动态申请权限
1)判断sd卡是否可用
/**
* Check if the primary "external" storage device is available.
*/
public static boolean hasSDCardMounted() {
String state = Environment.getExternalStorageState();
if (state != null && state.equals(Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}
2)Android6.0以上动态申请权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String[] permissions = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
if (checkPermission(act)) {
act.requestPermissions(permissions, REQUEST_CODE_PERMISSION_STORAGE);
}
private static boolean checkPermission(Activity act) {
return ((act.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|| (act.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED));
3)一个完整的判断参考
if ((Build.VERSION.SDK_INT >= 19 || PermissionChecker.checkCallingOrSelfPermission(activity,
"android.permission.WRITE_EXTERNAL_STORAGE") == PermissionChecker.PERMISSION_GRANTED)
&& Environment.getExternalStorageState().equals("mounted")
&& external != null) {
sdCardPath = external.getAbsolutePath();
}
如果仅仅是做了简单的图片缓存工作,那么我们应该把图片缓存放到/data/data/应用包名/cache/或者SDCard/Android/data/应用包名/cache/,因为在6.0系统(API > 23)时,不需要申请权限就可以向这两个目录写入文件。而且/data/data/应用包名/cache/目录,是内置存储的应用私有缓存目录,在系统空间不够时还会被自动清除,对于图片缓存来讲也是一个不错的管理策略,不过谷歌建议我们最好还是自己实现缓存清除管理,例如用DiskLruCache。
实际上我们可以在API >= 19(不一定非要大于23)时,就可以在不需要申请权限的情况下把文件放到这两个目录了。如果开发的时候足够规范,即使在API < 19时,我们申请到写入权限后,我们也应该手动创建和前面相同的目录,使得应用存储数据目录统一化。
为了兼容API < 19,会在AndroidManifest.xml文件里注册WRITE_EXTERNAL_STORAGE,这时当App运行在一台6.0的设备时,即使你的App全程都没有调用requestPermissons来申请权限,用户还是可以在Android6.0系统上 进入设置->应用->你的App->权限里面,取消存储空间这一个权限。记住是运行在6.0系统的机器上,这是关键,因为低于6.0的系统根本没有这个设置。只要在manifest里面注册了,就可以动态取消之,此时你的图片在6.0机器上也就没法缓存喽。
解决:
将AndroidManifest.xml文件中的
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
改为
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"/>
表示只在API <= 18时,才申请WRITE_EXTERNAL_STORAGE权限。这样用户就无法在Android6.0系统的设置下面看到存储空间权限的开关,当然也就无法关闭它了。
对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。
要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类。
private static Uri getFileUri(Context context, File file, Intent intent) {
Uri uri;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
uri = Uri.fromFile(file);
} else {
uri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
return uri;
}
参考:
数据和文件存储概览
Android存储及getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()区别
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。