安卓简易音乐播放器实现
文章目录
- 一、参考文章
- 二、功能说明
- 三、重要代码说明
- 1、存储权限读取
- 2、指定歌曲路径,初始化MediaPlayer组件并使其进入准备状态
- 3、进度条功能
- 四、用到的MediaPlayer的方法总结
- 五、完整代码
- 1、activity_main.xml
- 2、MainActivity.java
- 3、不要忘记AndroidManifect也需要写明申请什么权限
一、参考文章
参考文章:Android音乐播放器的实现-简书
原文使用了service,也稍微看了一下。service大概就是下面这样的:但是我发现即使只用Activity,切出去之后歌曲的播放也不会停止,于是就暂时没有使用它,只用到了Activity,需要用到service的朋友可以看一下上面那篇文章。
service是Android中实现程序后台的解决方案,不依赖任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,service还能保持运行。
二、功能说明
实现了播放、暂停、停止、下一首歌、上一首歌和进度条的功能,可以拖动进度条来改变歌曲的进度。
界面就像下面这样:丑丑的
三、重要代码说明
1、存储权限读取
① 首先调用checkSelfPermission进行权限检查,如果无权限则使用requestPermissions进行权限申请,其中PackageManager.PERMISSION_GRANTED 表示有权限, PackageManager.PERMISSION_DENIED 表示无权限。
if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);//这里会调用后面的onRequestPermissionResult}else{initMediaPlayer(0);}
② requestPermissions方法进行权限申请后会自动调用onRequestPermissionsResult(),覆写onRequestPermissionsResult()
@Override//拒绝权限获取则直接关闭程序public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){switch (requestCode){case 1:{if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){initMediaPlayer(0);}else{Toast.makeText(this,"拒绝权限将无法使用程序",Toast.LENGTH_SHORT).show();finish();}break;}default:break;}}
③ 在AndroidManifest.xml文件中注明申请了什么权限
注意uses-permission要作为manifest的直接孩子
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、指定歌曲路径,初始化MediaPlayer组件并使其进入准备状态
下面这段代码你没看错,就是很粗暴地自己在内部存储根目录下建一个叫做MyTestMusic的文件夹,然后放四首歌进去,再把这几首歌都作为歌曲的路径。
File pFile = Environment.getExternalStorageDirectory();//SD卡根目录//歌曲路径private String[] musicPath = new String[]{pFile + "/MyTestMusic/想自由_林宥嘉.flac",pFile + "/MyTestMusic/Adele-Someone Like You.ape",pFile + "/MyTestMusic/Taylor Swift - Love Story.mp3",pFile + "/MyTestMusic/感同身受_林宥嘉.flac"};
private void initMediaPlayer(int musicIndex){try {//File file = new File(pFile,"Adele-Someone Like You.ape");mediaPlayer.setDataSource(musicPath[musicIndex]);//指定音频文件路径mediaPlayer.prepare();//让MediaPlayer进入到准备状态}catch(Exception e){e.printStackTrace();}
}
3、进度条功能
① 在initMediaPlayer中加入对进度条最大长度的设置,并通过setOnSeekBarChangeListener来完成用户拖动进度条时改变歌曲进度的功能。为什么加在这里呢,因为每换一首歌seekBar的长度都要发生变化。
//这个要放在指定音频文件路径之后seekBar.setMax(mediaPlayer.getDuration());//拖动进度条时应该发生的事情seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {//如果不判断是否来自用户操作进度条,会不断执行下面语句块里面的逻辑if(fromUser){//seekBar.getProgress()为进度条拖到的地方mediaPlayer.seekTo(seekBar.getProgress());}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});
② 更新UI,获取歌曲进度并在进度条上展现,并每隔一秒跳一个数字
主线程创建handler,在子线程中通过handler的post(Runnable)方法更新UI信息。
private Handler myHandler = new Handler();
……//更新UIprivate Runnable updateUI = new Runnable() {@Overridepublic void run() {//获取歌曲进度并在进度条上展现seekBar.setProgress(mediaPlayer.getCurrentPosition());//获取播放位置timeTextView.setText(time.format(mediaPlayer.getCurrentPosition()) + "s");myHandler.postDelayed(updateUI,1000);}};
③ 在onCreate函数的最后:
myHandler.post(updateUI);
四、用到的MediaPlayer的方法总结
重要的功能就前面那些了,其他的开始什么都是很容易地调用一下就可以了,下面总结一下MediaPlayer有哪些方法好了。
方法 | 功能 |
---|---|
setDataSource() | 指定音频文件路径 |
prepare() | 让MediaPlayer进入到准备状态 |
getDuration() | 获取歌曲长度 |
getCurrentPosition() | 获取现在播放到的位置 |
seekTo(int msec) | 播放到指定位置 |
isPlaying() | 是否正在播放 |
start() | 开始播放 |
pause() | 暂停播放 |
reset() | 应该是有些停止播放的意味,后面一般重新使MediaPlayer进入准备状态 |
release() | 释放资源 |
五、完整代码
1、activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"android:layout_marginVertical="30dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginHorizontal="20dp"><Buttonandroid:id="@+id/play"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="play" /><Buttonandroid:id="@+id/pause"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="pause"android:layout_marginLeft="40dp"/><Buttonandroid:id="@+id/stop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="stop"android:layout_marginLeft="20dp"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_marginHorizontal="30dp"android:layout_marginVertical="30dp"><Buttonandroid:id="@+id/previous"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="previous" /><Buttonandroid:id="@+id/next"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="next"android:layout_marginLeft="120dp"/></LinearLayout><SeekBarandroid:layout_marginTop="20dp"android:id="@+id/seekbar"android:layout_width="match_parent"android:layout_height="wrap_content"/><TextViewandroid:text="当前进度:"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/text1"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout></android.support.constraint.ConstraintLayout>
2、MainActivity.java
package com.example.yogi.mymusicplayer;import android.Manifest;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;import java.io.File;
import java.text.SimpleDateFormat;public class MainActivity extends AppCompatActivity implements View.OnClickListener {//主线程创建handler,在子线程中通过handler的post(Runnable)方法更新UI信息。private Handler myHandler = new Handler();private MediaPlayer mediaPlayer = new MediaPlayer();private SeekBar seekBar;private TextView timeTextView;//进度条下面的当前进度文字,将毫秒化为m:ss格式private SimpleDateFormat time = new SimpleDateFormat("m:ss");private int i = 0;//当前歌曲序号File pFile = Environment.getExternalStorageDirectory();//SD卡根目录//歌曲路径private String[] musicPath = new String[]{pFile + "/MyTestMusic/想自由_林宥嘉.flac",pFile + "/MyTestMusic/Adele-Someone Like You.ape",pFile + "/MyTestMusic/Taylor Swift - Love Story.mp3",pFile + "/MyTestMusic/感同身受_林宥嘉.flac"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button play = findViewById(R.id.play);Button stop = findViewById(R.id.stop);Button pause = findViewById(R.id.pause);Button nextMusic = findViewById(R.id.next);Button preMusic = findViewById(R.id.previous);play.setOnClickListener(this);stop.setOnClickListener(this);pause.setOnClickListener(this);nextMusic.setOnClickListener(this);preMusic.setOnClickListener(this);seekBar = findViewById(R.id.seekbar);timeTextView = findViewById(R.id.text1);//运行时权限处理,动态申请WRITE_EXTERNAL_STORAGE权限//PackageManager.PERMISSION_GRANTED 表示有权限, PackageManager.PERMISSION_DENIED 表示无权限if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);//这里会调用后面的onRequestPermissionResult}else{initMediaPlayer(0);}myHandler.post(updateUI);}private void initMediaPlayer(int musicIndex){try {//File file = new File(pFile,"Adele-Someone Like You.ape");mediaPlayer.setDataSource(musicPath[musicIndex]);//指定音频文件路径mediaPlayer.prepare();//让MediaPlayer进入到准备状态}catch(Exception e){e.printStackTrace();}//这个要放在指定音频文件路径之后seekBar.setMax(mediaPlayer.getDuration());//拖动进度条时应该发生的事情seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {//如果不判断是否来自用户操作进度条,会不断执行下面语句块里面的逻辑if(fromUser){mediaPlayer.seekTo(seekBar.getProgress());}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {}});}@Override//拒绝权限获取则直接关闭程序public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){switch (requestCode){case 1:{if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){initMediaPlayer(0);}else{Toast.makeText(this,"拒绝权限将无法使用程序",Toast.LENGTH_SHORT).show();finish();}break;}default:break;}}@Overridepublic void onClick(View v){switch (v.getId()){case R.id.play:if(!mediaPlayer.isPlaying()){mediaPlayer.start();}break;case R.id.pause:if(mediaPlayer.isPlaying()){mediaPlayer.pause();}break;case R.id.stop:if(mediaPlayer.isPlaying()){mediaPlayer.reset();initMediaPlayer(i);}break;case R.id.next:playNextMusic();break;case R.id.previous:playPreMusic();break;default:break;}}private void playNextMusic(){if(mediaPlayer != null && i < 4 && i >=0){mediaPlayer.reset();//没有reset会报IllegalStateExceptionswitch (i){case 0: case 1: case 2:initMediaPlayer(i+1);i = i + 1;case 3:initMediaPlayer(0);}if(!mediaPlayer.isPlaying()){mediaPlayer.start();}}}private void playPreMusic(){if(mediaPlayer != null && i < 4 && i >=0){mediaPlayer.reset();//没有reset会报IllegalStateExceptionswitch (i){case 1: case 2: case 3:initMediaPlayer(i-1);i = i - 1;case 0:initMediaPlayer(3);}if(!mediaPlayer.isPlaying()){mediaPlayer.start();}}}//更新UIprivate Runnable updateUI = new Runnable() {@Overridepublic void run() {//获取歌曲进度并在进度条上展现seekBar.setProgress(mediaPlayer.getCurrentPosition());//获取播放位置timeTextView.setText(time.format(mediaPlayer.getCurrentPosition()) + "s");myHandler.postDelayed(updateUI,1000);}};//释放资源protected void onDestroy(){super.onDestroy();//handler发送是定时1000s发送的,如果不关闭,MediaPlayer release了还在getCurrentPosition就会报IllegalStateException错误myHandler.removeCallbacks(updateUI);if(mediaPlayer != null){mediaPlayer.stop();mediaPlayer.release();}}
}
3、不要忘记AndroidManifect也需要写明申请什么权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.yogi.mymusicplayertest">……<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /></manifest>
安卓简易音乐播放器实现相关推荐
- JavaScript + Audio API自制简易音乐播放器(详细完整版、小白都能看懂)
JavaScript + Audio API自制简易音乐播放器(详细完整版) ** 音乐播放器的功能清单如下: ** 1.点击暂停按钮,歌曲暂停 2.点击播放按钮,歌曲播放 3.单曲循环与取消单曲循环 ...
- html实现简易音乐播放器
目标: 使用vue.js导包的形式做一个简单的音乐播放器,新手也很容易看懂. 内容: 1. 使用了flex实现响应式布局: 2. 使用min-width防止字体被压缩: 3. 使用computed计算 ...
- Android Studio简易音乐播放器设计作业
Android Studio简易音乐播放器设计作业 实验成功展示 实验代码 MainActivity.java XML文件 class文件 利用BroadcastReceiver模拟音乐播放器,实现播 ...
- 单片机音乐播放器课程设计C语言,单片机课程设计简易音乐播放器
单片机课程设计简易音乐播放器 论文题目:简易音乐播放器所属系部:电子工程系 指导教师: 学生姓名: 学 号: 专 业: 电子信息工程技术 题目: 简易音乐播放器任务与要求:本设计以 MCS-51 系列 ...
- 【毕业设计】28-基于单片机的音乐播放器简易音乐播放器设计(原理图+源代码+仿真工程+答辩PPT+答辩论文)
typora-root-url: ./ [毕业设计]28-基于单片机的音乐播放器简易音乐播放器设计(原理图+源代码+仿真工程+答辩PPT+答辩论文) 文章目录 typora-root-url: ./ ...
- android 无损播放器,山灵公布M6 Pro 安卓无损音乐播放器:骁龙430+4GB内存
IT之家3月18日消息 今天,山灵在微博中公布了M6 Pro 安卓无损音乐播放器,搭载骁龙 430 CPU和4GB内存,全新屏内R角,AG磨砂钢化玻璃,AK4497EQ DAC *2解码芯片,价格尚 ...
- 【微信小程序】简易音乐播放器,进度条拖拉、音乐的播放与暂停
小程序简易音乐播放器实现 粗糙的页面设计: wxml部分: <view class="test"><view class="img">& ...
- 利用Broadcast及相关组件实现简易音乐播放器功能
目录 前言 项目源码 准备工作 代码编写 页面布局 Service类的创建 主函数的编写 项目心得 前言 在Andriod Studio中使用Broadcast实现了简易音乐播放器的功能.可以进行播放 ...
- PyQt5实现简易音乐播放器
PyQt5实现简易音乐播放器 环境 vscode python 3.10.0 PyQt5 5.15.4 功能目标 能够读取本地的音乐文件,并实现播放的开关.曲目的切换和音量的加减 具体实现 新建一个文 ...
最新文章
- Ubuntn删除软件
- 【深度学习】LSTM神经网络解决COVID-19预测问题(二)
- Windows 2000/NT/XP管理员密码丢失解决方法
- [改善Java代码]覆写equals方法必须覆写hashCode方法
- 在doc中生成柱状图_Python从CSV文件导入数据和生成简单图表
- Unable to execute dex: Multiple dex files define Lcom
- 几位无人驾驶领域的杰出科学家
- html中form标签的作用style,HTML5中meta常用标签属性说明
- jeewx-api.jar入门教程
- field list什么意思_什么是生物信息学?
- 阿克曼函数Ackerman
- 空调基础知识培训课件
- vbs格式编程教程提高
- Java文件上传接口
- 【无人机系统】四轴飞行器及其UAV飞控系统 - 桂林电子科技大学信息科技学院 电子工程系(一)
- 链表初始化typedef struct LNode{}LNode,*linklist的理解
- vs2017旗舰版_2017年的所有旗舰手机都有明显的妥协。 这是他们告诉我们有关设计的信息。...
- 2020最新开发及环境搭建类经典面试题
- libcurl简单接口的使用(FTP)
- SSH登录及失败解决
热门文章
- Ecma 118th GA会议手记
- 制作精致闪电天气APP图标的PS教程
- 祝大家开工大吉,工作顺利。
- 《Nature》子刊发布,IIT科学家模仿“植物的触须”,打造可逆渗透致动的仿生软体机器人
- android照片备份软件下载,照片备份云相册app-照片备份云相册安卓版下载v1.5-乐游网安卓下载...
- 跟领导关系再好,也别做3件小事,嘴欠手贱,煮熟鸭子会飞
- 设计模式【2.2】-- 工厂模式怎么演变成抽象工厂模式?
- ubuntu关机或重启出现memtest
- 史上最详细:word文档怎么在第三页插入页码,只要7步
- python爬虫模式_python爬虫的入门试炼