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以后的版本的更多相关文章

  1. Android 下载文件及写入SD卡

    Android 下载文件及写入SD卡,实例代码 <?xml version="1.0" encoding="utf-8"?> <LinearL ...

  2. android文件缓存,并SD卡创建目录未能解决和bitmap内存溢出解决

    1.相关代码: 加入权限: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ...

  3. [android] 分析setting源代码获取SD卡大小

    保存文件到sd卡需要判断sd卡的大小,通过查看android系统的自带应用的源代码,得到方法,sdk下面的source是sdk的源代码,包含的是android.Jar下面的所有class的源代码.在a ...

  4. 【译】如何在 Android 5.0 上获取 SD卡 的读写权限

    因为最近项目需要,涉及到 SD卡 的读写操作,然而申请 <!-- 读写权限 --> <uses-permission android:name="android.permi ...

  5. File存对象--android 的File存储到SD卡();

    方法1:android File存对象--File存储到SD卡(); 1.保存对象到本地或SD卡需要注意的是,要保存的对象(OAuthV1)一定要实现了Serializable接口.实现了Serial ...

  6. Android中使用SQLiteOpenHelper管理SD卡中的数据库

    使用Android中自带的SQLiteOpenHelper可以完成数据库的创建与管理,但有两点局限: (1)数据库创建在内存卡中,大小受限,创建位置位于/data/data/应用程序名/databas ...

  7. android学习笔记47——读写SD卡上的文件

    读写SD卡上的文件 通过Context的openFileInput.openFileOutput来打开文件输入流.输出流时,程序打开的都是应用程序的数据文件夹里的文件,其存储的文件大小可能都比较有限- ...

  8. 6、android 普通日志输出到SD卡

    这是本人见过写博文最负责的一个人: http://www.crifan.com/android_try_use_android_logging_log4j_to_output_log_to_sd_ca ...

  9. Android 将文件保存到SD卡中

    ①写文件到sd卡中需要获得权限,在AndroidManifest.xml中添加如下权限: <uses-permission android:name="android.permissi ...

随机推荐

  1. eclipse进行开发

    最近在用eclipse进行开发的时候遇到了一个很奇怪的问题,其实这个问题很早以前就遇到了只是苦于一直没有需找到答案.直到今天又遇到了,才觉得这真是个很实用很使用的功能,所以分享给大家,希望对大家有帮助 ...

  2. 2013 Multi-University Training Contest 4 Who's Aunt Zhang

    看题就知道要用polya,但是当时没做出来,还是不是很熟悉polya!!! 总共有24种置换: 1. 不做任何旋转 K ^ (54 + 12 + 8) 2. 绕相对面中心的轴转 1) 90度 K ^ ...

  3. highcharts 切换

    <!doctype html> <html lang="en"> <head> <script type="text/javas ...

  4. xcode 树形管理 cocos2d-x的资源

    把资源以目录的形式加入xcode中, 同时, 在加入时, 选择"Create Folder References for any  added folders", 而不是默认的&q ...

  5. 【mysql的编程专题⑥】视图

    视图是表的一个映射,是一张虚表,在结构上视图和普通的表没什么区别,一样可以用sql语句来增删改查; 视图创建后是一直存在数据库内 操作 创建视图 语法 CREATE [ALGORITHM]={UNDE ...

  6. 我的JAVA基础学习史1

    又开始学习了..很是兴奋呢~~~~ 本来是想学安卓的,但是安卓的视频课程中,第一阶段是环境,第二阶段是JAVA基础(讲课的这个老师真是在念课本,但是实在没有办法,没找到更好.更完整的资料了). 虽然以 ...

  7. xp宿主机和VMware下Ubuntu12.04共享文件夹

    VMware下Windows与Linux共享文件的方法有很多,比如Samba等等,我这里介绍简单地通过设置VMware来达到共享的目的. 打开VMware的设置,在"options" ...

  8. MySQL优化器 limit影响的case

    测试的用例中,因为limit的大小不同,而产生了完全不同的执行计划: 1. 测试case: create table t1 ( f1 ) not null, f2 ) not null, f3 ) n ...

  9. ASP.NET的六种验证控件的使用

    C# 中的验证控件分为一下六种 :1 CompareValidator:比较验证,两个字段的值是否相等,比如判断用户输入的密码和确认密码是否一致,则可以用改控件: 2 CustomValidator ...

  10. LCA与RMQ

    一.什么是LCA? LCA:Least Common Ancestors(最近公共祖先),对于一棵有根树T的任意两个节点u,v,求出LCA(T, u, v),即离跟最远的节点x,使得x同时是u和v的祖 ...