安卓app,MediaPlayer播放本地音频 | 按钮控制播放和停止

简介: 在Jetpack Compose中,不直接操作原生Android组件如`Button`和`MediaPlayer`,而是使用Compose UI构建器定义界面并结合ViewModel管理音频播放逻辑。以下示例展示如何播放本地音频并用按钮控制播放/停止:创建一个`AudioPlayerViewModel`管理`MediaPlayer`实例和播放状态,然后在Compose UI中使用`Button`根据`isPlaying`状态控制播放。记得在`MainActivity`设置Compose UI,并处理相关依赖和权限。

本文讨论内容基于 Jetpack Compose 框架



在Jetpack Compose中,我们通常不会直接操作Android的原生组件(如ButtonMediaPlayer),而是会利用Compose的UI构建器来定义UI,并可能使用ViewModel和Lifecycle等组件来管理音频播放的逻辑。

以下是一个简单的例子,展示了如何在Jetpack Compose中使用MediaPlayer来播放本地音频,并使用按钮来控制播放和停止。

首先,你需要在你的项目中添加一个ViewModel来管理MediaPlayer的实例和播放状态。


viewModel

import android.content.Context  
import android.media.MediaPlayer  
import androidx.lifecycle.MutableLiveData  
import androidx.lifecycle.ViewModel  
  
class AudioPlayerViewModel : ViewModel() {  
    private var mediaPlayer: MediaPlayer? = null  
  
    // 播放状态  
    val isPlaying = MutableLiveData<Boolean>(false)  
  
    // 初始化MediaPlayer并准备播放  
    fun initPlayer(context: Context, audioResourceId: Int) {  
        mediaPlayer = MediaPlayer.create(context, audioResourceId)  
        mediaPlayer?.setOnPreparedListener {  
            isPlaying.value = false  
        }  
    }  
  
    // 播放音频  
    fun play() {  
        mediaPlayer?.start()  
        isPlaying.value = true  
    }  
  
    // 暂停音频  
    fun pause() {  
        mediaPlayer?.pause()  
        isPlaying.value = false  
    }  
  
    // 停止并释放MediaPlayer  
    fun stopAndRelease() {  
        mediaPlayer?.stop()  
        mediaPlayer?.release()  
        mediaPlayer = null  
        isPlaying.value = false  
    }  
  
    // 检查是否正在播放  
    fun isCurrentlyPlaying(): Boolean {  
        return mediaPlayer?.isPlaying ?: false  
    }  
}



Compose UI

接下来,在你的Compose UI中,你可以使用Button组件来控制播放和停止,并使用Observer来观察播放状态


import android.content.Context  
import androidx.activity.ComponentActivity  
import androidx.activity.compose.setContent  
import androidx.compose.foundation.layout.*  
import androidx.compose.runtime.*  
import androidx.compose.ui.Modifier  
import androidx.compose.ui.tooling.preview.Preview  
import androidx.lifecycle.ViewModelProvider  
import androidx.lifecycle.viewmodel.compose.viewModel  
import com.google.accompanist.insets.navigationBarsPadding  
import com.google.accompanist.insets.statusBarsPadding  
  
@Composable  
fun AudioPlayerScreen(context: Context) {  
    val viewModel: AudioPlayerViewModel = viewModel()  
  
    viewModel.initPlayer(context, R.raw.your_audio_file) // 替换为你的音频文件资源ID  
  
    BoxWithConstraints(  
        modifier = Modifier  
            .fillMaxSize()  
            .statusBarsPadding()  
            .navigationBarsPadding()  
    ) {  
        Column(  
            modifier = Modifier  
                .fillMaxSize()  
                .padding(16.dp),  
            verticalArrangement = Arrangement.Center,  
            horizontalAlignment = Alignment.CenterHorizontally  
        ) {  
            Button(  
                onClick = {  
                    if (viewModel.isCurrentlyPlaying()) {  
                        viewModel.pause()  
                    } else {  
                        viewModel.play()  
                    }  
                }  
            ) {  
                Text(  
                    if (viewModel.isPlaying.value == true) "Pause" else "Play",  
                    style = MaterialTheme.typography.button  
                )  
            }  
  
            // 这里可以添加更多UI元素,如播放进度条等  
        }  
    }  
  
    // 清理MediaPlayer资源  
    DisposableEffect(Unit) {  
        onDispose {  
            viewModel.stopAndRelease()  
        }  
    }  
}  
  
@Preview(showBackground = true)  
@Composable  
fun DefaultPreview() {  
    AudioPlayerScreen(LocalContext.current)  
}  
  
