当前位置: 首页 > news >正文

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();
}

 

相关文章:

  • 开源HYBUnicodeReadable日志显示Unicode中文
  • CKEditor在线编辑器增加一个自定义插件
  • 【转载】Tomcat 7.0.3x 启动慢并且遇到StackOverflowError的异常的解决办
  • ubuntu14.04 使用kvm安装win7系统
  • A successful Git branching model
  • ELK日志系统:Elasticsearch + Logstash + Kibana 搭建教程
  • centos制作yum源
  • android在假设绘制自己定义的bitmap,然后返回给ImageView
  • 通过读取excel文件生成sql语句
  • 指针知识梳理5-字符串与指针,程序内存总结
  • 使用360浏览器访问字体逆时针旋转90度的问题
  • Shell脚本实现自动修改IP地址
  • 参数的排列组合
  • 在当今快节奏的软件更迭当中,我们是否还需要进行系统的学习?
  • JSTL截取字符串
  • Apache Spark Streaming 使用实例
  • gitlab-ci配置详解(一)
  • GitUp, 你不可错过的秀外慧中的git工具
  • java小心机(3)| 浅析finalize()
  • js写一个简单的选项卡
  • PHP CLI应用的调试原理
  • php面试题 汇集2
  • SpringBoot几种定时任务的实现方式
  • Twitter赢在开放,三年创造奇迹
  • Vue 2.3、2.4 知识点小结
  • 诡异!React stopPropagation失灵
  • 基于webpack 的 vue 多页架构
  • 开源SQL-on-Hadoop系统一览
  • 前端之React实战:创建跨平台的项目架构
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 移动端解决方案学习记录
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • ​520就是要宠粉,你的心头书我买单
  • # include “ “ 和 # include < >两者的区别
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (C语言)二分查找 超详细
  • (LeetCode C++)盛最多水的容器
  • (差分)胡桃爱原石
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • .“空心村”成因分析及解决对策122344
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .net6+aspose.words导出word并转pdf
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • ::
  • @DataRedisTest测试redis从未如此丝滑
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——
  • [④ADRV902x]: Digital Filter Configuration(发射端)
  • [acm算法学习] 后缀数组SA
  • [AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现
  • [Avalon] Avalon中的Conditional Formatting.
  • [BZOJ1877][SDOI2009]晨跑[最大流+费用流]