Android开发中SoundPool加载音频失败,点击按钮无法播放问题求助
问题定位
- SoundPool的
load()方法为异步操作,你在onCreateView中触发加载后直接在点击事件中调用播放逻辑,此时音频还未完成加载,是出现Unable to load sample报错的核心原因。 - 点击事件中调用
play()后立刻执行了autoPause(),就算音频加载完成,刚启动播放就会被暂停,无法听到声音。 - 未设置SoundPool加载完成监听,无法确认音频加载状态,也无法在加载完成后再执行播放操作。
- 需要确认
res/raw目录下的音频文件命名是否和R.raw.soundbite_mpthree完全匹配:Android资源名仅支持小写字母、数字和下划线,不需要添加文件后缀,若你的文件实际为soundbite_mpthree.mp3才对应该ID,命名不匹配也会触发加载失败。
修复方案
- 新增布尔变量标记音频加载状态,避免未加载完成时触发播放
- 给SoundPool设置加载完成监听器,加载成功后更新状态标记
- 移除点击事件中多余的
autoPause()调用 - 点击按钮时先校验音频加载状态,再执行播放逻辑
- 在Fragment销毁时释放SoundPool资源,避免内存泄漏
修复后代码
public class LauncherFragment extends Fragment { private FragmentLauncherBinding binding; private SoundPool soundPool; private int launcher; // 标记音频是否加载完成 private boolean isSoundLoaded = false; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { binding = FragmentLauncherBinding.inflate(inflater, container, false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { AudioAttributes audioAttributes = new AudioAttributes .Builder() .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .build(); soundPool = new SoundPool .Builder() .setMaxStreams(3) .setAudioAttributes(audioAttributes) .build(); } else { soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0); } // 设置加载完成监听 soundPool.setOnLoadCompleteListener((soundPool, sampleId, status) -> { if (status == 0) { isSoundLoaded = true; } }); try { launcher = soundPool.load(requireContext(), R.raw.soundbite_mpthree, 1); } catch (Exception e) { Toast.makeText(requireContext(), "Load failed", Toast.LENGTH_SHORT).show(); } return binding.getRoot(); } public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); binding.launcherButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 仅在加载完成后播放 if (isSoundLoaded) { soundPool.play(launcher, 1, 1, 0, 0, 1); } NavHostFragment.findNavController(LauncherFragment.this) .navigate(R.id.action_LauncherFragment_to_ActionFragment); } }); } // 销毁时释放资源 @Override public void onDestroyView() { super.onDestroyView(); soundPool.release(); soundPool = null; binding = null; } }
内容的提问来源于stack exchange,提问作者BMG
相关产品推荐
相关产品推荐

