Android本地音乐播放器

article/2025/10/24 2:34:23

UI界面模仿QQ音乐
实现一个简单的本地播放器,功能包括:播放,暂停,上一曲,下一曲,进度条。

功能实现

读取本地音乐
1.创建一个Song类

public class Song {public String song;//歌曲名public String singer;//歌手public long size;//歌曲所占空间大小public int duration;//歌曲时间长度public String path;//歌曲地址public String album;//专辑名
}

2.用于获取本地音乐的Utils

public class Utils {//定义一个集合,存放从本地读取到的内容public static List<Song> list;public static Song song;public static List<Song> getmusic(Context context) {list = new ArrayList<>();Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null, null, null, MediaStore.Audio.AudioColumns.IS_MUSIC);if (cursor != null) {while (cursor.moveToNext()) {song = new Song();song.song = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));song.album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));song.singer = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));song.path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));song.duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));song.size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));//把歌曲名字和歌手切割开if (song.size > 1000 * 800) {if (song.song.contains("-")) {String[] str = song.song.split("-");song.singer = str[0];song.song = str[1];}list.add(song);}}}cursor.close();return list;}//    转换歌曲时间的格式public static String formatTime(int time) {if (time / 1000 % 60 < 10) {String tt = time / 1000 / 60 + ":0" + time / 1000 % 60;return tt;} else {String tt = time / 1000 / 60 + ":" + time / 1000 % 60;return tt;}}
}

3.在布局里面定义一个ListView,并写一个适配器

//适配器class MyAdapter extends BaseAdapter {Context context;List<Song> list;private int mSelect;   //选中项public MyAdapter(MainActivity mainActivity, List<Song> list) {this.context = mainActivity;this.list = list;}@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int i) {return list.get(i);}@Overridepublic long getItemId(int i) {return i;}@Overridepublic View getView(int i, View view, ViewGroup viewGroup) {Myholder myholder;if (view == null) {myholder = new Myholder();view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.text, null);// myholder.t_position = view.findViewById(R.id.t_postion);myholder.t_song = view.findViewById(R.id.t_song);myholder.t_singer = view.findViewById(R.id.t_singer);myholder.t_blank=view.findViewById(R.id.t_blank);myholder.t_albumn=view.findViewById(R.id.t_albumn);myholder.t_point=view.findViewById(R.id.t_point);myholder.t_duration = view.findViewById(R.id.t_duration);view.setTag(myholder);} else {myholder = (Myholder) view.getTag();}myholder.t_song.setText(list.get(i).song.toString());myholder.t_singer.setText(list.get(i).singer.toString());String time = Utils.formatTime(list.get(i).duration);myholder.t_albumn.setText(list.get(i).album.toString());myholder.t_duration.setText(time);//myholder.t_position.setText(i + 1 + "");//设置相关数据if (mSelect==-1){myholder.t_song.setEnabled(true);myholder.t_singer.setEnabled(true);myholder.t_blank.setVisibility(View.INVISIBLE);//选中项背景myholder.t_song.setTextColor(getResources().getColor(R.color.tilte_color));myholder.t_singer.setTextColor(getResources().getColor(R.color.tilte_color));myholder.t_albumn.setTextColor(getResources().getColor(R.color.tilte_color));myholder.t_point.setTextColor(getResources().getColor(R.color.tilte_color));}if (mSelect == i) {myholder.t_song.setEnabled(true);myholder.t_singer.setEnabled(true);myholder.t_blank.setVisibility(View.VISIBLE);//选中项背景myholder.t_song.setTextColor(getResources().getColor(R.color.theme));myholder.t_singer.setTextColor(getResources().getColor(R.color.theme));myholder.t_albumn.setTextColor(getResources().getColor(R.color.theme));myholder.t_point.setTextColor(getResources().getColor(R.color.theme));myholder.t_duration.setTextColor(getResources().getColor(R.color.theme));} else {myholder.t_song.setEnabled(false);myholder.t_singer.setEnabled(false);myholder.t_blank.setVisibility(View.INVISIBLE);//其他项背景myholder.t_song.setTextColor(getResources().getColor(R.color.tilte_color));myholder.t_singer.setTextColor(getResources().getColor(R.color.song));myholder.t_albumn.setTextColor(getResources().getColor(R.color.song));myholder.t_point.setTextColor(getResources().getColor(R.color.song));myholder.t_duration.setTextColor(getResources().getColor(R.color.song));}return view;}class Myholder {ImageView t_blank;TextView t_position, t_song, t_singer, t_duration,t_albumn,t_point;}//刷新方法public void changeSelected(int positon){if (positon != mSelect) {mSelect = positon;notifyDataSetChanged();}}}

