基于Android系统对存储卡访问的各种特性,在充分保证基线的产品交互体验前提下,定义Android APP各业务开发中的可选存储路径,对应存储特性,各自适合存储文件范围和存储路径格式规范。
存储类型根路径特性存储文件范围业务路径格式内置数据分区 /data/..//files/ (对应:Context.getFilesDir())1.APP被安装时系统分配在data分区上的存储路径;2.APP访问不需要申请权限;APP私有,安全性最高;3.(非root或非共享UID)其它APP无权访问4.files和cache的区别:cache存储偏临时性的文件,在系统存储空间紧张时会被系统auto clean,应用设置中“清理缓存”会清理掉cache内文件;5.APP卸载时或“清理数据”时,此2种路径下的所有文件都会被系统自动清理;1.数据文件体积小(KB级别);2.运行时只能在data区加载的文件(如:动态下载的so库,插件apk或hotfix Dex文件等)3.安全性要求高的私密性文件;4.记录方便用户继续使用的历史行为数据,不希望被频繁重置到默认值的数据文件;各存储类型根路径下各业务相对路径格式:
.////,
1.APP内各业务统一路径标准后,为了避免业务间冲突,请各业务找基线APP申请和注册,插件的还涉及的注册,由各业务内部自行分配;但要严格根据存储特性和适合的文件范围选择存储路径;和是可选的;
2.各一级业务存储路径层级尽量不要超过3级,层次越深,遍历计算各级文件大小和删除时效率越低;
3.示例:
基线:./app
:
下载:./app/download/
播放器:./app/player/
泡泡:./paopao
插件: ./plugins
./plugins//
...
/data/..//cache/ (对应:Context.getCacheDir())1.文件体积小(KB级别);2.被频繁删除或重置后不影响用户历史状态功能的文件;3.存储数据安全性相对较高,不希望被第三方获取到的临时文件内置存储卡(或分区)(APP私有存储路径)/
Android/data//files/
(对应:Context.getExternalFilesDir())
1.系统为每个APP分配的基于不可插拔内置存储卡(或分区)的路径;2.APP私有的在存储卡上的空间,读写不需要特殊权限;3. 三方应用在获取到存储卡动态权限后可以读写该目录下文件,在存储安全性相比data区要低;4.files和cache的区别:cache存储偏临时性的文件,在系统存储空间紧张时会被系统auto clean,应用设置中“清理缓存”会清理掉cache内文件;5.APP卸载时或“清理数据”时,此2种路径下的所有文件都会被系统自动清理;1.存储体积较大的文件(例如:分发或自动更新的APK,下载的视频类文件,图片,ZIP压缩包等体积较大的文件);2.存储对安全和隐私性要求不高的文件;
3.没有单独的编辑删除入口,频繁删除或重置后不影响用户历史状态功能的文件放在cache目录中;
/
Android/data//cache/ (对应:Context.getExternalCacheDir())
存储卡非APP私有存储路径存储卡上非APP私有存储的其它路径(包括内置或可插拔的外置存储卡的非APP私有存储路径)1.Android 6.0+和部分OEM定制6.0-系统要动态申请存储卡读写权限,用户授权后才能读写;2.可插拔存储卡被移除后就数据无法访问;
3.非系统指定的APP私有路径,卸载APP或清除数据时,对应的数据不会被清除,持久性强;
4.放置到公共存储卡上,其实更容易被工具类APP清理缓存时引导用户做清理,
因涉及用户动态权限,卸载APP后无法自动清理干净,一般不建议在此类路径下存储文件,有特殊需求的需要提出来Review审核 不建议使用的存储路径,暂时不做规范SharedPreferences/data/..//shared_prefs/存储SharedPreferences文件存储全局性的开关,基类型的键值对数据涉及历史数据兼容性,此类数据存储体积上相对较小,暂时不做清理和统一要求;但需要业务内定期静态清理废弃的字段或表;单个表添加的数据项得设置上限值(一般1000条以内),做LRU替换Databse/data/..//databases/存储APP内基于系统Sqlite数据库存储的存储按数据库表格式访问的数据注:Android APP内各业务存储路径汇总表
2. Android APP统一访问存储卡路径的API根据第1节的介绍,基线APP内各业务一般只需要在内置数据区和存储卡APP私有路径上存取文件或数据,按基线APP中运行的业务特性提供不同的根路径获取API
1>基线维护的所有业务,或以aar,jar等依赖基线基础库接入基线的业务,使用基线基础库提供的适配层API(便于在Android新系统或定制机型上存储特性变更时,由基线APP基础库修改API内部逻辑做兼容)
内置数据区files根路径: File getInternalDataFilesDir(Context mContext, String subFolder);
内置数据区cache根路径:File getInternalDataCacheDir(Context mContext, String subFolder);
内置存储卡APP私有存储files根路径:File getInternalStorageFilesDir(Context mContext, String subFolder)
内置存储卡APP私有存储cache根路径:File getInternalStorageCacheDir(Context mContext, String subFolder)
注:以上API细节定义和说明参考wiki:Android存储介绍及API定义
2>基线对接的native库,由native提供API和接收路径参数,按照第1节中描述的存储特性,由基线APP层传递相应的根路径给native业务;
3>独立不依赖基线APP基础库的业务按照当前系统API来获取各自存储根路径(Android新系统或厂商定制系统上存储特性变更时,自行解决兼容性)
内置数据区files根路径:Context.getFilesDir()
内置数据区cache根路径:Context.getExternalCacheDir()
内置存储卡APP私有存储files根路径:Context.getExternalFilesDir()
内置存储卡APP私有存储cache根路径:Context.getExternalCacheDir()
4>垂直插件业务:各个插件按照3>中独立业务形式使用API,但插件中心会Hook Context中4个API来锁定根路径(对应到基线基础库的4个API上的根路径);
3.缓存清理规范用户在基线APP的“清理缓存”入口触发清理时,可以提供2个层次的清理选项
1.自动清理
临时数据:图片,网络请求的缓存临时数据(如:okhttp,fresco下载缓存的文件),直接删除后对用户体验影响可以忽略,直接扫描后清理;
2.深度清理
1>自动扫描清理cache目录:按第1节规范的路径,接入基线APP的按要求统一存放路径,对数据分区和内置存储卡APP私有目录的cache目录和各级子目录(非白名单路径)下的文件直接进行清理,静默删除,不需要用户确认(类似于系统应用设置中“清理缓存”操作);
白名单路径:存放在cache目录下,删除后影响用户下次操作体验,删除后重复下载耗费流量,或其它特殊需求目录或文件;需要各业务找基线技术和产品申请配置白名单,白名单支持云端动态更新,白名单以相对路径中或名称匹配,不能直接配置 为白名单(避免不被删除的缓存文件范围过大);
2> 用户交互式清理:对files路径或各级子路径,做扫描,扫描出的文件和目录不直接删除,UI上展示出“文件用途,删除后的影响,文件大小”等信息,由用户自主选择和确认后删除; 各业务产品自己定义交互提示信息和涉及的文件路径范围;
3. 技术接口
1>基线业务,泡泡,Native库等业务,由基线APP在临时kill掉主进程,启独立子进程删除对应文件,删除后自动重启APP(参考地区模式切换的产品形态,产品定义必要的交互提示)效果上类似与系统应用设置中“清除数据”;独立业务可以提供独立清理API给基线APP调用清理对应文件,但各业务要确保文件能删除干净;
2>各插件业务的清理,由基线的插件中心统一做清理。
注:各业务的SharedPreferences,数据库,或其他独立文件中有记录或依赖被删除文件的,请自行内部判断检查文件被删除后可能导致业务逻辑异常的情况
参考:
1,Android官方文档对数据存储说明:Data Storage
2.基线APP实践和测试总结的存储特性:Android存储介绍及API定义
3.stackoverflow :when to clear the cache dir in Android