Kotlin实现简单音乐播放器

news2024/11/14 19:52:14

关于音乐播放器,我真的是接触比较多,听歌作为我第一大爱好,之前也用Java设计过音乐播放器,感兴趣的同学可以阅读:Android Studio如何实现音乐播放器(简单易上手)和 Android Studio实现音乐播放器2.0

一、实验目的

理论知识

  1. 掌握Kotlin面向对象的软件开发方面的基础知识。
  2. 巩固前期Activity、UI控件的使用。
  3. 掌握Service和BroadcastReceiver的特点及用法。

专业技能

  1. 熟悉Android软件开发环境并掌握具体的工具的使用。
  2. 掌握Service和BroadcastReceiver组件的使用。
  3. 掌握移动应用软件分析和设计方法,并能将其运用到工程实践当中。

职业素养

  1. 逐步形成系统的设计的思想,具有一定的创新精神。
  2. 养成良好的编程习惯。

二、实验内容

根据Service及BroadcastReceiver的知识讲解和案例使用,实现一个Android音乐播放器,强化对服务与广播的理解。要求能实现音乐的播放,暂停,上一首,下一首等功能。要求:

  1. 巩固Android应用开发工具(Eclipse或者Android Studio)的常规用法;
  2. 巩固Activity、UI控件的常规用法;
  3. 掌握Service和BroadcastReceiver的编程要点;
  4. 理解MediaPlayer的使用。

三、实验步骤

1、页面布局

先考虑下简单音乐播放器的元素,那肯定是播放暂停停止,上一首和下一首了。

在这里插入图片描述

父布局是RelativeLayout,然后是ListView显示歌单,接下去就是Button按键了,没什么需要讲的,都过于基础。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <ListView
        android:id="@+id/lv_music"
        android:layout_width="match_parent"
        android:layout_height="500dp"/>
    <LinearLayout
        android:id="@+id/ll_play"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_below="@+id/lv_music"
        android:layout_marginTop="20dp">
        <Button
            android:id="@+id/btn_start"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="开始播放"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_margin="5dp"
            android:background="@drawable/btn_selector"
            android:layout_height="match_parent"/>
        <Button
            android:id="@+id/btn_pause"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="暂停播放"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_margin="5dp"
            android:background="@drawable/btn_selector"
            android:layout_height="match_parent"/>

        <Button
            android:id="@+id/btn_stop"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="停止播放"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_margin="5dp"
            android:background="@drawable/btn_selector"
            android:layout_height="match_parent"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_below="@+id/ll_play"
        android:layout_marginTop="20dp">
        <Button
            android:id="@+id/btn_pre"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="上一首"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_margin="5dp"
            android:background="@drawable/btn_selector"
            android:layout_height="match_parent"/>
        <Button
            android:id="@+id/btn_next"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="下一首"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_margin="5dp"
            android:background="@drawable/btn_selector"
            android:layout_height="match_parent"/>
    </LinearLayout>

</RelativeLayout>

2、音乐服务

其实播放音乐只需要MediaPlayer和start、resume等方法就行,几行代码解决。但Service越来越需要音乐播放器来体现出来,作为四大组件之一,Service从来不露脸,借助Activity来发挥自己的才能。是四大组件里面和Content Provider一样低调的人。

首先定义mediaPlayer对象。然后重写 onCreate()方法,在里面给mediaPlayer初始化和initMediaPlayer(),init的方法中就是打开assets文件夹下的音乐,调用setDataSource()设置数据源,然后prepare()准备就绪。

    private lateinit var mediaPlayer:MediaPlayer
    private var index = 0
    override fun onCreate() {
        super.onCreate()
        mediaPlayer = MediaPlayer()
        initMediaPlayer()
    }
    fun initMediaPlayer() {
        val assetManager = assets
        var fileName = "music" + index + ".mp3"
        var fd = assetManager.openFd(fileName)
        mediaPlayer.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)
        mediaPlayer.prepare()
    }

既然要通过Service实现音乐服务,那么就要控制音乐播放,在MusicService类中定义一个内部类MusicControl。它继承自Binder,里面只有成员方法,而且都没有返回值,其实就是对mediaplaer的方法进行了封装。start()、pause()、reset(),全局变量index是歌曲下标,在切换上下首时调用。

inner class MusicControl:Binder() {
        fun playMusic() {
            if (!mediaPlayer.isPlaying) {
                mediaPlayer.start()
            }
        }
        fun pasueMusic() {
            if (mediaPlayer.isPlaying) {
                mediaPlayer.pause()
            }
        }
        fun stopMusic() {
            if (mediaPlayer.isPlaying) {
                mediaPlayer.reset()
                initMediaPlayer()
            }
        }
        fun prePlay() {
            // 循环播放前一首
            index = (index + 5) % 6
            // 如果正在播放则重置播放器
            if (mediaPlayer.isPlaying) {
                mediaPlayer.reset()
            }
            initMediaPlayer()
            mediaPlayer.start()
        }
        fun nextPlay() {
            // 循环播放下一首
            index = (index + 7) % 6
            // 如果正在播放则重置播放器
            if (mediaPlayer.isPlaying) {
                mediaPlayer.reset()
            }
            initMediaPlayer()
            mediaPlayer.start()
        }
    }