在类里面定义一个刷新位置的方法changeSelectde与ListView的点击监听事件配合使用,用于ListView被点击后将position参数传入,相应的文字颜色的改变
4.给ListView设置适配器

mylist = (ListView) findViewById(R.id.mylist);list = new ArrayList<>();list = Utils.getmusic(this);//获取音乐myAdapter = new MyAdapter(this, list);mylist.setAdapter(myAdapter);

5.使用MediaPlayer播放音乐
把音乐读取到ListView之后,点击音乐列表的音乐,就能够进行音乐的播放,并在底栏显示相应的音乐名,歌手名,可以拖动进度条进行音乐的控制,点击相应的按钮能够暂停,上一曲,下一曲。
首先封装一个播放音乐的方法,传入的参数currentPosition为音乐的位置

private void musicPlay(int currentPosition) {seekBar.setMax(list.get(currentPosition).getDuration());try {// 重置音频文件,防止多次点击会报错mediaPlayer.reset();//调用方法传进播放地址mediaPlayer.setDataSource(list.get(currentPosition).getPath());//异步准备资源,防止卡顿mediaPlayer.prepareAsync();//调用音频的监听方法,音频准备完毕后响应该方法进行音乐播放mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mediaPlayer) {mediaPlayer.start();//开始播放Thread thread = new Thread(new SeekBarThread());//更新SeekBar的线程thread.start();}});} catch (Exception e) {e.printStackTrace();}}

然后为ListView设置点击事件

mylist.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {currentPosition=position;musicPlay(currentPosition);//播放音乐myAdapter.changeSelected(currentPosition);//设置字体变色play.setVisibility(View.INVISIBLE);//播放按钮消失pause.setVisibility(View.VISIBLE);//暂停按钮出现String song=list.get(currentPosition).song;//获取音乐名String singer=list.get(currentPosition).singer;//获取歌手名bottomSong.setText(song);//底栏显示音乐名bottomSinger.setText(singer);//底栏显示歌手名gang.setVisibility(View.VISIBLE);//横杠}});

播放,暂停,上一曲,下一曲按钮点击事件

//暂停按钮pause.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mediaPlayer.pause();//暂停音乐pause.setVisibility(View.INVISIBLE);play.setVisibility(View.VISIBLE);}});//播放按钮play.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {play.setVisibility(View.INVISIBLE);pause.setVisibility(View.VISIBLE);mediaPlayer.start();//播放音乐}});/*** 下一曲*/next.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {currentPosition++;if (currentPosition > list.size() - 1) {currentPosition = 0;}musicPlay(currentPosition);myAdapter.changeSelected(currentPosition);//ListView颜色变化//底栏设置正在播放的歌曲信息String song=list.get(currentPosition).song;String singer=list.get(currentPosition).singer;bottomSong.setText(song);bottomSinger.setText(singer);gang.setVisibility(View.VISIBLE);}});/*** 上一曲*/pre.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {currentPosition--;if (currentPosition < 0) {currentPosition = list.size() - 1;}musicPlay(currentPosition);myAdapter.changeSelected(currentPosition);//ListView颜色变化//底栏设置正在播放的歌曲信息String song=list.get(currentPosition).song;String singer=list.get(currentPosition).singer;bottomSong.setText(song);bottomSinger.setText(singer);gang.setVisibility(View.VISIBLE);}});

给mediaPlayer添加一个监听事件,实现当前音乐播放完成后自动播放下一首的功能

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {currentPosition++;if (currentPosition > list.size() - 1) {currentPosition = 0;}musicPlay(currentPosition);myAdapter.changeSelected(currentPosition);//底栏设置正在播放的歌曲信息String song=list.get(currentPosition).song;String singer=list.get(currentPosition).singer;bottomSong.setText(song);bottomSinger.setText(singer);gang.setVisibility(View.VISIBLE);}});

5.进度条
使用Handler类,进行SeekBar的更新

private static final int UPDATE_SEEKBAR=0;private Handler  handler=new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what){case UPDATE_SEEKBAR:// 将SeekBar位置设置到当前播放位置seekBar.setProgress(mediaPlayer.getCurrentPosition());break;default:break;}}};

定义一个类,实现Runnable接口进行SeekBar状态的刷新

class SeekBarThread implements Runnable {@Overridepublic void run() {while (mediaPlayer.isPlaying()) {try {// 每500毫秒更新一次位置Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}Message message=new Message();message.what=UPDATE_SEEKBAR;handler.sendMessage(message);}}}

给SeekBar添加监听事件,实现拖动进度条改变音乐进度

seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {if(fromUser==true){mediaPlayer.seekTo(progress);}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});}

源码下载链接:
下载链接


http://chatgpt.dhexx.cn/article/Q6MQl3f7.shtml

相关文章

毕业设计- 基于Android的本地音乐播放器

—— 木叶飞舞之处&#xff0c;火亦生生不息。 项目介绍 本系统支持扫瞄本地音乐播放、暂停、上一首、下一首&#xff0c;点击播放栏跳转到播放页面&#xff0c;可查看当前播放列表&#xff0c;设置播放模式如顺序播放、随机播放&#xff0c;标记为我的喜欢&#xff0c;可以创…

Selenium自动化测试设计模式-PO模式

前言&#xff1a; 在python自动化过程中&#xff0c;Selenium自动化测试中有一个名字常常被提及PageObject&#xff08;思想与面向对象的特性相同&#xff09;&#xff0c;通过PO模式可以大大提高测试用例的维护效率。 不了解po设计模式的可自行百度 面向对象的特性&#xf…

电商项目测试实战(十一)后台业务场景测试设计

后台订单处理业务场景测试设计 流程步骤&#xff1a; 设计测试用例&#xff1a; 第一步&#xff1a;绘制流程图 1、确认业务中的操作 2、分析执行的顺序 3、按照业务方向进行连线 收到前台订单&#xff08;商城->订单->订单列表&#xff09;订单确认发货&#xff0…

电商项目测试实战(十)前台下单业务场景测试设计

前台下单业务场景测试设计 流程步骤&#xff1a; 设计测试用例&#xff1a; 第一步&#xff1a;需求分析 第二步&#xff1a;绘制流程图 1、确定业务中的操作 2、分析执行的顺序 3、按照业务方向进行连线 登录->选购商品->加入购物车->支付->确认订单->等待…

空调测试用例设计

** 空调测试用例设计 ** 界面测试 功能测试 可靠性测试 易用性测试 可维护性测试 兼容性测试 竞品测试 负载压力测试 稳定性测试 文档测试 界面测试&#xff1a; 空调外观的美观性空调外观尺寸是否和设计尺寸一致遥控按钮是否清晰和易懂显示温度及模式的显示屏是否显示设备…

测试场景设计-登录设计

来一波广告&#xff1a;欢迎关注测者说&#xff0c;测试理论知识尽在此处 面试中经常被问到有一个登录页面&#xff0c;你怎么设计测试场景&#xff0c;原来可以做到这么细致。 具体需求&#xff1a; 有一个登陆页面&#xff0c;&#xff08;假如上面有2个textbox,一个提交按钮…

基于微信小程序的大学生心理健康测试设计与实现 .docx

目录 1 绪论 3 1.1 项目开发背景 3 1.2 项目开发意义 3 1.3 项目主要的内容 4 2 相关技术介绍及系统环境开发条件 5 2.1相关技术介绍 5 2.2系统环境开发条件 6 3 系统的需求分析与设计 6 3.1可行性分析 7 3.2需求分析 7 3.2.1系统总体概述 8 3.2.2功能性需求 8 3.2.3非功能性需…

测试设计技术

本文是根据测试架构师修炼之道&#xff08;第二部分 突破&#xff1a;向软件测试架构师的目标迈进&#xff09;整理的&#xff0c;主要分为5个小部分&#xff1a;测试设计四步走、测试设计软技能、设计技术之控制用例粒度、设计技术之自动化测试、设计技术之探索式测试。学习的…

数字系统的测试与可测试设计(DFT)

数字系统的测试与可测试设计&#xff08;DFT&#xff09; 背景介绍1 Defects1.1 名词解释1.2 缺陷种类1.2.1 Physical Defects物理缺陷1.2.2 Shorting Defects1.2.2.1 Gate-Oxide-Shorts1.2.2.2 Bridge1.2.2.1 Open1.2.2.1 Post-fabrication failures 2 Fault Modelling&#x…

2. 测试分析与测试设计

1. 为什么要做好测试分析和测试设计 以业务驱动测试&#xff1a;当下的测试圈子内&#xff0c;大家一直在强调自动化技术、DevOps等&#xff0c;这些是提高效率和质量的利器&#xff0c;但是所有有效的测试行为&#xff0c;都是建立在对业务需求有正确的理解和分析的基础上的。…

软件测试之---测试设计方法

二、测试设计方法&#xff08;黑盒测试设计方法&#xff1b;白盒测试设计方法&#xff09; 1、等价类划分法 1.1等价类划分法概念 将输入&#xff08;输出&#xff09;域划分成若干个子集合&#xff0c;从划分的子集合中选取代表数据&#xff0c;如果选取的数据测试没有问题&…

测试用例:四步测试设计法

读者提问&#xff1a; 阿常&#xff0c;上节我们讲到测试点不等同于测试用例&#xff0c;想请教你一下&#xff0c;如何把测试点加工成测试用例呢&#xff1f; 目前团队中测试人员针对同样的测试点&#xff0c;编写出来的测试用例各不相同&#xff0c;一千个人就有一千个哈姆雷…

常用测试设计方法

目录 1、按照开发阶段划分&#xff08;1&#xff09;单元测试(模块测试)&#xff08;2&#xff09;集成测试(组装测试)&#xff08;3&#xff09;确认测试(有效性测试)&#xff08;4&#xff09;系统测试&#xff08;5&#xff09;验收测试 2、按照代码运行划分&#xff08;1&a…

大数据基础概述

大数据基础概述 1.前言2.大数据技术发展的三个阶段3.大数据技术面临的问题4.大数据技术数据的特点5.大数据对各方面的影响6.大数据技术的应用领域7.大数据技术的相关概念8.大数据技术的相关产业9.云计算和物联网 1.前言 三次信息浪潮 信息化浪潮发生时间标志解决问题代表企业第…

大数据概论

大数据big data指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新 处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。大量数据资源为解决以前不可能解决的问题带来了可能性。1大数据不一定…

大数据技术概论

大数据技术概论 大数据技术的产生 大数据的基本概念 ●大数据简介: 大数据是规模非常巨大和复杂的数据集,传统数据库管理工具处理起来面临很多问题,比如说获取、存储、检索、共享、分析和可视化,数据量达到PB、EB或ZB的级别。 大数据有三个V: 一是数据量(Volume),数据量是持续…

2【源码】数据可视化:基于 Echarts + Java SpringBoot 实现的动态实时大屏范例-物流大数据

数据可视化大屏的出现&#xff0c;掀起一番又一番的浪潮&#xff0c;众多企业纷纷想要打造属于自己的“酷炫吊炸天”的霸道总裁大屏驾驶舱。 之前小伙伴们建议我出一些视频课程来学习Echarts&#xff0c;这样可以更快上手&#xff0c;所以我就追星赶月的录制了《Echarts - 0基…

客快物流大数据项目(九十一):ClickHouse的数据库引擎

​​​​​​​ 文章目录 ClickHouse的数据库引擎 一、MySQL引擎 ClickHouse的数据库引擎 ClickHouse提供了本机、M

客快物流大数据项目(九十二):ClickHouse的MergeTree系列引擎介绍和MergeTree深入了解

文章目录 ClickHouse的MergeTree系列引擎介绍和MergeTree深入了解 一、MergeTree系列引擎介绍