AudioPlaybackManager
该音频播映器基于 AVPlayer 完结在线/本地播映, 在线播映支撑加载本地缓存。支撑设置后台播映信息。支撑长途操控。
可初始化、可单例。兼容 OC 调用。
代码结构

AudioPlaybackManager
为完结根底播映类, 其他功用则别离位于不同文件中, 下边会根据该目录结构来进行对应功用的简单运用解说。
播映设置
根底播映
设置 playerItem
let audio = Audio(audioURL: URL)
AudioPlaybackManager.shared.setupItem(audio, beginTime: 0.0)
针对 playerItem 添加了 3 个监听, 别离是:
-
AVPlayerItem.status
, 监听 playerItem 状况。-
当处于
readyToPlay
状况时, 会在此处获取音频总时长, 一起若autoPlayWhenItemReady = true
时, 则会自动播映。若需要手动播映, 则可在收到
AudioPlaybackManager.readyToPlayNotification
告诉或audioPlaybackManagerRreadyToPlay(_:)
代理办法之后调用play()
办法即可。
-
-
AVPlayerItem.loadedTimeRanges
, 监听缓存加载进展, 同步至loadedTime
。 -
AVPlayerItemDidPlayToEndTime
, 监听播映完结, 同步至playStatus = .playCompleted
。
属性监听
@objc dynamic var playStatus: PlayStatus = .prepare
enum PlayStatus: Int {
case prepare, playing, paused, stop, playCompleted, error
}
-
@objc dynamic var playTime: Float64 = 0
- 默以为 (1/30)s 回调 1 次
-
@objc dynamic var progress: Float = 0
- 默以为 (1/30)s 回调 1 次
-
@objc dynamic var duration: Float64 = 0
-
@objc dynamic var loadedTime: Float64 = 0
以上属性均支撑经过 KVO 监听。
播映操控
-
play()
-
pause()
-
togglePlayPause()
-
stop()
-
switchNext()
- 收到
AudioPlaybackManager.nextTrackNotification
告诉或audioPlaybackManagerNextTrack(_:)
代理办法后从头设置setupItem(_:beginTime:)
。
- 收到
-
switchPrevious()
- 收到
AudioPlaybackManager.previousTrackNotification
告诉或audioPlaybackManagerPreviousTrack(_:)
代理办法后从头设置setupItem(_:beginTime:)
。
- 收到
更多操控
skipForward(_ timeInterval: TimeInterval)
skipBackward(_ timeInterval: TimeInterval)
seekToPositionTime(_ positionTime: TimeInterval)
seekToProgress(_ value: Float)
beginRewind(rate: Float = -2.0)
beginFastForward(rate: Float = 2.0)
endRewindFastForward()
播映被其他 App 影响
中止
当电话、闹钟、其它非官方 App 播映(这里触及到后台播映, 下边会讲)… 时, 若二者不支撑混音播映, 那么当时播映则会被体系暂停。这里自动调用了 pause()
来跟从改变播映状况。
中止康复播映
var shouldResumeWhenInterruptEnded = true
, 若不期望自动康复播映, 可将其置为 false
。
若中止方在完毕播映后告知体系应该告诉其他应用程序其现已停用了音频会话, 那么被中止的音频会话则能够挑选是否继续播映。
一般体系 App 都会对此进行告诉, 而部分第三方 App 或许没对此进行处理, 那么也将不能自动康复播映。
ps: 因为目前没有混音播映的需求, 后续考虑是否要将中止告诉转发给开发者来自主操控暂停/播映。
播映 Route 改变
外设改变触及:
- 从外音播映改为耳机播映,继续播映;
- 耳机播映中,拿掉耳机(AirPods)自动暂停, 戴上继续播映;
整体能够概括为:
switch reason {
case .newDeviceAvailable:
play()
case .oldDeviceUnavailable:
pause()
default: break
}
ps: 其他状况收到 route 改变告诉如 AVAudioSession.Category
改变, 则不在该播映器考虑领域内。
后台播映
- 敞开后台播映权限

- 设置
setActiveSession(_ enabled: Bool)
在播映时设置为 true
, 播映完毕后设置为 false
。假如仅在一个特定的操控器内播映的话, 在履行 deinit
办法中设置为 false
也是个不错的挑选。
ps: 该办法设置 AVAudioSession.Category = .playback
, AVAudioSession.Mode = .default
。会保持应用程序音频在设备静音或屏幕锁守时能够继续播映。
在线播映加载本地缓存
var cacheEnabled: Bool
, 提供了在线播映缓存开关, 默许封闭状况。
ps: 在线播映缓存引用了 VIMediaCache 第三方库, 支撑自定义缓存目录, 默许存储在 tmp
目录下。想详细了解缓存流程的能够去看下, 文章写的很详细。
设置后台播映信息展现
var allowSetNowPlayingInfo: Bool
, 默以为敞开状况。
如需展现, 需要在设置 let audio = Audio(audioURL: URL)
时额定对其后台展现信息相关参数进行设置。
如需获取音频本身音频数据来进行展现, 则设置 useAudioMetadata = true
即可。
若音频不存在相关元数据, 则能够经过其他相关参数来进行设置。
/// Audio url.
open var audioURL: URL
public init(audioURL: URL) {
self.audioURL = audioURL
}
/// -------------- `MPNowPlayingInfoCenter` --------------
/// Set `nowPlayingInfo` using audio metadata.
///
/// Default is `false`.
open var useAudioMetadata: Bool = false
// Note: If `useAudioMetadata` is set to false, then you can set it through the following properties.
/// Audio name.
open var title: String?
/// Album name.
open var albumName: String?
/// Artist.
open var artist: String?
/// Artwork.
open var artworkImage: UIImage?
open var artworkURL: URL?
ps: allowSetNowPlayingInfo = true
时播映进展相关信息会跟从一并设置。
效果图:

长途操控
简单长途操控方法
UIApplication.shared.beginReceivingRemoteControlEvents()
UIApplication.shared.endReceivingRemoteControlEvents()
在 AppDelegate
中完结
func remoteControlReceived(with event: UIEvent?) {
if let event = event, event.type == .remoteControl {
switch event.subtype {
case .remoteControlPlay:
case ...
}
}
}
这种长途操控可满足大部分需求, 而且完结非常简单, 但是存在一个很大的问题, 便是无法完结进展条操控。
项目长途操控方法
选用 MPRemoteCommandCenter
方法。
根底操控功用
activatePlaybackCommands(_ enabled: Bool)
activatePreviousTrackCommand(_ enabled: Bool)
activateNextTrackCommand(_ enabled: Bool)
activateChangePlaybackPositionCommand(_ enabled: Bool)
长按 快进/快退
var remoteControlRewindRate: Float
, 默以为 -2.0
;
var remoteControlFastForwardRate: Float
, 默以为 2.0
;
activateSeekBackwardCommand(_ enabled: Bool)
activateSeekForwardCommand(_ enabled: Bool)
跳动播映
activateSkipForwardCommand(_ enabled: Bool, interval: Int = 0)
activateSkipBackwardCommand(_ enabled: Bool, interval: Int = 0)
ps: 敞开跳动播映会占用 上一首/下一首 方位。
封闭长途操控
在不需要长途操控功用时, 调用 deactivateAllRemoteCommands()
即可完全封闭。
项目
好了, 以上基本便是悉数运用办法了。源代码及 Demo 可访问 Github 进行检查。