Android SoundPool仅首次调用可播放声音,后续无输出问题求助
问题根因
- 错误使用资源ID作为播放ID:
SoundPool.load()方法执行后会返回专属的播放ID,你直接将资源IDR.raw.boo赋值给soundId用于播放是完全错误的,首次能播放属于偶发巧合。 - 未等待异步加载完成就调用播放:
load()是异步操作,代码中触发加载后立刻执行play(),绝大多数场景下资源未加载完成,会直接触发播放失败。 - 资源泄漏导致音频通道被占满:每次调用
playThatSound都会新建一个SoundPool实例,且使用完成后没有调用release()释放底层音频资源,多次调用后系统分配的音频资源被耗尽,自然无法再播放声音,必须重启设备或重装应用才能释放被占的资源。
修复方案
核心优化逻辑
- 全局仅初始化一次
SoundPool实例,不要每次播放都重复创建 - 提前加载音频资源,使用
load()方法返回的ID作为播放凭证 - 页面/应用销毁时主动释放
SoundPool资源 - 可选配置加载完成监听器,确保资源加载完成后再执行播放
修复后代码示例
import android.media.AudioAttributes import android.media.SoundPool // 全局SoundPool实例,建议在Activity/ViewModel初始化阶段创建 private lateinit var soundPool: SoundPool // 存储音频标识与对应加载完成的播放ID private val soundCache = hashMapOf<String, Int>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 使用官方推荐的Builder方式初始化SoundPool,兼容Android 5.0+系统 val audioAttrs = AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .build() soundPool = SoundPool.Builder() .setMaxStreams(6) .setAudioAttributes(audioAttrs) .build() // 提前加载所需音频,保存返回的播放ID soundCache["boo"] = soundPool.load(baseContext, R.raw.boo, 1) // 可选配置加载完成监听,避免未加载完成就播放 soundPool.setOnLoadCompleteListener { _, _, status -> if (status == 0) { // 音频加载完成,可正常调用播放方法 } } } private fun playThatSound(sound: String) { val playId = soundCache[sound] ?: return soundPool.play(playId, 1F, 1F, 0, 0, 1F) } // 页面销毁时主动释放资源 override fun onDestroy() { super.onDestroy() soundPool.release() }
额外注意
SoundPool本身设计用于播放短音效,官方推荐音频大小不超过100KB、时长不超过10s,你当前使用的213KB的mp3可以先做压缩处理,避免出现加载异常。
内容的提问来源于stack exchange,提问作者LastCard1440
相关产品推荐
相关产品推荐

