安卓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元素,或者根据应用的需求进行扩展。



相关文章
|
8月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1530 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
8月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1064 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
8月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1148 4
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
8月前
|
移动开发 Android开发
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
403 0
|
11月前
|
存储 Android开发 数据安全/隐私保护
Thanox安卓系统增加工具下载,管理、阻止、限制后台每个APP运行情况
Thanox是一款Android系统管理工具,专注于权限、后台启动及运行管理。支持应用冻结、系统优化、UI自定义和模块管理,基于Xposed框架开发,安全可靠且开源免费,兼容Android 6.0及以上版本。
1344 4
|
安全 算法 小程序
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
1045 28
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
|
安全 Java Android开发
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
496 0
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
598 1
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
1011 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
|
Android开发 开发者 Kotlin
告别AsyncTask:一招教你用Kotlin协程重构Android应用,流畅度飙升的秘密武器
【9月更文挑战第13天】随着Android应用复杂度的增加,有效管理异步任务成为关键。Kotlin协程提供了一种优雅的并发操作处理方式,使异步编程更简单直观。本文通过具体示例介绍如何使用Kotlin协程优化Android应用性能,包括网络数据加载和UI更新。首先需在`build.gradle`中添加coroutines依赖。接着,通过定义挂起函数执行网络请求,并在`ViewModel`中使用`viewModelScope`启动协程,结合`Dispatchers.Main`更新UI,避免内存泄漏。使用协程不仅简化代码,还提升了程序健壮性。
580 1

热门文章

最新文章