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

相关推荐
三少爷的鞋20 小时前
Android 架构指南之Data 层不要再暴露 start/stop 了:用 Flow 接管生命周期
android
李艺为20 小时前
Android 14 U盘无法正常显示中文盘符(卷标)问题解决
android
ch.ju20 小时前
Java Programming Chapter 4——Overloading of method
java·开发语言
Teable任意门互动20 小时前
拆解 Teable 背后研发主体,开源多维表格平台实力与落地案例
开发语言·开源·excel·飞书·开源软件
吃好睡好便好20 小时前
用直接输入的方式创建矩阵
开发语言·人工智能·学习·线性代数·算法·matlab·矩阵
NiKick20 小时前
理解C++中的构造函数如何影响对象初始化
开发语言·c++
陆业聪20 小时前
Agent智能体:让AI自己调API干活——从Android Service到AI Agent的思维跃迁
android·人工智能·aigc
海上彼尚20 小时前
Nodejs也能写Agent - 9.Mastra篇 - Mastra客户端
开发语言·前端·javascript·人工智能·node.js
2401_8332693020 小时前
Java异常处理入门
java·开发语言
极客小云20 小时前
【用 Go 写一个统一的 LLM Token 统计库:tokencalc 的设计与实现】
开发语言·后端·golang