Android 11设备出现java.lang.IllegalArgumentException存储设备查找异常求助
Android 11下存储设备检测崩溃的解决方法
问题概述
在Android 11设备上启动应用时,SplashActivity触发崩溃,错误堆栈显示java.lang.IllegalArgumentException: Failed to find storage device at null,该错误由Environment.isExternalStorageRemovable(file)方法抛出,且网上相关排查信息极少。
错误原因分析
getExternalCacheDirs()返回null元素:部分Android 11设备的系统实现中,Context.getExternalCacheDirs()返回的数组可能包含null项,代表无效的存储路径。- 未做null校验直接传参:原代码未检查循环中的
file是否为null,直接传入Environment.isExternalStorageRemovable(),该方法在参数为null时会抛出IllegalArgumentException。 - 异常捕获范围不足:原代码仅捕获NullPointerException,未覆盖IllegalArgumentException,导致崩溃无法被拦截。
解决方案
核心修改点
- 遍历存储路径时先过滤null项
- 扩展异常捕获范围,覆盖IllegalArgumentException
- 对
getExternalCacheDir()的返回值做null校验,避免后续StatFs初始化崩溃
修改后的代码
void initSaveDataFolder() { if (SecurityPreferences.getAutoChosseFolder()) { File[] externalCacheDirs = App.get().getExternalCacheDirs(); // 先判断数组是否为空 if (externalCacheDirs != null) { for (File file : externalCacheDirs) { // 跳过null的存储路径 if (file == null) { continue; } try { if (Environment.isExternalStorageRemovable(file)) { StatFs stat = new StatFs(file.getAbsolutePath()); long bytesAvailableInSdCard = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks(); // 检查内部缓存目录是否有效 File internalCacheDir = App.get().getExternalCacheDir(); if (internalCacheDir == null) { SecurityPreferences.setIsSaveDataOnUsb(false); break; } StatFs stat2 = new StatFs(internalCacheDir.getAbsolutePath()); long bytesAvailableInInternalMemory = (long) stat2.getBlockSize() * (long) stat2.getAvailableBlocks(); SecurityPreferences.setIsSaveDataOnUsb(bytesAvailableInSdCard > bytesAvailableInInternalMemory); System.out.println("memoryes is " + bytesAvailableInSdCard + " " + bytesAvailableInInternalMemory); SecurityPreferences.saveAutoChosseFolder(true); break; } } catch (NullPointerException | IllegalArgumentException e) { // 同时捕获空指针和非法参数异常 SecurityPreferences.setIsSaveDataOnUsb(false); break; } } } else { // 当存储路径数组为空时,默认保存到内部存储 SecurityPreferences.setIsSaveDataOnUsb(false); } } }
权限优化建议
原权限声明中的READ_INTERNAL_STORAGE是多余的,Android应用默认拥有内部存储的读写权限,可移除该权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
内容的提问来源于stack exchange,提问作者pavkabrika
相关产品推荐
相关产品推荐

