day08MediaPlayer完成音乐播放器

本文详细介绍了Android中MediaPlayer的使用,包括其生命周期、常用方法及注意事项。强调了单例模式的应用、异步加载资源以防止UI卡顿、资源回收的重要性以及错误处理策略,以确保流畅的音乐播放体验。
摘要由CSDN通过智能技术生成

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();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值