Android MediaPlayer 播放器网络音频播放总结

        在近期的Android 系统MediapPalyer使用中,碰到了不少问题。其中一些问题也是在特殊的条件下才会出现,尝试很多方法才解决。这里做了总结,也跟大家分享一下:

1.播放器需要多线程实现

        一般我们会把MediaPlayer放到Service中,做播放相关的逻辑操作。但是因为Service也是在主线程中,如果播放器内部发生阻塞就会导致整个UI线程阻塞。尤其播放网络资源的时候,播放器的prepare()方法会缓存足够的资源才会播放。这里建议新建一个播放线程控制MediaPlayer的播放。这里我是通过android.os.HandlerThread和Handler实现控制子线程播放操作。

2.网络问题较差时,mediaPlayer.prepare()阻塞线程问题的解决

           楼主开始调用播放代码如下。经过测试当网速不好的情况下(10kB)一下。播放线程会卡在

 mediaPlayer.prepare()的内部方法中。期间使用了几个方法:
     1.将mediaPlayer.prepare()换成mediaPlayer.prepareAsync()使用异步准备的方式。经过测试用异步的方式,当频繁切换的时候界面会出现ANR。原因应该是多线程控制的问题。经过查资料需要在mediaPlayer.reset()之前调用stop的方法。这样做的确界面不ANR,但是因为调用的状态不合法会出现IllegalStateException异常。并且这样也会让播放器内部出现问题。在调用mediaPlayer.setDataSource(path)的时候返回各种不同的错误。

 
  

      try {
            mediaPlayer.reset();
            mediaPlayer.setDataSource(path);
            mediaPlayer.prepare();
            mediaPlayer.start();
        catch (IllegalArgumentException e) {
        }
        catch (SecurityException e) {
        }
        catch (IllegalStateException e) {
        }
        catch (IOException e) {
        }
        catch (NullPointerException e) {
        }
        2.因为第一种方案问题更多,之后我还是继续使用 mediaPlayer.prepare()方法。想通过线程的中断来解决问题。因为是阻塞在MediapPalyer的内部只能通过两种方案,一种就是让MediapPalyer内部报异常,一种就是强制结束线程。这里尝试第一种方案的时候发现。当播放线程阻塞的时候 mediaPlayer.prepare() ,在主线程调用 mediaPlayer.stop()方法可以让prepare方法报 IllegalStateException(经过测试这个是必现的,API中有stop方法调用合法状态)。解决方案具体如下:当播放新歌曲的时候,如果发现播放线程阻塞了,也就是当前的状态是preparing状态,主线程中调用mediaPlayer.stop()方法结束子线程阻塞,销毁掉当前的播放器,重新初始化播放器。延迟1s后播放新的歌曲。这里做延迟的原因是为了防止界面频繁点击新的歌曲。如果不延时,将会在初始化的地方出现ANR。

            //让阻塞的播放线程报异常结束注册
            mediaPlayer.stop();
            //这里必须起线程调用release不然多次调用之后,会出现ANR
            final MediaPlayer releaseMediaPlayer = mediaPlayer;
            new Thread() {
                public void run() {
                    releaseMediaPlayer.release();
                };
            }.start();
          //重新初始化的原因是因为抛出异常之后播放器内部会出现问题,几次之后就报错误无法播放。
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setOnCompletionListener(this);
            mediaPlayer.setOnErrorListener(this);
            mediaPlayer.setOnBufferingUpdateListener(this);
            mediaPlayer.setOnInfoListener(this);
            mediaPlayer.setOnPreparedListener(this);
        }
        catch (Exception e) {
            e.printStackTrace();
        }

3.MediapPalyer OnPreparedListener的作用
        因为我是调用的 mediaPlayer.prepare();方法,所以就没有在OnPreparedListener回调方法Onprepared方法中调用mediaPlayer.start()方法进行播放。在部分的android设备上也是没有问题的。但是经过测试有个设备会偶现mediaPlayer(-38,0)错误(这里错误是在执行prepare()的方法时出现,还没有执行到start()方法)。通过log也发现。如果顺序执行,mediaPlayer.start()方法的确是执行onPrepared方法之前。然后我就把mediaPlayer.start()写到Onprepared()的回调方法中。经过测试不会出现这个偶现的问题。在这里问题解决方案存在疑问,也请大神们指点一下。

4.mediaPlayer.getCurrentPosition()播放过程中会出现的误差
       为了实现一个当播放器播放到最大缓冲的位置(播放器之后不能再播放)提示“加载中”。这里简单的实现了一下,大致的方案如下:在刷新播放进度的方法中,判断当前的播放进度和上一次的播放进度。如果当前精度小于等于上一次的播放进度,就提示“加载中”。经过测试发现,网络较差时的确存在本次播放进度比上一次播放进度小的问题,差值有时候会很大会有几s左右。具体原因不可知。这里也请大家提供合理的解决方案。




 
  

       

你可能感兴趣的:(Android MediaPlayer 播放器网络音频播放总结)