3、音乐播放

创建适配器,使用默认的simple_list_item_1,显示一行歌曲名就行。如果你想自定义加上其他的歌曲元素,可以自己创建一个适配器和子项布局文件。这里讲解的重点是Service和Activity进行绑定。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, musicList)
        binding.lvMusic.adapter = adapter
        // 定义意图对象,绑定服务自动创建
        musicIntent = Intent(this, MusicService::class.java)
        bindService(musicIntent, musicConnection, BIND_AUTO_CREATE)
        initView()
    }

首先MainActivity里面还需要定义个内部类MusicConnection,用于连接MusicService的内部类,继承自ServiceConnection,重写的分类方法中只是在连接上服务的时候将iBinder赋值给musicControl。这里musicControl就是MusicService的内部类对应的对象。

lateinit var musicControl:MusicService.MusicControl
    inner class MusicConnection:ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            musicControl = p1 as MusicService.MusicControl
        }
        override fun onServiceDisconnected(p0: ComponentName?) {

        }
    }

下面我们就用初始化好的MusicConnection对象来连接MainActivity和MusicService。很简单的两句就好了。

    musicIntent = Intent(this, MusicService::class.java)
    bindService(musicIntent, musicConnection, BIND_AUTO_CREATE)

下面我们设置下按钮的点击事件,其实就是直接调用musicControl对象的方法。

	override fun onClick(p0: View?) {
        when(p0?.id) {
            R.id.btn_start->{
                musicControl.playMusic()
            }
            R.id.btn_pause->{
                musicControl.pasueMusic()
            }
            R.id.btn_stop->{
                musicControl.stopMusic()
            }
            R.id.btn_pre->{
                musicControl.prePlay()
            }
            R.id.btn_next->{
                musicControl.nextPlay()
            }
        }
    }

四、运行演示

打开就是主页面,点击开始播放,从第一首开始,然后可以暂停播放,再点开始播放就是继续播放,随时停止播放,上一首和下一首也无比流畅。

在这里插入图片描述

五、实验总结

这已经是第四次做音乐播放器了,这次做的也是最快的,也可能是简单的原因,没加什么复杂内容,其实如果是从音乐文件的数据库中读取再播放,我觉得就要花些时间了。或者从SD卡中读文件也是不错的想法,感兴趣的同学可以尝试挑战。

🔥源代码已上传CSDN🔥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/342883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全链路异步,让你的 SpringCloud 性能优化10倍+

背景 随着业务的发展&#xff0c;微服务应用的流量越来越大&#xff0c;使用到的资源也越来越多。 在微服务架构下&#xff0c;大量的应用都是 SpringCloud 分布式架构&#xff0c;这种架构&#xff0c;总体是全链路同步模式。 同步编程模式不仅造成了资源的极大浪费&#x…

设计模式:适配器模式(c++实现案例)

适配器模式 适配器模式是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。好比日本现在就只提供110V的电压&#xff0c;而我的电脑就需要220V的电压&#xff0c;那怎么办啦?适配器就是干这活的&#xff0…

CVE-2019-2725

//去年存货 前言 在学习内网过程中遇到了weblogic比较常见的漏洞&#xff0c;编号是cve-2019-2725,之前没有总结过&#xff0c;于是本篇文章给大家总结归纳一下该漏洞的利用方法与原理。 基础知识 cve-2019-2725漏洞的核心利用点是weblogic的xmldecoder反序列化漏洞&#x…

Bean(Spring)的执行流程和生命周期

Bean&#xff08;Spring&#xff09;的执行流程具体的流程就和我们创建Spring基本相似。启动 Spring 容器 -> 实例化 Bean&#xff08;分配内存空间&#xff0c;从无到有&#xff09; -> Bean 注册到 Spring 中&#xff08;存操作&#xff09; -> 将 Bean 装配到需要的…

基于微信小程序的医院挂号系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

C# 泛型集合中的排序

集合排序问题与ICompareble对于C#最常见的集合List<T>&#xff0c;有时候需要进行排序&#xff0c;而List是直接有Sort方法&#xff0c;因此对于一个简单地整数集合排序&#xff0c;很简单&#xff1a;List<int> ints new List<int>() { 1, 3, 1, 4, 5, 9, …

LeetCode-222. 完全二叉树的节点个数

