美文网首页
音频播放工具类

音频播放工具类

作者: smallestt | 来源:发表于2018-01-30 14:10 被阅读0次

实现音频的播放效果及音频列表播放踩坑,效果图: WX20180130-103857.png

device-2018-01-30-111413.png

实现:

1.声明

    private TextView tv_time_start = null;//播放的时间进度
    private MediaPlayer player = null;
    private ImageView iv_go_left = null;//快退
    private ImageView iv_go_right = null;//快进
    private ImageView iv_start = null;//开始播放按钮
    private ImageView iv_pause = null;//暂停播放按钮
    private SeekBar skbProgress = null;// 播放进度条
    private volatile boolean isDrag = false; //互斥量,seekbar拖动或者Timer
    private Thread thread = null;
    private String sourse = "";//音乐路径
    private boolean isPause = false;//是否暂停
    private int tag = -1;//音频列表,点击播放时判断是否为同一Item

解决在音频列表里播放时,因为不同item的点击出现播放紊乱的情况,将播放按钮与position进行绑定,在点击时根据position来区分下一步操作是该暂停还是该下一个item的播放:

 Object object = iv_start.getTag();
        int tag = -1;
        if (null != object) {
            tag = Integer.valueOf(object + "");
            if (this.tag != tag && this.tag != -1) {
                completion();//恢复初始状态
            }
        }
this.tag = tag;

2.播放或者继续播放

  /**
     * 播放or继续播放
     * */
    public void start() {
        iv_start.setVisibility(View.INVISIBLE);
        iv_pause.setVisibility(View.VISIBLE);
        if (true == isPause) {
            player.start();//继续播放
            isPause = false;
            setProgress();
        } else
            play();//开始播放音乐
    }

3.播放音频

    /**
     * 播放音频
     * */
    private void play() {
        try {
            if (null == player) {
                player = new MediaPlayer();
            }
            player.reset();
            player.setDataSource(sourse);
            player.prepare();
            player.start();//开始播放
            isPause = false;
            setProgress();
        } catch (IllegalArgumentException e) {
        } catch (SecurityException e) {
        } catch (IllegalStateException e) {
        } catch (NullPointerException e) {
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.暂停播放

    /**
     * 暂停播放
     * 这里的非空判断,是为了解决列表播放时,滑动的复用导致的NullPointerException异常
     * */
    public void pause() {
        if (null != iv_start)
        iv_start.setVisibility(View.VISIBLE);
        if (null != iv_pause)
        iv_pause.setVisibility(View.INVISIBLE);
        try {
            if (null != player && player.isPlaying() && !isPause) {
                player.pause();//暂停播放
                isPause = true;
            }
        } catch (IllegalStateException e) {
        }
    }

5.进度条设置

 private void setProgress() {
        try {
            skbProgress.setMax(player.getDuration());
            skbProgress.setOnSeekBarChangeListener(new SeekbarmusicEvent());
            player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer arg0) {
                    // TODO Auto-generated method stub
                    completion();
                }
            });
        } catch (IllegalArgumentException e) {
        } catch (SecurityException e) {
        } catch (IllegalStateException e) {
        } catch (NullPointerException e) {
        }
        try {
            thread = new Thread(new SeekBarThread());
            thread.start();
        } catch (
                IllegalStateException e) {
        }
    }

