问题:
我们在项目中会将崩溃日志保存在本地,方便处理异常,但是我发现在android11版本的设备上会出现 Operation not permitted 异常,导致文件保存失败。
问题分析:
- 权限没开通?
android 11虽然开启了强制分区存储,但是只是针对targetSdk >= 30的情况,而本应用的targetSdk为26,并未开启强制分区存储
问题原因:
因为我使用当前时间(yyyy-MM-dd HH:mm:ss)作为文件名,而当前时间(yyyy-MM-dd HH:mm:ss)名中带有":",导致文件创建失败。并且不只是":",许多其他的字符如上图都属于公共空间文件名的不合法字符,但是在应用的私有空间是不存在这个问题的,这可能是由于在分区存储后公有空间和私有空间文件访问走的是两套机制,访问公有空间要通过MediaStore,但是访问私有空间并不需要,自然就没有了这个文件名称的校验。
private static boolean isValidFatFilenameChar(char c){
if ((0x00<= c &&c<= 0x1f)){
return false;
}
switch (c) {
case '"':
case '*':
case '/':
case ':':
case '<':
case '>':
case '?':
case '\\':
case 0x7F:
return false;
default:
return true;
}
为了验证这个问题,打开android 11 的文件管理器,尝试在手机外部存储公共空间修改文件名加入":",提示特殊字符无效。
查看android 10的代码,未发现如上流程,也说明了为什么这个bug只和android 11有关。
问题解决:
- 将日志路径设置到应用的私有空间
- 修改文件名称,把特殊字符替换掉