音频播放一直是一个最常用的功能,不管是否是以该功能为主业务的app,音频播放都可以作为一个模块存在于其中。
一般来说,在普通的业务需求中,很少会遇到直接播放本地资源文件的情况,基本都是给一个资源链接再播放。
那么,在一个以音频播放为核心功能的app中,相关延伸的功能也就必须实现:
- 边缓冲边播放。
- 播放进度控制。
- 缓存机制(即播放过一遍的链接再次播放时无需再次请求资源)
- 后台播放以及远程控制响应(从锁屏和控制中心进行的播放控制)
那么为何使用AVPlayer作为播放框架,而不使用市面上其他的第三方封装的流媒体播放框架(AudloStreamer, freeStreamer等)呢?这里说明一下,我个人在工作中遇到的坑。
AudloStreamer是一款历史久远的流媒体播放框架,基于苹果的AudioToolbox封装,功能强大,不仅实现了播放,缓冲,缓存等必备机制,还可提供一些音频数据处理的相关功能,可谓是十分强大。而在我负责的项目中原本使用的也是该框架。此框架作为核心音频播放框架使用,一直表现稳定,并无任何bug出现。但是,iOS13的出现,彻底动摇了此框架的地位。
众所周知,iOS13出现的初期,可谓是烽烟四起,各大app频频出现被无故杀后台的现象,但知道真相的用户毕竟是少数,多数用户会把现象归结于程序本身,认为是程序自身出了bug,才导致的后台无故退出。当然苹果后来也对这种疯狂杀后台的机制做了调整(估计是收到了大量开发者的抗议),但某些机制并未作出调整。
比如,我负责的这个项目也出现了崩溃率暴涨的现象(因iOS杀后台是被系统级的watchDog强行结束进程,因此会被崩溃监听的框架认为是异常退出),而用户并不知道退出的真正原因,只从现象上进行反馈,比如:“为什么我播着播着就停了?”,“为什么从后台打开就重启了?”,“为什么后台播放停止了我在锁屏上点什么都没反应?”等等等等。这一系列反馈的根本原因都是因为我这个项目在后台播放时,莫名其妙的被系统看门狗干掉了。
在这个现象出现的初期,我实在一头雾水,因为崩溃的线程很奇怪,那是一个网络请求使用的线程,而这个网络请求使用的框架更是一个远古的框架,著名的ASIHTTPRequset。而在此之前,整个后台播放的流程运行到此处时并未出现问题,而且崩溃位置被记录到了框架代码内部。由于该框架早已无人维护,因此也无法向框架作者寻求帮助,于是只能自己开始研究。
过程就不多说了,直接说结果。经过一系列的尝试,最终问题锁定在了播放框架上,也就是AudloStreamer。我们都知道,如果想让你的app在后台播放音频,那必须要先启动系统的音频播放通道AVAudioSession。当然,这在之前肯定也是做了的,否则早就出问题了。但是,在iOS13中,当我这个项目退到后台播放时,只要播放结束,下一个音频开始播放之后程序就会被杀死。然而,我尝试使用苹果自己封装的AVAudioPlayer循环播放一个本地音频文件时,却可以正常播放。
这也就解释了为什么之前的崩溃会发生在网络层。请求发出了,等待响应的时候app直接被杀死了,当然是网络请求的进程会报错。所以我得出结论,如果使用苹果封装的音频播放框架,则程序可以正常存活在后台,如果使用自己封装的播放框架,则程序就不能正常在后台存活。
这就是我选择了AVPlayer的主要原因。一个以音频播放为核心功能的app,如果不能正常在后台持续播放那还玩个锤子。而且,