被这个The surface has been released错误纠缠了2天,今天终于解决了,现在整理下思路。
自己练手做了个项目,使用SurfaceView播放视频。但是测试时发现如果播放时来电话,通话结束后不能自动播放。经过百度,重写了onPush和onResume方法,测试通过。但是此时如果按HOME键,再切换回主程序时,视频不能自动播放,并且会报The surface has been released这个错误。
各位大神的见解基本都差不多,说是 在surfaceHolder还没准备好的时候,就调用了MediaPlayer的start()方法。并建议将mediaPlayer.setDisplay(surfaceHolder)放在surfaceCreated中,自己尝试了下,问题并没有解决。最后经过多方查阅,才知道surface的创建在onResume方法之后,但是我确是在onResume方法之中调用的play方法,因此必然会报这个错。
好的,既然知道了问题,那么答案也就在眼前了,我的解决思路是,不采用onPush和onResume这两个方法来判断应用是否在前台。而是用surfaceHolder.addCallback(new SurfaceCallback());来监听,通过surfaceCreated和surfaceDestroyed这两个方法来判断。当然,这样只是解决了HOME键返回的问题,当来电话时是不会调用这两个方法的(但是onPush和onResume方法却会调用,很奇怪,不知道为什么),所以接下来要做的是对来电进行监听。
//获取电话服务
manager = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
// 手动注册对PhoneStateListener中的listen_call_state状态进行监听
manager.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
创建MyPhoneStateListener类,由于OFFHOOK是主动挂断电话,API中没有被动挂断这一状态,所以只能定义一个isCalling用来判断被动挂断这种情况。
private class MyPhoneStateListener extends PhoneStateListener{
@Override
public void onCallStateChanged(int state, String incomingNumber) {
//需要考虑主动挂断和被动挂断两种情况
switch (state){
//空闲
case TelephonyManager.CALL_STATE_IDLE:
System.out.println("电话处于空闲状态......");
//判断通话是否为对方挂断
if (isCalling) {
if (position > 0 && path != null) {
play(position);
position = 0;
}
}
isCalling = false;
break;
//来电
case TelephonyManager.CALL_STATE_RINGING:
System.out.println("电话呼入......电话号码是:"+incomingNumber);
if (mediaPlayer.isPlaying()) {
position = mediaPlayer.getCurrentPosition();
mediaPlayer.stop();
}
isCalling = true;
break;
//主动挂断
case TelephonyManager.CALL_STATE_OFFHOOK:
System.out.println("电话挂断......");
if (position > 0 && path != null) {
play(position);
position = 0;
}
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
最后,千万别忘了注册权限
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
现在。OK,大功告成,无论是电话进来,还是按HOME键返回,当程序切换回来的时候,视频都可以继续播放了!
最后,如果我的经验对你有用,不要吝啬你宝贵的支持,在下面回复下吧!