Jetpack Compose 给APP添加声音(点击音效/背景音乐)
在 Jetpack Compose 中播放声音,最常用、最简单 的方案是使用 Android 原生的 SoundPool (短音效,如点击、弹窗)和 MediaPlayer(长音频,如背景音乐)。
我给你整理了开箱即用的完整代码,直接复制就能用。
第一步:准备音频文件
- 在
res目录下创建 raw 文件夹(右键 res → New → Android Resource Directory → Resource type 选raw) - 把你的音频文件(
mp3/wav格式)放进去,例如:click_sound.wavbg_music.mp3
文件名只能是:小写字母、数字、下划线
方案1:短音效(点击按钮/交互)SoundPool ✅
适合点击、弹窗、反馈等短音频,延迟低、性能好。
完整 Compose 代码
kotlin
import android.media.SoundPool
import android.content.Context
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
// 播放点击音效
@Composable
fun PlaySoundScreen() {
val context = LocalContext.current
// 1. 初始化 SoundPool
val soundPool = remember {
SoundPool.Builder()
.setMaxStreams(1) // 同时播放的音频数量
.build()
}
// 2. 加载音频(只加载一次)
val clickSoundId = remember {
soundPool.load(context, R.raw.click_sound, 1)
}
// 3. 页面销毁时释放资源
DisposableEffect(Unit) {
onDispose {
soundPool.release()
}
}
// 页面布局
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Button(onClick = {
// 播放音效:(soundID, 左音量, 右音量, 优先级, 循环, 播放速度)
soundPool.play(clickSoundId, 1f, 1f, 1, 0, 1f)
}) {
Text("点击播放音效")
}
}
}
参数说明
1f, 1f:左右音量(0.0 ~ 1.0)0:循环次数(0=不循环,-1=无限循环)1f:播放速度(0.5~2.0)
方案2:长音频(背景音乐)MediaPlayer ✅
适合背景音乐、语音播报等长音频。
完整 Compose 代码
kotlin
import android.media.MediaPlayer
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
// 播放背景音乐
@Composable
fun PlayBackgroundMusicScreen() {
val context = LocalContext.current
// 初始化 MediaPlayer
val mediaPlayer = remember {
MediaPlayer.create(context, R.raw.bg_music).apply {
isLooping = true // 循环播放
setVolume(0.5f, 0.5f) // 音量
}
}
// 页面销毁时停止并释放
DisposableEffect(Unit) {
onDispose {
mediaPlayer.stop()
mediaPlayer.release()
}
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Button(onClick = { mediaPlayer.start() }) {
Text("播放背景音乐")
}
Button(onClick = { mediaPlayer.pause() }) {
Text("暂停背景音乐")
}
}
}
方案3:全局点击音效(整个APP点击都发声)
如果你想所有按钮点击都自动播放音效 ,可以封装一个自定义点击修饰符:
kotlin
import androidx.compose.foundation.clickable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import android.media.SoundPool
// 全局带音效的点击
@Composable
fun Modifier.clickWithSound(
soundId: Int,
soundPool: SoundPool,
onClick: () -> Unit
): Modifier {
return this.clickable {
soundPool.play(soundId, 1f, 1f, 1, 0, 1f)
onClick()
}
}
使用:
kotlin
Text(
text = "点我有声音",
modifier = Modifier.clickWithSound(clickSoundId, soundPool) {
// 你的点击逻辑
}
)
常见问题
-
音频没声音?
- 检查文件是否放在
res/raw/下 - 检查音量是否打开
- 音频文件名必须小写
- 检查文件是否放在
-
报错资源找不到?
- 重建项目:Build → Clean Project → Rebuild Project
-
页面退出还在响?
- 必须用
DisposableEffect在页面销毁时release()释放音频
- 必须用
总结
- 短音效(点击) :用 SoundPool,延迟低
- 长音效(背景音乐) :用 MediaPlayer
- 音频文件放在
res/raw/ - 页面销毁必须释放资源,避免内存泄漏
需要我帮你把音效封装成一个工具类,让整个 APP 随便调用吗?