// 在你的Activity中设置Compose UI  
class MainActivity : ComponentActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContent {  
            AudioPlayerScreen(this)  
        }  
    }  
}


请注意,上述代码中的R.raw.your_audio_file需要替换为你的音频文件在资源目录中的ID。同时,你还需要在build.gradle文件中添加对Jetpack Compose和Accompanist(用于处理窗口内边距)的依赖。

确保你的应用有适当的权限来访问和播放音频文件。如果你的音频文件在外部存储上,你可能还需要处理运行时权限请求。







在Jetpack Compose中集成MediaPlayer以播放本地音频,并使用按钮来控制播放和停止的过程,涉及到几个关键点:状态管理、生命周期感知以及与Compose UI的交互。下面是一个示例代码片段,展示了如何在Jetpack Compose中实现这些功能。

首先,你需要在你的build.gradle文件中添加androidx.media:media依赖项,以便使用MediaPlayer



dependencies {
    implementation 'androidx.media:media:1.4.3'
}



接下来,使用下面的Composable函数来创建UI和逻辑:



import android.media.MediaPlayer
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import kotlinx.coroutines.delay

@Composable
fun MediaPlayerDemo() {
    var mediaPlayer by remember { mutableStateOf<MediaPlayer?>(null) }
    var isPlaying by remember { mutableStateOf(false) }

    LaunchedEffect(key1 = true) {
        mediaPlayer = MediaPlayer.create(LocalContext.current, R.raw.your_audio_file)
        mediaPlayer?.setOnCompletionListener {
            isPlaying = false
        }
    }

    Column(modifier = Modifier.fillMaxSize()) {
        Button(
            onClick = {
                if (!isPlaying && mediaPlayer != null) {
                    mediaPlayer?.start()
                    isPlaying = true
                }
            },
            enabled = !isPlaying
        ) {
            Text(text = "Play")
        }
        Button(
            onClick = {
                if (isPlaying && mediaPlayer != null) {
                    mediaPlayer?.pause()
                    isPlaying = false
                }
            },
            enabled = isPlaying
        ) {
            Text(text = "Stop")
        }
    }
}


在这段代码中,我们使用remember来保持MediaPlayerisPlaying状态。LaunchedEffect用于初始化MediaPlayer,并设置一个完成监听器,以便在音频播放完毕时停止播放状态。

两个Button分别用于控制播放和停止。onClick回调根据当前的播放状态来决定是否应该开始播放或暂停播放。

请确保替换R.raw.your_audio_file为你自己的音频资源ID。此外,由于LocalContext.current在Compose中可能不总是返回正确的上下文,你可能需要根据你的具体需求调整获取上下文的方式,例如从ViewModel或Application中获取。

这段代码提供了一个基本的框架,你可以在此基础上添加错误处理、更复杂的UI元素,或者根据应用的需求进行扩展。



相关文章
|
6月前
|
缓存 移动开发 JavaScript
如何优化UniApp开发的App的启动速度?
如何优化UniApp开发的App的启动速度?
1080 139
|
6月前
|
移动开发 JavaScript weex
UniApp开发的App在启动速度方面有哪些优势和劣势?
UniApp开发的App在启动速度方面有哪些优势和劣势?
518 137
|
6月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1022 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
6月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
819 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
6月前
|
人工智能 前端开发 JavaScript
最佳实践3:用通义灵码开发一款 App
本示例演示使用通义灵码,基于React Native与Node.js开发跨平台类通义App,重点展示iOS端实现。涵盖前端页面生成、后端代码库自动生成、RTK Query通信集成及Qwen API调用全过程,体现灵码在全栈开发中的高效能力。(238字)
706 11
|
6月前
|
移动开发 Android开发
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
303 0
|
6月前
|
数据采集 JavaScript 前端开发
开发比分App?你缺的不是程序员
开发体育比分App,关键不在代码,而在懂体育、懂数据、懂用户。明确定位、理清需求、选好数据源,再找专业的产品、数据与技术人才协同,才能少走弯路。程序员最后入场,效率最高。
335 154
|
7月前
|
移动开发 小程序 Android开发
基于 uni-app 开发的废品回收类多端应用功能与界面说明
本文将对一款基于 uni-app 开发的废品回收类多端应用,从多端支持范围、核心功能模块及部分界面展示进行客观说明,相关资源信息也将一并呈现。
237 0
|
10月前
|
容器
HarmonyOS NEXT仓颉开发语言实战案例:外卖App
仓颉语言实战分享,教你如何用仓颉开发外卖App界面。内容包括页面布局、导航栏自定义、搜索框实现、列表模块构建等,附完整代码示例。轻松掌握Scroll、List等组件使用技巧,提升HarmonyOS应用开发能力。