kotlin:Jetpack Compose 给APP添加声音(点击音效/背景音乐)

Jetpack Compose 给APP添加声音(点击音效/背景音乐)

在 Jetpack Compose 中播放声音,最常用、最简单 的方案是使用 Android 原生的 SoundPool (短音效,如点击、弹窗)和 MediaPlayer(长音频,如背景音乐)。

我给你整理了开箱即用的完整代码,直接复制就能用。


第一步:准备音频文件

  1. 在 res 目录下创建 raw 文件夹(右键 res → New → Android Resource Directory → Resource type 选 raw)
  2. 把你的音频文件(mp3 / wav 格式)放进去,例如:
    • click_sound.wav
    • bg_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) {
        // 你的点击逻辑
    }
)

常见问题

  1. 音频没声音?

    • 检查文件是否放在 res/raw/ 下
    • 检查音量是否打开
    • 音频文件名必须小写
  2. 报错资源找不到?

    • 重建项目:Build → Clean Project → Rebuild Project
  3. 页面退出还在响?

    • 必须用 DisposableEffect 在页面销毁时 release() 释放音频

总结

  • 短音效(点击) :用 SoundPool,延迟低
  • 长音效(背景音乐) :用 MediaPlayer
  • 音频文件放在 res/raw/
  • 页面销毁必须释放资源,避免内存泄漏

需要我帮你把音效封装成一个工具类,让整个 APP 随便调用吗?

相关推荐
朝朝辞暮i18 小时前
C++ 第 23 课:class —— 开始真正进入面向对象
开发语言·c++·算法
小师兄吃牛肉19 小时前
C语言篇:宏
c语言·开发语言
郑同学的笔记19 小时前
【c++随笔28】strcmp 和 memcmp对比
开发语言·c++
言乐620 小时前
Python根据无法识别搜索词找出可能输入内容模型
开发语言·python·django·virtualenv·pygame
weixin_3077791320 小时前
有限产能智能排产与动态重排智能体:从需求解构到技术实现
开发语言·人工智能·算法·架构
kakakahahahaha20 小时前
Windows C盘临时文件清理:%temp%、Windows Temp、Prefetch、Windows.old与hiberfil.sys处理指南
c语言·开发语言·windows
朝朝辞暮i20 小时前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法
朝朝辞暮i21 小时前
C++ 第 29 课:回调函数 Callback
开发语言·c++·算法
笨笨饿21 小时前
140_AI新手村MCP与Skills是干嘛的
开发语言·人工智能·python·stm32·单片机·嵌入式硬件·物联网
YOLO数据集集合21 小时前
EvoAgent:面向PR研发治理的自进化Multi-Agent Harness系统
java·开发语言·目标检测·agent·自进化