文章目录

  • 一、参考文章
  • 二、功能说明
  • 三、重要代码说明
    • 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>

安卓简易音乐播放器实现相关推荐

  1. JavaScript + Audio API自制简易音乐播放器(详细完整版、小白都能看懂)

    JavaScript + Audio API自制简易音乐播放器(详细完整版) ** 音乐播放器的功能清单如下: ** 1.点击暂停按钮,歌曲暂停 2.点击播放按钮,歌曲播放 3.单曲循环与取消单曲循环 ...

  2. html实现简易音乐播放器

    目标: 使用vue.js导包的形式做一个简单的音乐播放器,新手也很容易看懂. 内容: 1. 使用了flex实现响应式布局: 2. 使用min-width防止字体被压缩: 3. 使用computed计算 ...

  3. Android Studio简易音乐播放器设计作业

    Android Studio简易音乐播放器设计作业 实验成功展示 实验代码 MainActivity.java XML文件 class文件 利用BroadcastReceiver模拟音乐播放器,实现播 ...

  4. 单片机音乐播放器课程设计C语言,单片机课程设计简易音乐播放器

    单片机课程设计简易音乐播放器 论文题目:简易音乐播放器所属系部:电子工程系 指导教师: 学生姓名: 学 号: 专 业: 电子信息工程技术 题目: 简易音乐播放器任务与要求:本设计以 MCS-51 系列 ...

  5. 【毕业设计】28-基于单片机的音乐播放器简易音乐播放器设计(原理图+源代码+仿真工程+答辩PPT+答辩论文)

    typora-root-url: ./ [毕业设计]28-基于单片机的音乐播放器简易音乐播放器设计(原理图+源代码+仿真工程+答辩PPT+答辩论文) 文章目录 typora-root-url: ./ ...

  6. android 无损播放器,山灵公布M6 Pro 安卓无损音乐播放器:骁龙430+4GB内存

    IT之家3月18日消息  今天,山灵在微博中公布了M6 Pro 安卓无损音乐播放器,搭载骁龙 430 CPU和4GB内存,全新屏内R角,AG磨砂钢化玻璃,AK4497EQ DAC *2解码芯片,价格尚 ...

  7. 【微信小程序】简易音乐播放器,进度条拖拉、音乐的播放与暂停

    小程序简易音乐播放器实现 粗糙的页面设计: wxml部分: <view class="test"><view class="img">& ...

  8. 利用Broadcast及相关组件实现简易音乐播放器功能

    目录 前言 项目源码 准备工作 代码编写 页面布局 Service类的创建 主函数的编写 项目心得 前言 在Andriod Studio中使用Broadcast实现了简易音乐播放器的功能.可以进行播放 ...

  9. PyQt5实现简易音乐播放器

    PyQt5实现简易音乐播放器 环境 vscode python 3.10.0 PyQt5 5.15.4 功能目标 能够读取本地的音乐文件,并实现播放的开关.曲目的切换和音量的加减 具体实现 新建一个文 ...

最新文章

  1. Ubuntn删除软件
  2. 【深度学习】LSTM神经网络解决COVID-19预测问题(二)
  3. Windows 2000/NT/XP管理员密码丢失解决方法
  4. [改善Java代码]覆写equals方法必须覆写hashCode方法
  5. 在doc中生成柱状图_Python从CSV文件导入数据和生成简单图表
  6. Unable to execute dex: Multiple dex files define Lcom
  7. 几位无人驾驶领域的杰出科学家
  8. html中form标签的作用style,HTML5中meta常用标签属性说明
  9. jeewx-api.jar入门教程
  10. field list什么意思_什么是生物信息学?
  11. 阿克曼函数Ackerman
  12. 空调基础知识培训课件
  13. vbs格式编程教程提高
  14. Java文件上传接口
  15. 【无人机系统】四轴飞行器及其UAV飞控系统 - 桂林电子科技大学信息科技学院 电子工程系(一)
  16. 链表初始化typedef struct LNode{}LNode,*linklist的理解
  17. vs2017旗舰版_2017年的所有旗舰手机都有明显的妥协。 这是他们告诉我们有关设计的信息。...
  18. 2020最新开发及环境搭建类经典面试题
  19. libcurl简单接口的使用(FTP)
  20. SSH登录及失败解决

热门文章

  1. Ecma 118th GA会议手记
  2. 制作精致闪电天气APP图标的PS教程
  3. 祝大家开工大吉,工作顺利。
  4. 《Nature》子刊发布,IIT科学家模仿“植物的触须”,打造可逆渗透致动的仿生软体机器人
  5. android照片备份软件下载,照片备份云相册app-照片备份云相册安卓版下载v1.5-乐游网安卓下载...
  6. 跟领导关系再好,也别做3件小事,嘴欠手贱,煮熟鸭子会飞
  7. 设计模式【2.2】-- 工厂模式怎么演变成抽象工厂模式?
  8. ubuntu关机或重启出现memtest
  9. 史上最详细:word文档怎么在第三页插入页码,只要7步
  10. python爬虫模式_python爬虫的入门试炼