处理拖动seekbar事件

   //处理拖动seekbarmusic事件
    class SeekbarmusicEvent implements SeekBar.OnSeekBarChangeListener {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                                      boolean fromUser) {
            // TODO Auto-generated method stub
            tv_time_start.setText(showTime(seekBar.getProgress()));
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub
            isDrag = true;//拖动seekbar停止timer
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub
            try {
                tv_time_start.setText(showTime(seekBar.getProgress()));
                player.seekTo(skbProgress.getProgress());
                isDrag = false;//开启timer
                thread = new Thread(new SeekBarThread()); // 启动线程
                thread.start();
                if (skbProgress.getProgress() == skbProgress.getMax()) {
                    iv_pause.setVisibility(View.VISIBLE);
                    iv_start.setVisibility(View.INVISIBLE);
                    tv_time_start.setText("00:00");
                    player.seekTo(0);
                    skbProgress.setProgress(0);
                    isPause = false;
                }
            } catch (IllegalStateException e) {
            }
        }
    }

  class SeekBarThread implements Runnable {
        @Override
        public void run() {
            try {
                while (null != player && ! isDrag && player.isPlaying()) {
                    skbProgress.setProgress(player.getCurrentPosition());
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
            } catch (IllegalStateException e) {
            }
        }

    }
 

    /**
     * 根据进度格式化时间
     * */
    public static String showTime(Object time) {
        SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
        formatter.setTimeZone(TimeZone.getTimeZone("00:00"));
        String hms = formatter.format(time);
        return hms;
    }

6.快进/快退

    /**
     * 快进
     * */
    public void forWard() {
        try {
            Log.i("sxh", "forWard");
            if (player != null && player.isPlaying()) {
                int position = player.getCurrentPosition();
                player.seekTo(position + 5000);
            }
        } catch (IllegalStateException e) {
        }
    }

    /**
     * 快退
     * */
    public void backWard() {
        try {
            if (player != null && player.isPlaying()) {
                int position = player.getCurrentPosition();
                if (position > 5000) {
                    position -= 5000;
                } else {
                    position = 0;
                }
                player.seekTo(position);
            }
        } catch (IllegalStateException e) {
        }

    }

7.播放完成后的恢复默认状态

   /**
     * 播放完成
     * 这里的非空判断是为了避免音频列表播放时,因为item的复用导致的异常
     * */
    public void completion() {
        try {
            if (null != iv_start)
                iv_start.setVisibility(View.VISIBLE);
            if (null != iv_pause)
                iv_pause.setVisibility(View.INVISIBLE);
            if (null != tv_time_start)
                tv_time_start.setText("00:00");
            if (null != skbProgress)
                skbProgress.setProgress(0);
            isPause = false;
            if (null != player)
                player.seekTo(0);
        } catch (IllegalStateException e) {

        }
    }

8.停止播放与销毁

  /**
     * 销毁
     * */
    public void destoryPlayer() {
        if (null != player) {
            player.release();
            isPause = false;
        }
    }

    /***
     * 停止播放
     * */
    public void stop(){
        if (null != player)
            player.stop();
    }

列表播放需要注意:

  • 列表滑动时,要停止当前正在播放的item里的音频,并把各个状态恢复初始状态,否则滑动后由于item的复用会导致播放状态混乱
 view_recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (null != adapter)
                    adapter.audioCompletion(); //上方封装的completion()和stop()方法
               
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

            }
        });
  • 音频列表,当前item处于被操作状态的同时去操作下一个item时,要及时将当前状态恢复为初始状态,否则会出现异常,处理方法:将播放按钮与position进行绑定,在播放时判断前后点击的position是否相同,相同的话就根据状态判断是暂停还是继续播放,如果不相同就停止播放并将状态恢复成默认情况。
 ((ViewHolderAudio) holder).iv_play.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String audio = mList.get(position).getVideo();
                    holder.iv_play.setTag(position);
                    mAudioTools.setSource(holder.tv_time_start, holder.sk_bar, holder.iv_play,holder.iv_pause, audio);
                    mAudioTools.start();
                }
            });

//工具类里初始化view方法里
public void setSource(...){
        Object object = iv_start.getTag();
        int tag = -1;
        if (null != object) {
           tag = Integer.valueOf(object + "");
            if (this.tag != tag && this.tag != -1) {
                completion();
            }
        }
    this.tag = tag;
}
  • 当Activity 处于onPause()和onDestroy()状态时,要及时停止播放或者销毁
    @Override
    public void onDestroy() {
        super.onDestroy();
         destoryPlayer();
    }

    @Override
    public void onPause() {
        super.onPause();
          pause();
}

相关文章

网友评论

      本文标题:音频播放工具类

      本文链接:https://www.haomeiwen.com/subject/hqiqzxtx.html