Android部分音频加载异常:‘File not found’及加载卡顿问题
问题原因分析
1. 部分文件触发“File not found”提示
- Scoped Storage 路径兼容问题:Android 10(API 29)及以上采用Scoped Storage机制,通过文件选择器获取的Uri无法直接转换为真实的本地文件路径,直接用
File(audioPath).exists()会返回false,触发该提示。 - 权限缺失:未正确申请或授予存储读取权限(Android 13+需
READ_MEDIA_AUDIO,低版本需READ_EXTERNAL_STORAGE),导致应用无法访问目标音频文件。 - 路径传递错误:从文件选择器获取路径时逻辑出错,传递了无效的路径字符串,导致
File对象无法定位到真实文件。
2. 6.5MB MP3加载弹窗持续显示不消失
- 成功分支未关闭弹窗:原代码中,当
loadAudio和loadVisualizer执行成功且无异常时,未调用closeProcessDiaglog(),导致弹窗一直处于显示状态。 - 耗时操作阻塞主线程:
loadAudio和loadVisualizer属于耗时操作(读取音频文件、解析音频数据),直接在主线程执行会阻塞UI线程,不仅弹窗无法关闭,还可能引发ANR(应用无响应)。 - 异常捕获不完整:如果
SoundController内部出现未被Exception覆盖的异常(如某些RuntimeException子类),会导致流程中断,无法触发弹窗关闭逻辑。
解决办法
针对“File not found”问题
适配Scoped Storage
避免直接依赖本地文件路径,改用ContentResolver读取音频文件。如果SoundController支持,可直接传递Uri并通过输入流加载:// 示例:从文件选择器返回的Uri获取输入流 InputStream inputStream = getContentResolver().openInputStream(selectedUri); // 让SoundController支持通过InputStream加载音频 mSoundController.loadAudio(inputStream);确保权限正确配置
- 在Manifest中添加权限声明:
<!-- Android 12及以下版本 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+版本 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> - 在用户选择文件前,动态申请并确认权限已授予。
- 在Manifest中添加权限声明:
修正文件名截取逻辑
不要用固定长度截取文件名,改用lastIndexOf('.')处理,避免因文件名含多个点或后缀长度不符导致的后续逻辑错误:String s = audioFile.getName(); int dotIndex = s.lastIndexOf('.'); mFileName = dotIndex != -1 ? s.substring(0, dotIndex) : s;
针对弹窗不消失问题
补充成功分支的弹窗关闭逻辑
在try块执行完成后添加弹窗关闭调用:try { mSoundController.loadAudio(audioFile.getAbsolutePath()); mSoundController.loadVisualizer(visualizerView, false); mSoundController.loadVisualizer(visualizerReverseView, true); // 加载成功后关闭弹窗 closeProcessDiaglog(); } catch (Exception e) { Toast.makeText(getApplicationContext(), "Cannot load audio file", Toast.LENGTH_SHORT).show(); closeProcessDiaglog(); }将耗时操作移至子线程
使用子线程执行加载逻辑,避免阻塞主线程,完成后切换回主线程更新UI:showProcessDialog(); new Thread(() -> { try { mSoundController.loadAudio(audioFile.getAbsolutePath()); mSoundController.loadVisualizer(visualizerView, false); mSoundController.loadVisualizer(visualizerReverseView, true); // 回到主线程关闭弹窗 runOnUiThread(this::closeProcessDiaglog); } catch (Exception e) { runOnUiThread(() -> { Toast.makeText(getApplicationContext(), "Cannot load audio file: " + e.getMessage(), Toast.LENGTH_SHORT).show(); closeProcessDiaglog(); }); } }).start();完善异常捕获范围
检查SoundController的loadAudio和loadVisualizer方法,确保所有可能的异常都被抛出或内部处理,避免未捕获异常导致流程中断。
内容的提问来源于stack exchange,提问作者DannyRoy
相关产品推荐
相关产品推荐

