效果图

编写布局文件

<TextViewandroid:id="@+id/music_name"android:layout_gravity="left"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="未获取"android:textSize="30sp"/><SeekBarandroid:id="@+id/playSeekBar"android:layout_width="395dp"android:layout_height="wrap_content"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:layout_marginLeft="10dp"android:id="@+id/play"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:text="播放"/><TextViewandroid:id="@+id/music_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="未获取"/><Buttonandroid:layout_marginRight="10dp"android:id="@+id/stop"android:layout_alignParentRight="true"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="不单曲循环"/></RelativeLayout>

逻辑部分

private MediaPlayer mediaPlayer=new MediaPlayer();private Button paly;private Button stop;private SeekBar seekBar;private Timer timer;private TextView musictime;private TextView musicname;private File file;private int musictimes=0;private int musictimes_f=0;private int musictimes_s=0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(layout.activity_main);paly=findViewById(id.play);stop=findViewById(id.stop);musictime=findViewById(id.music_time);musicname=findViewById(id.music_name);seekBar = (SeekBar) findViewById(id.playSeekBar);paly.setOnClickListener(this);stop.setOnClickListener(this);permisson();bindViews();}

首先定义了变量在oncreate中获取了空间并调用了申请权限的permisson();函数与控制音乐进度条的bindViews();

申请权限

 public void permisson(){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);}else{initMediaPlay();}}

执行完这个函数会自动调用onRequestPermissionsResult函数

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode){case 1:if (grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){initMediaPlay();}else {Toast.makeText(this,"请打开访问存储空间的权限",Toast.LENGTH_SHORT).show();}break;default:break;}
}

缓冲音乐

在获得权限之后会缓冲音乐调用initMediaPlay();

 private void initMediaPlay(){/* Environment.getExternalStorageDirectory()获取根路径的方式不友好,比如app删除,app对应的图片不删除,保存路径是sd卡根路径替代方案getExternalFilesDir(Environment.DIRECTORY_PICTURES) 注意:前面没有Environment,app删除对应的图片相应删除,保护隐私,保存路径是/storage/emulated/0/Android/data/com.wintec.huashang/files/Pictures*//*File file=new File(Environment.getExternalStorageDirectory(),"");*//* getExternalCacheDir()方法可以将文件放在SD卡的应用关联缓存目录*//*file的用法参考https://blog.csdn.net/lj317499/article/details/112778167*/try {file=new File(getExternalCacheDir(),"music.mp3");mediaPlayer.setDataSource(file.getPath());mediaPlayer.prepare();seekBar.setMax(mediaPlayer.getDuration());musicname.setText(file.getName());}catch (Exception e){e.printStackTrace();}}

这里先将准备好播放的文件放在了应用的SD卡的应用关联缓存目录通过file类获取了文件,再通过mediaPlayer设置了进度条与音乐名称

设置按钮的点击事件

public void onClick(View view) {switch (view.getId()){case id.play:permisson();if ( paly.getText().equals("播放")){mediaPlayer.start();paly.setText("暂停");timer();}else if(paly.getText().equals("暂停")) {mediaPlayer.pause();paly.setText("播放");timer.cancel();}break;case id.stop:if (stop.getText().equals("单曲循环")){stop.setText("不单曲循环");}else {stop.setText("单曲循环");}break;default:break;}
}

这里通过点击按钮切换播放器的播放模式和音乐的播放与暂停并控制启停timer。

 public void timer(){timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {seekBar.setProgress(mediaPlayer.getCurrentPosition());musictimes=seekBar.getMax()-seekBar.getProgress();musictimes_f=musictimes/60000;musictimes_s=(musictimes%60000)/1000;musictime.post(new Runnable() {@Overridepublic void run() {musictime.setText(musictimes_f+":"+musictimes_s);}});if (seekBar.getMax()==seekBar.getProgress() && stop.getText().equals("单曲循环")){mediaPlayer.seekTo(0);mediaPlayer.start();}if (seekBar.getMax()==seekBar.getProgress() && stop.getText().equals("不单曲循环")){musictime.post(new Runnable() {@Overridepublic void run() {mediaPlayer.seekTo(0);seekBar.setProgress(0);onClick(paly);timer.cancel();}});}/*    Log.d(String.valueOf(MainActivity.this),"时间长度"+musictimes_s);*/}},0,100);}

