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 ...
随机推荐
- 【C++基础】 各种“虚”总结(ing...)
虚基类,虚函数,虚析构函数,纯虚函数,虚函数表(待补充) 一.虚基类——在继承方式(public / private)之前加 virtual class B1: virtual public B0{} ...
- 【HTTP】Fiddler(一) - Fiddler简介和使用
1.为什么是Fiddler? 抓包工具有很多,小到最常用的web调试工具firebug,达到通用的强大的抓包工具wireshark.为什么使用fiddler?原因如下: a.Firebug虽然可以抓包 ...
- POJ3122Pie(二分)
http://poj.org/problem?id=3122 题意 :这个题最主要的就是审题要仔细,翻译不要漏句子.题目讲的是我要过生日,要给好友分馅饼(还有自己也想要一块),怕引起不公,所以每个人大 ...
- hdu 3537 Daizhenyang's Coin 博弈论
详见:http://www.cnblogs.com/xin-hua/p/3255985.html 约束条件6 代码如下: #include<iostream> #include<st ...
- EL表达式对数组、集合操作
el表达式是通过${key}的方式获取对象中的值.在el表达式中有如下几个隐含的对象,pageScope,requestSope,sessionScope,applicationScope,如果要取$ ...
- 李洪强漫谈iOS开发[C语言-013]-常量
// // main.m // 09 - 常量 // // Created by 李洪强 on 16/7/17. // Copyright © 2016年 李洪强. All rights re ...
- [itint5]跳马问题加强版
http://www.itint5.com/oj/#12 首先由跳马问题一,就是普通的日字型跳法,那么在无限棋盘上,任何点都是可达的.证法是先推出可以由(0,0)到(0,1),那么由对称型等可知任何点 ...
- thinkphp 分组
分组 配置项: // 开启分组 'APP_GROUP_LIST'=>'Home,Admin', // 默认分组 'DEFAULT_GROUP'=>'Home', 涉及分组: 配置文件分组, ...
- SQLite入门与分析(三)---内核概述(1)
写在前面:从本章开始,我们开始进入SQLite的内核.为了能更好的理解SQLite,我先从总的结构上讨论一下内核,从全局把握SQLite很重要.SQLite的内核实现不是很难,但是也不是很简单.总的来 ...
- 锋利的JQuery-Jquery选择器
1.css选择器 标签选择器:a{...} id选择器:#note{...} 类选择器:div.note{..}..dream{...} 群组选择器:td,p,div,a{...} 后代选择器: #l ...