MediaPlayer
生命周期
MediaPlayer常用的方法:
void setDataSource(String path) :通过一个具体的路径来设置MediaPlayer的数据源,path可以是本地的一个路径,也可以是一个网络路径
int getCurrentPosition() 获取当前播放的位置
int getAudioSessionId() 返回音频的session ID
int getDuration() 得到文件的时间
boolean isLooping () 是否循环播放
boolean isPlaying() 是否正在播放
void pause () 暂停
void start () 开始
void stop () 停止
void prepare() 同步的方式装载流媒体文件。
void prepareAsync() 异步的方式装载流媒体文件。
void reset() 重置MediaPlayer至未初始化状态。
void release () 回收流媒体资源。
void seekTo(int msec) 指定播放的位置(以毫秒为单位的时间)
void setLooping(boolean looping) 设置是否单曲循环
setOnCompletionListener(MediaPlayer.OnCompletionListener listener) 网络流媒体播放结束时回调
setOnErrorListener(MediaPlayer.OnErrorListener listener) 发生错误时回调 **
setOnPreparedListener(MediaPlayer.OnPreparedListener listener):当装载流媒体完毕的时候回调。
注意:reset方法是将数据清空。 release方法是将媒体对象回收掉
MediaPlayer使用注意的地方:
1。尽量保证在一个App中只有MediaPalyer对象(单例模式)
在使用start()播放流媒体之前,需要装载流媒体资源。这里最好使用prepareAsync()用异步的方式装载流媒体资源。因为流媒体资源的装载是会消耗系统资源的,在一些硬件不理想的设备上,如果使用prepare()同步的方式装载资源,可能会造成UI界面的卡顿,这是非常影响用于体验的。因为推荐使用异步装载的方式,为了避免还没有装载完成就调用start()而报错的问题,需要绑定MediaPlayer.setOnPreparedListener()事件,它将在异步装载完成之后回调。异步装载还有一个好处就是避免装载超时引发ANR((Application Not Responding)错误。
2。使用完MediaPlayer需要回收资源。MediaPlayer是很消耗系统资源的,所以在使用完MediaPlayer,不要等待系统自动回收,最好是主动回收资源。
3。对于单曲循环之类的操作,除了可以使用setLooping()方法进行设置之外,还可以为MediaPlayer注册回调函数,MediaPlayer.setOnCompletionListener(),它会在MediaPlayer播放完毕被回调。
4。因为MediaPlayer一直操作的是一个流媒体,所以无可避免的可能一段流媒体资源,前半段可以正常播放,而中间一段因为解析或者源文件错误等问题,造成中间一段无法播放问题,需要我们处理这个错误,否则会影响Ux(用户体验)。可以为MediaPlayer注册回调函数setOnErrorListener()来设置出错之后的解决办法,一般重新播放或者播放下一个流媒体即可。
package com.example.day08_mediaplayer;
import android.media.MediaPlayer;
import java.io.IOException;
import java.util.ArrayList;
/**
* 单例模式:饿汉+懒汉(双重校验锁)
*
* */
public class MediaPalyerUtils {
ArrayList<Music> list;
int current_item;
int mode;//0单曲 1顺序 2随机
public static final int MODE_DANQU=0;
public static final int MODE_SHUNXU=1;
public static final int MODE_SUIJI=2;
MediaPlayer mediaPlayer;
private MediaPalyerUtils(){
mediaPlayer=new MediaPlayer();
//添加播放完毕的监听
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
switch (mode){
case MODE_DANQU:
play(current_item);
break;
case MODE_SHUNXU:
next();
break;
case MODE_SUIJI:
int num= (int) Math.random()*list.size();
play(num);
break;
}
}
});
}
private static MediaPalyerUtils mediaPalerUtils;//懒汉
public static MediaPalyerUtils getInstance(){
if(mediaPalerUtils==null){
synchronized (String.class){
if(mediaPalerUtils==null){
mediaPalerUtils=new MediaPalyerUtils();
}
}
}
return mediaPalerUtils;
}
public void setList(ArrayList<Music> list){
this.list=list;
}
public void play(int position){
if(mediaPlayer!=null){
mediaPlayer.reset();//重置一下
try {
mediaPlayer.setDataSource(list.get(position).getPath());//设置新的资源
mediaPlayer.prepare();//准备
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();//准备完成就开始播放
}
});
current_item=position;
}
}
public void start(){
if (mediaPlayer!=null){
mediaPlayer.start();
}
}
public void pause(){
if (mediaPlayer!=null){
mediaPlayer.pause();
}
}
public void pre(){
if(mediaPlayer!=null){
if(current_item==0){//如果是第一首
current_item=list.size()-1;//最后一首
}else{
current_item--;
}
play(current_item);
}
}
public void next(){
if(mediaPlayer!=null){
if(current_item==list.size()-1){
current_item=0;
}else{
current_item++;
}
play(current_item);
}
}
public int mode(){
if(mode==0){
mode=1;
}else if(mode==1){
mode=2;
}else{
mode=0;
}
return mode;
}
public long getDuration(){
if(mediaPlayer!=null){
return mediaPlayer.getDuration();
}
return 0;
}
public long getCurrent(){
if(mediaPlayer!=null){
return mediaPlayer.getCurrentPosition();
}
return 0;
}
public void seekto(int position){
if(mediaPlayer!=null){
mediaPlayer.seekTo(position);
}
}
public void release(){
if(mediaPlayer!=null){
mediaPlayer.stop();//停止
mediaPlayer.release(); //弄死
mediaPlayer=null;//垃圾回收机制回收掉 火葬
}
}
}
package com.example.day08_mediaplayer;
public class Music {
private String path;
private String name;
public Music(String path, String name) {
this.path = path;
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.example.day08_mediaplayer;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.IntentFilter;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button bt_start,bt_pre,bt_next,bt_mode;
RecyclerView recyclerView;
SeekBar seekBar;
boolean flag = true;
Timer timer;
ArrayList<Music> list=new ArrayList<>();
BaseRVAdapter<Music> musicBaseRVAdapter;
@SuppressLint("HandlerLeak")
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==101){
long duration = MediaPalyerUtils.getInstance().getDuration();
long current = MediaPalyerUtils.getInstance().getCurrent();
seekBar.setMax((int) duration);
seekBar.setProgress((int) current);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initdate();
inittimer();
}
private void inittimer() {
timer= new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(101);
}
},0,100);
}
private void initdate() {
ContentResolver contentResolver = getContentResolver();
Uri uri= MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor query = contentResolver.query(uri, null, null, null, null);
while (query.moveToNext()){
String data = query.getString(query.getColumnIndex(MediaStore.Audio.Media.DATA));
String name = query.getString(query.getColumnIndex(MediaStore.Audio.Media.TITLE));
Music music = new Music(data, name);
list.add(music);
}
MediaPalyerUtils.getInstance().setList(list);
musicBaseRVAdapter=new BaseRVAdapter<Music>(list,this,R.layout.item) {
@Override
public void bind(BaseViewHolder baseViewHolder, final int i) {
baseViewHolder.setTextViewtext(R.id.tv_name,list.get(i).getName());
//设置点击
baseViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaPalyerUtils.getInstance().play(i);
}
});
}
};
recyclerView.setLayoutManager(new LinearLayoutManager(this));
DividerItemDecoration dividerItemDecoration=new DividerItemDecoration(this,DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setAdapter(musicBaseRVAdapter);
}
private void initView() {
bt_start=findViewById(R.id.btstart);
bt_pre=findViewById(R.id.btpre);
bt_next=findViewById(R.id.btnext);
bt_mode=findViewById(R.id.btmode);
recyclerView=findViewById(R.id.rev);
seekBar=findViewById(R.id.seekbar);
bt_start.setOnClickListener(this);
bt_pre.setOnClickListener(this);
bt_next.setOnClickListener(this);
bt_mode.setOnClickListener(this);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { }
@Override
public void onStartTrackingTouch(SeekBar seekBar) { }
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//获得音乐的最大值
seekBar.setMax((int) MediaPalyerUtils.getInstance().getDuration());
//获得进度条进度 给音乐设置
int progress = seekBar.getProgress();
MediaPalyerUtils.getInstance().seekto(progress);
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btstart:
if (flag==false){
bt_start.setBackgroundResource(R.mipmap.zt);
MediaPalyerUtils.getInstance().start();
flag=true;
}else {
bt_start.setBackgroundResource(R.mipmap.bf);
MediaPalyerUtils.getInstance().pause();
flag=false;
}
break;
case R.id.btpre:
MediaPalyerUtils.getInstance().pre();
break;
case R.id.btnext:
MediaPalyerUtils.getInstance().next();
break;
case R.id.btmode:
int num = MediaPalyerUtils.getInstance().mode();
if(num==0){
// bt_mode.setText("单曲");
bt_mode.setBackgroundResource(R.mipmap.danquxunhuan);
}else if(num==1){
// bt_mode.setText("顺序");
bt_mode.setBackgroundResource(R.mipmap.shunxubofang);
} else {
// bt_mode.setText("随机");
bt_mode.setBackgroundResource(R.mipmap.suiji);
}
break;
}
}
}
package com.example.day08_mediaplayer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class BaseViewHolder extends RecyclerView.ViewHolder {
//集合存储控件
SparseArray<View> hashMap=new SparseArray<>();//节省内存
public BaseViewHolder(@NonNull View itemView) {
super(itemView);
}
//TODO 1 提供一个根据id查找控件
public View getView(int id){
//先从集合中获取
View view=hashMap.get(id);
if(view==null){
//从布局拿
view=itemView.findViewById(id);
//集合存储一份
hashMap.put(id,view);
}
return view;
}
interface MyList{
public void dianji();
}
public void setOnClickL(int id, final MyList myList){
View view = getView(id);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myList.dianji();
}
});
}
//根据id给该TextView控件设置值
public void setTextViewtext(int id,String text){
//通过map集合
TextView textView = (TextView)getView(id);
if(textView!=null){
textView.setText(text);
}
}
//根据id给该ImageView件设置值
public void setImageSrc(int id,int src){
//通过map集合
ImageView view = (ImageView) getView(id);
if(view!=null){
view.setImageResource(src);
}
}
//imageView来自网络图片
public void setImageurl(int id,String url){
//通过map集合
ImageView view = (ImageView) getView(id);
if(view!=null){
//picasso或者glide
}
}
//imageView来自SD卡
public void setImagesd(int id,String filepath){
//通过map集合
ImageView view = (ImageView) getView(id);
if(view!=null){
Bitmap bitmap = BitmapFactory.decodeFile(filepath);
view.setImageBitmap(bitmap);
}
}
}
package com.example.day08_mediaplayer;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
//
public abstract class BaseRVAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
ArrayList<T> list;//泛型传进来
Context context;
int layout_id;//布局id传进来
public BaseRVAdapter(ArrayList<T> list, Context context, int layout_id) {
this.list = list;
this.context = context;
this.layout_id = layout_id;
}
//创建ViewHolder
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(layout_id, viewGroup, false);
return new BaseViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder baseViewHolder, final int i) {
//不能写具体的绑定数据逻辑
bind(baseViewHolder,i);
}
public abstract void bind(BaseViewHolder baseViewHolder, int i);
@Override
public int getItemCount() {
return list.size();
}
}