您的位置:首页 > 理论基础 > 计算机网络

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

2016-01-13 15:11 651 查看
在近期的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不然多次调用之后,会出现ANRfinal 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左右。具体原因不可知。这里也请大家提供合理的解决方案。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: