Android应用正确使用扩展SD卡,特别是安卓4.4以后的版本
Android 开发时如何正确获取使用扩展存储路径
在 2.x 版本中,Android设备都是单存储,第三方App写文件,必须申请 WRITE_EXTERNAL_STORAGE 权限;
在4.0之后,Android设备开始有了内置闪存,即 primary storage,并且可以外置SD卡,即 secondary external storage device;
WRITE_EXTERNAL_STORAGE 权限变成了仅仅控制 primary storage,同时引入了 WRITE_MEDIA_STORAGE 权限来控制secondary external storage device的操作。
到了Android 4.4 KitKat,WRITE_MEDIA_STORAGE 权限仅提供给系统应用,不再授予第三方App。
关于 secondary external storage device 的写操作也有了新规定。
Android的文档是这么写的:
Link: http://source.android.com/devices/tech/storage/index.html:
The WRITE_EXTERNAL_STORAGE permission must only grant write access to
the primary external storage on a device. Apps must not be allowed to
write to secondary external storage devices, except in their
package-specific directories as allowed by synthesized permissions.
Restricting writes in this way ensures the system can clean up files
when applications are uninstalled.
翻译:
WRITE_EXTERNAL_STORAGE 权限,仅仅用于授权用户写 primary external storage。对于secondary external storage devices,除了与自己包名相关的文件夹之外,应用程序不允许写secondary external storage devices的其它区域。这样限制的目的是为了在应用被卸载的时候这些外部文件能得到很好的清除。
举例来说,如果应用的包名是com.example.foo,那么外部存储上的Android/data/com.example.foo/文件夹就可随意访问,其他任何地方都不允许写,并且,存储在自己包名相关的文件夹的文件,当该应用被卸载时候也会随之被清除。
分情况来说:
只有外部存储的设备
这种设备一般是android4.0之前的,只有一个存储,不受这个规则限制,还是可以随便读写,但如果你刷了4.4系统,那么就只能写自己包名相关的文件夹了。 只有内部存储的设备
比如Nexus系列,sony L系列,不受这个规则限制,但是建议在自己的包名相关的文件夹写数据。 既有内部存储又有外部存储
需要遵守这个规定,不能在外部存储乱写了,需要在自己的包名相关的文件夹写数据。
Google做了这个限制后解决了这个问题:
随便一个App,都会在/sdcard、/sdcard1 上建一个目录,删了也会重新建,即使被卸载,也会留下一些垃圾文件。
但是,也产生了一个问题:
类似于视频、图像处理这种想在外部存储缓存大量音视频文件,并且App被卸载后还想保留的,就没办法了。
开发中应该怎么使用?
作为一个程序员,想必你也很讨厌App在SD卡根目录乱建目录吧,那就从我做起,来遵守Google的这一规定吧。
通过Context.getExternalFilesDir()方法可以获取到 SDCard/Android/data/{package_name}/files/ ,储存一些长时间保存的数据;
通过Context.getExternalCacheDir()方法可以获取到 SDCard/Android/data/{package_name}/cache/,储存临时缓存数据;
这两个目录分别对应 设置->应用->应用详情里面的”清除数据“与”清除缓存“选项。
一个获取外部存储Cache的例子:
/**
* 获取拓展存储Cache的绝对路径
* @param context
*/
public static String getExternalCacheDir(Context context) {
if (!isMounted())
return null; StringBuilder sb = new StringBuilder();
File file = context.getExternalCacheDir();
// In some case, even the sd card is mounted, getExternalCacheDir will return null may be it is nearly full.
if (file != null) {
sb.append(file.getAbsolutePath()).append(File.separator);
} else {
sb.append(Environment.getExternalStorageDirectory().getPath())
.append("/Android/data/").append(context.getPackageName())
.append("/cache/").append(File.separator).toString();
} return sb.toString();
}
Android应用正确使用扩展SD卡,特别是安卓4.4以后的版本的更多相关文章
- Android 下载文件及写入SD卡
Android 下载文件及写入SD卡,实例代码 <?xml version="1.0" encoding="utf-8"?> <LinearL ...
- android文件缓存,并SD卡创建目录未能解决和bitmap内存溢出解决
1.相关代码: 加入权限: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ...
- [android] 分析setting源代码获取SD卡大小
保存文件到sd卡需要判断sd卡的大小,通过查看android系统的自带应用的源代码,得到方法,sdk下面的source是sdk的源代码,包含的是android.Jar下面的所有class的源代码.在a ...
- 【译】如何在 Android 5.0 上获取 SD卡 的读写权限
因为最近项目需要,涉及到 SD卡 的读写操作,然而申请 <!-- 读写权限 --> <uses-permission android:name="android.permi ...
- File存对象--android 的File存储到SD卡();
方法1:android File存对象--File存储到SD卡(); 1.保存对象到本地或SD卡需要注意的是,要保存的对象(OAuthV1)一定要实现了Serializable接口.实现了Serial ...
- Android中使用SQLiteOpenHelper管理SD卡中的数据库
使用Android中自带的SQLiteOpenHelper可以完成数据库的创建与管理,但有两点局限: (1)数据库创建在内存卡中,大小受限,创建位置位于/data/data/应用程序名/databas ...
- android学习笔记47——读写SD卡上的文件
读写SD卡上的文件 通过Context的openFileInput.openFileOutput来打开文件输入流.输出流时,程序打开的都是应用程序的数据文件夹里的文件,其存储的文件大小可能都比较有限- ...
- 6、android 普通日志输出到SD卡
这是本人见过写博文最负责的一个人: http://www.crifan.com/android_try_use_android_logging_log4j_to_output_log_to_sd_ca ...
- Android 将文件保存到SD卡中
①写文件到sd卡中需要获得权限,在AndroidManifest.xml中添加如下权限: <uses-permission android:name="android.permissi ...
随机推荐
- Tiny6410 交叉编译helloworld程序
在工作目录下建立helloworld.c文件 #include <stdio.h> main() { printf("helloworld!\n"); } 保存关闭后. ...
- Hybrid App 和 React Native 开发那点事
简介:Hybrid App(混合模式移动应用)开发是指介于Web-app.Native-App这两者之间的一种开发模式,兼具「Native App 良好用户交互体验的优势」和「Web App 跨平台开 ...
- CodeForces 300A Array
http://codeforces.com/problemset/problem/300/A 题意 :给你n个数字,让你分成3组,第一组各个数之积要小于0,第二组要大于0,第三组要等于0,符合要求的答 ...
- HDU4714+三分
题意:给定N个点,每个点有初始位置和初始速度. 问:在哪个时刻 使得所有的点的最大距离值最小. 分析:一开始枚举两两之间的最大值,然后在最大值中求一个最小值...(WA:题意严重理解不清..) 由两点 ...
- linux踢人命令 pkill踢人用法
首先使用who命令查看在线用户,然后踢人. 强制踢人命令格式:pkill -kill -t tty 解释: pkill -kill -t 踢人命令 tty 所踢用户的TTY或者pts/x(x代表数字) ...
- codeforces #309 div1 D
求最小值最大显然是要二分 二分之后转换成了判定性问题 我们考虑哪些点一定不能选 显然是将所有可选点选中之后依然不满足条件的点不能选 那么我们不妨维护一个堆,每次取出堆顶看看是否满足条件 不满足条件就p ...
- perl杂项
perl -pi -e 's|googleapis.com|useso.com|g' `find ./ -type f` yingc@yingc:~/gcyin/test/thirdparty/ffm ...
- Frequent values && Ping pong
Frequent values 题意是不同颜色区间首尾相接,询问一个区间内同色区间的最长长度. 网上流行的做法,包括翻出来之前POJ的代码也是RMQ做法,对于序列上的每个数,记录该数向左和向右延续的最 ...
- oracle connect by 和start with
网上找了个例子 测试了一下 貌似明白了create table t2(root_id number,id number,name varchar(5),description varchar(10)) ...
- RabbitMQ消息队列(一): Detailed Introduction 详细介绍(转)
1. 历史 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有 ...