开发时最难走的路,莫过于苹果的套路~
今天给大家分享一个关于后台模式下,如何循环播放音乐的Demo
今天心血来潮,想要写一个音乐播放的软件自己玩.既然是音乐播放,想要玩的舒服,那么支持后台播放是必须的.好在苹果很好实现这个功能,我们只需要代码稍微设置下
NSError *error = nil; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
再把Xcode的后台模式勾选下
这样就可以实现后台的音乐播放了.接下来就是播放器的使用
播放器的选择
- AVAudioPlayer
我们最常用的音乐播放器应该就是AVAudioPlayer了,功能也十分强大,但是他也有一个弊端就在于只能播放单个文件,没有类似播放列表之类的功能,每次播放新的音频的时候需要重新创建对象.强迫症患者慎用.
AVAudioPlayer官方文档:
https://developer.apple.com/reference/avfoundation/avaudioplayer?language=objc
- AVPlayer
AVPlayer用在播放视频比较多一些,但是他本身也是可以播放音频的,
使用范围更广泛,功能也更多,本文通过AVPlayer的子类AVQueuePlayer
实现Demo效果.- AVQueuePlayer可以通过queuePlayerWithItems:传入装有AVPlayerItem的数组创建. AVPlayerItem的创建也十分简单,只需要传入文件对应的URL即可.具体可参考官方文档
官方文档:
https://developer.apple.com/reference/avfoundation/avplayer
https://developer.apple.com/reference/avfoundation/avqueueplayer
- AVQueuePlayer可以通过queuePlayerWithItems:传入装有AVPlayerItem的数组创建. AVPlayerItem的创建也十分简单,只需要传入文件对应的URL即可.具体可参考官方文档
AVQueuePlayer是根据内部的items数组来进行播放的,当前的item播放完毕后,会自动从列表中删除,同时播放下一个.这样就实现了自动播放的效果.当一轮音乐播放完毕的时候,我们只需要将列表重新添加一下即可.
需要注意的地方
1.一开始我将所有播放的item数组用了一个全局变量存储起来,打算用来列表清空后添加,但是当我使用insertItem函数的时候,苹果抛出了一个异常:同一个item最多只能在列队中存在一次.于是尝试removeAllItems
删除之前所有添加item,结果依然抛出相同异常.尝试将播放器置为nil利用数组重新初始化,结果抛出另一个异常:同一个item无法作用于不同的AVPlayer
无论是移除item还是将播放器置为nil都无法解决掉这个问题,只有创建新的列队来添加到尾部,实现循环列表
2.程序会在播放器的音乐播放结束的最后一秒挂起,这时候就无法操作了,普遍解决方案是注册taskID,但是楼主觉得比较麻烦.因为我们使用的是列队播放,和AVAudioPlayer相比有着得天独厚的优势,所以只要在最后一首播放结束前前被删除的列队重新添加进去就好了.
当然,理论说得再多也不如一个Demo来的实在
附上Demo地址:https://github.com/WeiTChen/MyMusci
网友评论