目录递归法改进题目来源222. 完全二叉树的节点个数递归法 递归三步曲 1.确定递归函数的参数和返回值 参数就是传入树的根节点&#xff0c;返回就返回以该节点为根节点二叉树的节点数量&#xff0c;所以返回值为int类型。 int countNodes(TreeNode root)2.确定终止条件 如果…

网络安全-Pyhton环境搭建

网络安全-Pyhton环境搭建 https://www.kali.org/get-kali/#kali-installer-images—kali官网下载地址 python这个东东呢 是目前来说最简单&#xff0c;方便的开源的脚本语言 广泛用于Web开发&#xff0c;AI&#xff0c;网站开发等领域 python要装2和3 为什么要安装两个版本…

Word处理控件Aspose.Words功能演示:使用 C++ 合并 MS Word 文档

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c;API支持所有流行的Word处理文件…

34岁测试工程师被辞退,难道测试岗位真的只是青春饭吗?

一&#xff1a;前言&#xff1a;人生的十字路口静坐反思 入软件测试这一行至今已经10年多&#xff0c;承蒙领导们的照顾与重用&#xff0c;同事的支持与信任&#xff0c;我的职业发展算是相对较好&#xff0c;从入行到各类测试技术岗位&#xff0c;再到测试总监&#xff0c;再…

阿里云共享标准型S6实例云服务器特性、适用场景及性能评测

阿里云共享标准型s6实例是相对于上一代共享型xn4、n4、mn4和e4实例&#xff0c;在性能上更加更定的全新一代共享型实例。相比与突发性能型T5,T6实例&#xff0c;S6是不限制CPU性能&#xff0c;非常适合个人网站和企业展示性网站等中小型网站和Web应用程序。相对于阿里云当下其他…

基于微信云开发的防诈反诈宣传教育答题小程序

基于微信云开发的防诈反诈宣传教育答题小程序一、前言介绍作为当代大学生&#xff0c;诈骗事件的发生屡见不鲜&#xff0c;但却未能引起大家的重视。高校以线上宣传、阵地展示为主&#xff0c;线下学习、实地送法为辅&#xff0c;从而构筑立体化反诈骗防线。在线答题考试是一种…

【gcc/g++】程序的翻译(.c -->.exe)

环境&#xff1a;centos7.6&#xff0c;腾讯云服务器Linux文章都放在了专栏&#xff1a;【Linux】欢迎支持订阅&#x1f339;前言我们在写完代码运行时会发现生成了一个.exe的可执行程序&#xff0c;那么该程序是如何形成的呢&#xff1f;本次章节将在linux下用编译器gcc进行一…

2019年广东工业大学腾讯杯新生程序设计竞赛(同步赛)

同步赛链接 A-原初的信纸(最值&#xff0c;STL&#xff09; 题意&#xff1a; 找 n 个数的最大值. 参考代码&#xff1a; void solve() {int n;std::cin >> n;std::vector<int> a(n);for (auto &c : a)std::cin >> c;std::cout << *max_element…

3. SpringMVC Rest 风格

1. REST 简介 REST&#xff08;Representational State Transfer&#xff09;&#xff0c;表现形式状态转换&#xff0c;它是一种软件架构风格。 当要表示一个网络资源的时候&#xff0c;可以使用两种方式&#xff1a; 传统风格资源描述形式 http://localhost/user/getById?…

ts快速上手之实现hello world 常见的踩坑排除

前言 大家新年快乐&#xff0c;刚过了一个年又快要到情人节了&#xff0c;提前祝各位同行有女朋友的情人节快乐&#xff0c;没有对象那就new一个对象吧[滑稽] 关于TypeScript 闲话少说&#xff0c;相信大家在这个平台上看到的文章好多开头都会说一些介绍是多久诞生的&#x…

Java面试——MyBatis篇

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Flutter(一)介绍、Dart语言简介

Flutter介绍 纯原生开发主要面临动态化更新和开发成本两个问题&#xff0c;而针对这两个问题&#xff0c;诞生了一些跨平台的动态化框架 跨平台技术简介 Flutter 是 Google 推出并开源的移动应用开发框架&#xff0c;主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开…

【云原生kubernetes】k8s service使用详解

一、什么是服务service&#xff1f; 在k8s里面&#xff0c;每个Pod都会被分配一个单独的IP地址,但这个IP地址会随着Pod的销毁而消失&#xff0c;重启pod的ip地址会发生变化&#xff0c;此时客户如果访问原先的ip地址则会报错 &#xff1b; Service (服务)就是用来解决这个问题的…

Django设计模式以及模板层介绍

MVC和MTV 传统的MVC作用&#xff1a;降低模块间的耦合度&#xff08;解耦&#xff09;Django的MTV模式 作用&#xff1a;降低模块间的耦合度&#xff08;解耦&#xff09;什么是模板 1、模板是可以根据字典数据动态变化的html网页2、模板可以根据视图中传递的字典数据动态生成相…