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 随便调用吗?

相关推荐
阿米亚波7 分钟前
【C++ STL】std::unordered_multimap
开发语言·数据结构·c++·笔记·stl
码农coding30 分钟前
android12 systemUI 之锁屏
android
SomeB1oody38 分钟前
【RustyML入门】1.0. 快速上手
开发语言·后端·机器学习·rust·教程
圆山猫41 分钟前
[Virtualization](三):RISC-V H-extension 与 Guest 执行模式
android·java·risc-v
狗凯之家源码网1 小时前
短剧系统搭建实战:源码功能与商业变现效果全景展示
开发语言·php
爱笑鱼1 小时前
Binder(七):getCallingUid() 读到的是谁?clearCallingIdentity() 又清掉了什么?
android
易筋紫容2 小时前
创建型模式:对象的诞生艺术
开发语言·前端·javascript
888CC++2 小时前
C++ 快速学习指南:从入门到进阶的实战路线
开发语言·c++
小小晓.2 小时前
C++记:函数
开发语言·c++·算法
牡丹雅忻13 小时前
AES 加密模式演进:从 ECB、CBC 到 GCM 的 C# 深度实践
java·开发语言·c#