Android自定义音乐播放器
来源:互联网 发布:linux search命令 编辑:程序博客网 时间:2024/04/30 09:40
因为项目需要,要做一个自定义的音乐播放器,要求简单但是稳定。代码已经调试好了,稳定性还不错吧~考虑到商业保密性就先不上图了,到时产品上市之后再补上。先描述一下功能:音乐播放时,总共有两个元素在动(音乐进度条,模拟现场乐团演奏的方式刷图),上一首、下一首、播完一首自动播下一首、循环播放、搜索相应目录下所有音乐文件、跑马灯效果显示音乐文字。
上代码:
MusicPlayerActivity.java
package com.ideal.swfplayer;/***************************************************************************************************** * 播放TF卡中的音频文件,主要角色是MediaPlayer,详细资料参考http://blog.csdn.net/runninglion/article/details/41909989* * ***************************************************************************************************/ import java.io.File;import java.util.ArrayList;import java.util.List;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import android.os.Bundle; import android.os.Handler;import android.annotation.SuppressLint;import android.app.Activity; import android.content.Intent;import android.view.KeyEvent;import android.widget.ImageView;import android.widget.SeekBar;import android.widget.TextView; @SuppressLint("HandlerLeak") public class MusicPlayerActivity extends Activity { private MediaPlayer mp; private String path,mfilepath; private SeekBar mseekbar; private TextView musicname; private int refress_pic_time=100; private int refress_seekbar_time=500; private ImageView mmusic_pic,mplay ; private int pic_number=0; private String[] ext={".mp3", ".wav",".MP3",".WAV"};//定义我们要查找的文件格式 private List<String> list; private int currIndex=0; private boolean flash_state=false; private int [] pic={R.drawable.music_pic1,R.drawable.music_pic2,R.drawable.music_pic3,R.drawable.music_pic4,R.drawable.music_pic5, R.drawable.music_pic6,R.drawable.music_pic7,R.drawable.music_pic8,R.drawable.music_pic9,R.drawable.music_pic10}; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_music); //初始化UI界面 InitUI(); //初始化配置 InitConfig(); //加载视频 LoadVoice(); } //更新seekbar进度条 Handler handler = new Handler(); Runnable updateThread = new Runnable(){ public void run() { //获得歌曲的长度并设置成播放进度条的最大值 mseekbar.setMax(mp.getDuration()); //获得歌曲现在播放位置并设置成播放进度条的值 mseekbar.setProgress(mp.getCurrentPosition()); //每次延迟refress_seekbar_time毫秒再启动线程 handler.postDelayed(updateThread, refress_seekbar_time); } }; //刷新图片,实现flash效果 Handler pic_handler = new Handler(); Runnable pic_updateThread = new Runnable(){ public void run() { //循环播放十张图片 if(pic_number>=10) pic_number=0; mmusic_pic.setImageResource(pic[pic_number]); pic_number++; //每次延迟refress_seekbar_time毫秒再启动线程 pic_handler.postDelayed(pic_updateThread, refress_pic_time); } }; //初始化UI界面 private void InitUI() {mmusic_pic = (ImageView)this.findViewById(R.id.music_pic);mplay = (ImageView)this.findViewById(R.id.music_play);musicname = (TextView)this.findViewById(R.id.music_name);mseekbar = (SeekBar)this.findViewById(R.id.music_seekbar);} //初始化配置private void InitConfig() {mp=new MediaPlayer();list = new ArrayList<String>();//获得前一个界面传来的文件路径Intent mIntent = getIntent(); path = mIntent.getStringExtra("music_path"); //获得前一个界面传来的音乐搜索目录 mfilepath = mIntent.getStringExtra("file_path"); File file =new File(mfilepath); //查找该目录下所有的音乐文件 search(file,ext);}//加载音频private void LoadVoice() {musicname.setText(GetPathName(path));try{ mp.setDataSource(path);//加载音频,进入Initialized状态。 mp.prepare(); mp.start(); //为MediaPlayer的播放完成讲件绑定市件监听器 mp.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { next(); } }); //加载刷新seekbar进度条 handler.post(updateThread); //十张图刷新 pic_handler.postDelayed(pic_updateThread, refress_pic_time); flash_state=true; }catch (Exception e) {e.printStackTrace();}} // 搜索音乐文件 ,将音乐路径存到list中 private void search(File file, String[] ext) { if (file != null) { if (file.isDirectory()) { File[] listFile = file.listFiles(); if (listFile != null) { for (int i = 0; i < listFile.length; i++) { search(listFile[i], ext); } } } else { String filename = file.getAbsolutePath(); for (int i = 0; i < ext.length; i++) { if (filename.endsWith(ext[i])) { list.add(filename); break; } } } } } //从音乐路径中提取出音乐名字 private String GetPathName(String mpath){ String[] strarray=mpath.split("/"); return strarray[strarray.length-1]; } //上一首 private void previous() { if((currIndex-1)>=0){ currIndex--; if (list.size() > 0 && currIndex < list.size()) { musicname.setText(GetPathName(list.get(currIndex))); path = list.get(currIndex); //该句的作用是消除上一次pm的资源,让mp回到ide状态,可了解它的生命周期 mp.reset(); try{ //必须先执行setDataSource之后才能执行prepare mp.setDataSource(path);//加载音频,进入Initialized状态。 mp.prepare();//进入prepared状态。 mp.start(); //监听播放完成 mp.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { //播放完成之后自动跳到下一首 next(); } }); //加载音乐进度条与刷图 if(!flash_state){ handler.post(updateThread); pic_handler.postDelayed(pic_updateThread, refress_pic_time); } }catch (Exception e) {e.printStackTrace();} }else{ } }else{ currIndex=list.size()-1; if (list.size() > 0 && currIndex < list.size()) { musicname.setText(GetPathName(list.get(currIndex))); path = list.get(currIndex); mp.reset(); try{ mp.setDataSource(path); //加载音频,进入Initialized状态。 mp.prepare();//进入prepared状态。 mp.start(); mp.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { next(); } }); if(!flash_state){ handler.post(updateThread); pic_handler.postDelayed(pic_updateThread, refress_pic_time); } }catch (Exception e) {e.printStackTrace();} }else{ } } } //下一自首 private void next() { if(currIndex+1<list.size()){ currIndex++; if (list.size() > 0 && currIndex < list.size()) { musicname.setText(GetPathName(list.get(currIndex))); path = list.get(currIndex); mp.reset(); try{ mp.setDataSource(path); //加载音频,进入Initialized状态。 mp.prepare();//进入prepared状态。 mp.start(); //为MediaPlayer的播放完成讲件绑定市件监听器 mp.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { next(); } }); if(!flash_state){ handler.post(updateThread); pic_handler.postDelayed(pic_updateThread, refress_pic_time); } }catch (Exception e) {e.printStackTrace();} }else{ } }else{ currIndex=0; if (list.size() > 0 && currIndex < list.size()) { musicname.setText(GetPathName(list.get(currIndex))); path = list.get(currIndex); mp.reset(); try{ mp.setDataSource(path); //加载音频,进入Initialized状态。 mp.prepare();//进入prepared状态。 mp.start(); mp.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { next(); } }); if(!flash_state){ handler.post(updateThread); pic_handler.postDelayed(pic_updateThread, refress_pic_time); } }catch (Exception e) {e.printStackTrace();} }else{ } } } //检测监听事件public boolean onKeyDown(int keyCode, KeyEvent event) {//下一首if (keyCode == KeyEvent.KEYCODE_R) { next(); //上一首} else if (keyCode == KeyEvent.KEYCODE_L) {previous(); //暂停或开始} else if (keyCode == KeyEvent.KEYCODE_S) {if(!mp.isPlaying()){mp.start();handler.post(updateThread); pic_handler.postDelayed(pic_updateThread, refress_pic_time); flash_state=true;mplay.setImageResource(R.drawable.music_stop);//设置暂停标记}else{mp.pause();handler.removeCallbacks(updateThread);pic_handler.removeCallbacks(pic_updateThread);flash_state=false;mplay.setImageResource(R.drawable.music_play);//设置暂停标记}//退出} else if (keyCode == KeyEvent.KEYCODE_B) {//这两句很重要,如果不加这两句而直接退出会出现异常,原因是该线程还未终止pic_handler.removeCallbacks(pic_updateThread);handler.removeCallbacks(updateThread);if (mp != null) {// 如果为空,我们调用释放资源的方法时就会出现空指针异常。 mp.release();// 释放音频资源,一定要释放,不然会造成推出之后还播放音乐以及内存异常溢出 mp = null; }MusicPlayerActivity.this.finish();} return super.onKeyDown(keyCode, event);}}
虽然没有很核心的算法,但是读者可以参考下具体实现的一些细节处理。比如说怎么处理MediaPlayer的生命周期,关掉应用之前必须释放音乐资源,释放音乐之前必须要先杀死相关进程,否则会退出异常。读者如有疑问可以提出,在线回答~
0 0
- Android自定义音乐播放器
- android音乐播放器播放音乐卡
- Android 音乐播放 类似音乐播放器
- android 音乐播放器
- Android 音乐播放器
- android 音乐播放器
- Android音乐播放器
- Android--音乐播放器
- Android音乐播放器
- android 音乐播放器
- Android音乐播放器
- Android 音乐播放器
- Android音乐播放器
- Android音乐播放器
- Android:音乐播放器
- Android 音乐播放器。
- android 音乐播放器
- Android--音乐播放器
- 快速搭建Web环境 Angularjs + Express3 + Bootstrap3
- opencv 3.0 windows 计时函数 timer
- STM32 学习十 Flash下载与调试
- Delphi 与 C/C++ 数据类型对照表(转)
- getline基本用途
- Android自定义音乐播放器
- Java泛型数组转换处理
- 排序算法
- [ASP.NET-V] SQL Server 2008数据库的备份与还原
- Effective C++ (笔记) : 条款11 -- 条款17
- 【East!模拟赛 Round_VI】(YGY_Round) 题目
- R语言安装包出现Warning:unable to move temporary installation ** to ** 的一个解决思路
- 家庭物联网系统设计之以太网通信
- Designing an Adaptive Security Architecture to Protect Against Advanced Threats