iOS6下慎用MPMoviePlayerViewController!

这个MPMoviePlayerViewController的事要从何说起呢,嗯……其实主要还是由于在播放视频时按Home键切出引发的问题:

先是测试发现游戏在播放开场视频时按Home键切换到后台后会触发libGPUSupportMercury.dylib: gpus_ReturnNotPermittedKillClient导致crash,关于这个异常大苹果的Technical Q&A QA1766(http://developer.apple.com/library/ios/#qa/qa1766/_index.html)已经交待得很清楚了,简单来说就是应用在处于后台状态时是不允许执行任何OpenGL命令的,包括前台时提交但尚未实际执行的缓冲指令!不过文档中提到的几个关键点我也都按规矩做了处理,稍作跟踪后发现,导致这个异常的原因是在应用播放视频时切到后台之后,MPMoviePlayerPlaybackDidFinishNotification通知被莫名其妙的触发了,导致后续逻辑按照开场视频播放结束开始执行,进而去加载OpenGL贴图,初始化状态等,于是自然被OS认为是违规调用了OpenGL命令,因此被kill掉了!

随后,通过对MPMoviePlayerController的MPMoviePlayerPlaybackStateDidChangeNotification通知消息进行跟踪后发现,当app切换到后台之后,MoviePlayer并没有按照我之前所想的那样,对尚未播放完成的视频做了暂停操作(MPMoviePlaybackStatePaused状态),而是直接切换到了MPMoviePlaybackStateStopped状态,随后发出了视频播放结束的通知!

既然如此,我就按照实际发生的情况,在AppDelegate的applicationWillResignActive:和applicationDidBecomeActive:消息中作了一下状态处理,忽略掉应用后台时收到的视频播放完成通知,这样修改之后,后台调用GL命令的情况就没再出现了。但是,随之而来的又发现了另一个问题,就是视频播放过程中切出再切回来时视频应该以继续的方式接着播放,而由于之前测试发现的stop状态,导致每次应用切回来后都是从头开始播放!搜索一番后发现可以用MPMoviePlayerController的setInitialPlaybackTime:方法设置视频初始播放时间,也就是说需要手动记录视频播放中断时的时间,这个好办,用一个NSTimeInterval保存MPMoviePlaybackStatePaused或应用切出时的currentPlaybackTime即可。

满心欢喜的改完后,却发生了悲剧的事情:真机测试时,发现这种实现方式在iOS5设备上没有问题,虽然切回来时不一定能准确定位到中断时的时间,但也会是在附近继续播放,算是实现了预期的效果,可是在iOS6设备上测试时,发现setInitialPlaybackTime:完全没有起到作用,视频依然是从头播放!这个问题后来在cnrainbird的博客中找到了一丝线索:http://blog.cnrainbird.com/index.php/2012/11/02/jiu_gong_cheng_shi_pei_ios6_he_iphone5_xu_zhi_mpmovieplayercontroller/,但我按照此篇博文里的方式修改了一下后测试发现依然没有效果!不管怎么说,用MPMoviePlayerViewController时的setInitialPlaybackTime在iOS6上不起作用这已经是个不争的事实了,也许是bug!

搜索各种论坛,翻各种博客后,无意间发现了大苹果官方的MoviePlayer示例程序:http://developer.apple.com/library/ios/#samplecode/MoviePlayer_iPhone/Introduction/Intro.html,载下来替换成自己的视频试了一下切出和切入,发现完全没有问题,暂停和继续的时间都和我现在的方法在iOS5设备上看到的一样,细看了一下代码实现后,发现这个例子并没有用MPMoviePlayerViewController而是自己实现了一个继承自UIViewController的封装了MPMoviePlayerController的自定义视图控制器,随后断点跟踪了一下例子里的代码执行逻辑,发现程序切出后,通知回调并没有像我之前的做法那样收到MPMoviePlaybackStateStopped状态通知(同时也没有播放完成的通知!),而就是所想的MPMoviePlaybackStatePaused状态,当然,这些都是在iOS6设备上测试的。继续看代码后发现,示例程序也没有对applicationWillResignActive:和applicationDidBecomeActive:或类似消息做什么特殊处理。因此断定:iOS6下慎用MPMoviePlayerViewController!

替换掉了原来的MoviePlayer视频播放逻辑实现方式,改为和大苹果例子一样的自定义视图控制器封装MPMoviePlayerController的做法后,之前的问题得到了比较完美的解决!

博主友情提示:

如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。