timer中控制着进度条的刷新和音乐剩余时间的刷新以及音乐播放完后控制音乐的再次播放和暂停。

  private void bindViews() {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) {if (mediaPlayer.isPlaying()){mediaPlayer.pause();}}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {permisson();mediaPlayer.seekTo(seekBar.getProgress());mediaPlayer.start();if (paly.getText().equals("播放")){onClick(paly);}}});}

这个函数控制进度条的功能。

最后退出的时候清空timer和 mediaPlayer

 @Overrideprotected void onDestroy() {super.onDestroy();if (mediaPlayer!=null){mediaPlayer.stop();mediaPlayer.release();timer.cancel();timer = null;}}

到这里一个简单的音乐播放器就制作完成了

所有代码

package com.example.playaudiotest;import static com.example.playaudiotest.R.*;
import static com.example.playaudiotest.R.color.*;import androidx.annotation.ColorLong;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;import android.Manifest;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
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.io.IOException;
import java.util.Timer;
import java.util.TimerTask;public class MainActivity extends AppCompatActivity implements View.OnClickListener{private MediaPlayer mediaPlayer=new MediaPlayer();private Button paly;private Button stop;private SeekBar seekBar;private Timer timer;private TextView musictime;private TextView musicname;private File file;private int musictimes=0;private int musictimes_f=0;private int musictimes_s=0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(layout.activity_main);paly=findViewById(id.play);stop=findViewById(id.stop);musictime=findViewById(id.music_time);musicname=findViewById(id.music_name);seekBar = (SeekBar) findViewById(id.playSeekBar);paly.setOnClickListener(this);stop.setOnClickListener(this);permisson();bindViews();}private void initMediaPlay(){/* Environment.getExternalStorageDirectory()获取根路径的方式不友好,比如app删除,app对应的图片不删除,保存路径是sd卡根路径替代方案getExternalFilesDir(Environment.DIRECTORY_PICTURES) 注意:前面没有Environment,app删除对应的图片相应删除,保护隐私,保存路径是/storage/emulated/0/Android/data/com.wintec.huashang/files/Pictures*//*File file=new File(Environment.getExternalStorageDirectory(),"");*//* getExternalCacheDir()方法可以将文件放在SD卡的应用关联缓存目录*//*file的用法参考https://blog.csdn.net/lj317499/article/details/112778167*/try {file=new File(getExternalCacheDir(),"music.mp3");mediaPlayer.setDataSource(file.getPath());mediaPlayer.prepare();seekBar.setMax(mediaPlayer.getDuration());musicname.setText(file.getName());}catch (Exception e){e.printStackTrace();}}@Overridepublic void onClick(View view) {switch (view.getId()){case id.play:permisson();if ( paly.getText().equals("播放")){mediaPlayer.start();paly.setText("暂停");timer();}else if(paly.getText().equals("暂停")) {mediaPlayer.pause();paly.setText("播放");timer.cancel();}break;case id.stop:if (stop.getText().equals("单曲循环")){stop.setText("不单曲循环");}else {stop.setText("单曲循环");}break;default:break;}}public void timer(){timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {seekBar.setProgress(mediaPlayer.getCurrentPosition());musictimes=seekBar.getMax()-seekBar.getProgress();musictimes_f=musictimes/60000;musictimes_s=(musictimes%60000)/1000;musictime.post(new Runnable() {@Overridepublic void run() {musictime.setText(musictimes_f+":"+musictimes_s);}});if (seekBar.getMax()==seekBar.getProgress() && stop.getText().equals("单曲循环")){mediaPlayer.seekTo(0);mediaPlayer.start();}if (seekBar.getMax()==seekBar.getProgress() && stop.getText().equals("不单曲循环")){musictime.post(new Runnable() {@Overridepublic void run() {mediaPlayer.seekTo(0);seekBar.setProgress(0);onClick(paly);timer.cancel();}});}/*    Log.d(String.valueOf(MainActivity.this),"时间长度"+musictimes_s);*/}},0,100);}private void bindViews() {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) {if (mediaPlayer.isPlaying()){mediaPlayer.pause();}}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {permisson();mediaPlayer.seekTo(seekBar.getProgress());mediaPlayer.start();if (paly.getText().equals("播放")){onClick(paly);}}});}@Overrideprotected void onDestroy() {super.onDestroy();if (mediaPlayer!=null){mediaPlayer.stop();mediaPlayer.release();timer.cancel();timer = null;}}public void permisson(){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);}else{initMediaPlay();}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode){case 1:if (grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){initMediaPlay();}else {Toast.makeText(this,"请打开访问存储空间的权限",Toast.LENGTH_SHORT).show();}break;default:break;}}}

安卓开发———简易音乐播放器。Timer,SeekBar,mediaPlayer相关推荐

  1. android开发音乐播放器,Android开发简易音乐播放器

    这里介绍一个简易的音乐播放器,供大家参考,具体内容如下 效果图如下: 但是,由于这是一个简易版的音乐播放器,所播放的音乐只有一首,且被写死,但,操作却十分简单,方便理解! 这是代码的主要设计: 音乐主 ...

  2. JavaScript开发简易音乐播放器

    使用h5开发的歌词联动音乐播放器,html部分代码如下: <div id="box"><img src="images/1.gif" widt ...

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

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

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

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

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

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

  6. .net vue漂亮登录界面_基于 electron-vue 开发的音乐播放器「实践」

    作者:XiaoTuGou 转发链接:https://github.com/SmallRuralDog 前言 基于 electron-vue 开发的音乐播放器,界面模仿QQ音乐. 技术栈electron ...

  7. Android应用开发--MP3音乐播放器滚动歌词实现

    Android应用开发--MP3音乐播放器滚动歌词实现 2013年6月2日  简.美音乐播放器开发记录 -----前话 有网友给我博客评论说,让我借鉴好的Android代码,代码贴出来的时候最好整体先 ...

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

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

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

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

  10. iOS开发:音乐播放器

    /******************       iOS开发:音乐播放器     *****************/ 要求:给button一个触发事件,点击一下播放歌曲,显示暂停提示: 再点击一下 ...

最新文章

  1. 【系统架构师修炼之道】(13):操作系统基础知识——进程基础知识
  2. log4j2 xsd_Log4j 2.x XSD的描述不完整
  3. Aptana插件安装到eclipse和myeclipse的详细过程
  4. wget python3_python wget
  5. JS将数字转换为中文
  6. Joomla2.5模板简明教程
  7. java简单ai聊天_一个hello/hi的简单的网络聊天程序——JAVA
  8. Spring-Data-JPA--增删改查2——自定义接口查询
  9. 将jar包制作成docker镜像
  10. 【Eclipse】启动时报错:No Java virtual machine (已解决)
  11. JVM监控及诊断工具GUI篇之JConsole
  12. 快速批量执行redis命令
  13. itextpdf 更换字体
  14. html图片表情怎么搞,学习使用HTML5/CSS3来制作简单的表情动画
  15. python画鱼骨图_这样做数据可视化驾驶舱,高端大气,一目了然,领导不点赞都难...
  16. MarkDownPad 2实用教程
  17. C# webbrowser爬虫中经常碰到的脚本错误弹出窗口的问题解决
  18. Redhat认证体系
  19. labelme标记图像时JSON标签复制
  20. python对淘宝运营有帮助吗_淘宝运营,有前途吗?

热门文章

  1. dotnet core error 0x80070057
  2. 【Fortran】STOP语句
  3. VMware Workstation左侧不见了,左侧菜单栏不见了
  4. CSS实现优惠券特殊样式的技巧
  5. iOS基础-小Demo--刮开涂层(刮刮乐效果)
  6. A. Diverse Team
  7. MonoJSG:联合语义和几何代价函数的单目3D目标检测(CVPR2022)
  8. 笔记本电脑WIFI图标消失解决方案大全,无WIFI图标也能自由连WIFI上网。
  9. 中国计算机科技成果,中国科技成就有哪些(盘点2020年中国八大黑科技)
  10. DruidDataSource详解部分(一)