A-A+

iOS 后台播放静音文件 延迟APP的存活

博客主机

创建

AudioManager.swift

import Foundation
import AVFoundation
import UIKit
class AudioManager: NSObject {

static let shared = AudioManager()
fileprivate let audioSession = AVAudioSession.sharedInstance()
fileprivate var backgroundAudioPlayer: AVAudioPlayer?
fileprivate var backgroundTimeLength = 0
fileprivate var timer: Timer?

// 是否开启后台自动播放无声音乐
var openBackgroundAudioAutoPlay = false {
didSet {
if self.openBackgroundAudioAutoPlay {
self.setupAudioSession()
self.setupBackgroundAudioPlayer()
} else {
if let player = self.backgroundAudioPlayer {
if player.isPlaying {
player.stop()
}
}
self.backgroundAudioPlayer = nil
try? self.audioSession.setActive(false, options: AVAudioSession.SetActiveOptions.notifyOthersOnDeactivation)
}
}
}

override init() {
super.init()
self.setupListener()
}
deinit {
NotificationCenter.default.removeObserver(self)
}
private func setupAudioSession() {
do {
try self.audioSession.setCategory(AVAudioSession.Category.playback, options: AVAudioSession.CategoryOptions.mixWithOthers)
try self.audioSession.setActive(false)
} catch let error {
debugPrint("\(type(of:self)):\(error)")
}
}
private func setupBackgroundAudioPlayer() {
do {
self.backgroundAudioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: Bundle.main.path(forResource: "WhatYouWant", ofType: "mp3")!))
debugPrint(Bundle.main.path(forResource: "WhatYouWant", ofType: "mp3")!)
} catch let error {
debugPrint("\(type(of:self)):\(error)")
}
self.backgroundAudioPlayer?.numberOfLoops = -1
self.backgroundAudioPlayer?.volume = 1
self.backgroundAudioPlayer?.delegate = self
}

//主要修改了这里
private func setupListener() {

NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)

NotificationCenter.default.addObserver(self, selector: #selector(audioSessionInterruption(notification:)), name: AVAudioSession.interruptionNotification, object: nil)

}

}

// MARK: - 扩展 监听通知
extension AudioManager {
/// 进入后台 播放无声音乐
@objc public func didEnterBackground() {
self.setupTimer()
guard self.openBackgroundAudioAutoPlay else {return}

do {
try self.audioSession.setActive(true)
} catch let error {
debugPrint("\(type(of:self)):\(error))")
}
self.backgroundAudioPlayer?.prepareToPlay()
self.backgroundAudioPlayer?.play()
}

/// 进入前台,暂停播放音乐
@objc public func didBecomeActive() {
self.removeTimer()
self.hintBackgroundTimeLength()
self.backgroundTimeLength = 0
guard self.openBackgroundAudioAutoPlay else {return}

self.backgroundAudioPlayer?.pause()
do {
try self.audioSession.setActive(false, options: AVAudioSession.SetActiveOptions.notifyOthersOnDeactivation)
} catch let error {
debugPrint("\(type(of:self)):\(error))")
}

}

/// 音乐中断处理
@objc fileprivate func audioSessionInterruption(notification: NSNotification) {
guard self.openBackgroundAudioAutoPlay else {return}
guard let userinfo = notification.userInfo else {return}
guard let interruptionType: UInt = userinfo[AVAudioSessionInterruptionTypeKey] as! UInt? else {return}
if interruptionType == AVAudioSession.InterruptionType.began.rawValue {
// 中断开始,音乐被暂停
debugPrint("\(type(of:self)): 中断开始 userinfo:\(userinfo)")
} else if interruptionType == AVAudioSession.InterruptionType.ended.rawValue {
// 中断结束,恢复播放
debugPrint("\(type(of:self)): 中断结束 userinfo:\(userinfo)")
guard let player = self.backgroundAudioPlayer else {return}
if player.isPlaying == false {
debugPrint("\(type(of:self)): 音乐未播放,准备开始播放")
do {
try self.audioSession.setActive(true)
} catch let error {
debugPrint("\(type(of:self)):\(error)")
}
player.prepareToPlay()
player.play()
} else {
debugPrint("\(type(of:self)): 音乐正在播放")
}
}
}
}
// MARK: - 扩展 定时器任务
extension AudioManager {
fileprivate func setupTimer() {
self.removeTimer()
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerTask), userInfo: nil, repeats: true)
RunLoop.main.add(self.timer!, forMode: RunLoop.Mode.common)
// RunLoop.main.add(self.timer!, forMode: RunLoop.Mode.init(rawValue: ""))
}
fileprivate func removeTimer() {
self.timer?.invalidate()
self.timer = nil;
}
@objc func timerTask() {
self.backgroundTimeLength += 1
}
fileprivate func hintBackgroundTimeLength() {
let message = "本次后台持续时间:\(self.backgroundTimeLength)s"
HintTool.hint(message)
}
}

// MARK: - 扩展 播放代理
extension AudioManager: AVAudioPlayerDelegate {
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {

}
func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
debugPrint("\(type(of:self))" + error.debugDescription)
}
}

再写个提示工具

HintTool.swift

import UIKit

class HintTool {

private var hintView: UIView?

static let shared = HintTool()

static func hint(_ message: String) {
self.shared.showHintView(hintView: self.hintView(with: message))
}

private func showHintView(hintView: UIView) {
guard let window = UIApplication.shared.delegate?.window else {return}
guard self.hintView == nil else {return}

window!.addSubview(hintView)
window!.bringSubviewToFront(hintView)
self.hintView = hintView

// 消失
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
[weak self] in
UIView.animate(withDuration: 0.5, animations: {
[weak self] in
self?.hintView?.alpha = 0.5
}, completion: { (finished) in
self?.hintView?.removeFromSuperview()
self?.hintView = nil
})
}
}

private static func hintView(with message: String) -> UIView {
let minWidth = 180.0
let maxWidth = 260.0
let padding = 10.0
let font = UIFont.systemFont(ofSize: 14)

let messageSize = message.ext_size(withBoundingSize: CGSize(width: maxWidth-2*padding, height: 0) , font: font)

let labelFrame = CGRect(x: 0, y: 0, width: CGFloat(ceilf(Float(messageSize.width))), height: CGFloat(ceilf(Float(messageSize.height))))
let viewFrame = CGRect(x: 0, y: 0, width: max(minWidth, Double(messageSize.width) + padding*2), height: Double(messageSize.height) + padding*2)

let hintView = UIView()
hintView.isUserInteractionEnabled = false
hintView.backgroundColor = UIColor(white: 0, alpha: 0.7)
hintView.layer.cornerRadius = 8
hintView.layer.masksToBounds = true
hintView.frame = viewFrame
hintView.center = CGPoint(x: CGFloat(ceilf(Float(UIScreen.main.bounds.size.width*0.5))), y: CGFloat(ceilf(Float(UIScreen.main.bounds.size.height-100.0))))

let hintLabel = UILabel()
hintView.addSubview(hintLabel)
hintView.isUserInteractionEnabled = false
hintLabel.text = message
hintLabel.textColor = UIColor.white
hintLabel.textAlignment = .center
hintLabel.font = font
hintLabel.preferredMaxLayoutWidth = messageSize.width
hintLabel.numberOfLines = 0
hintLabel.frame = labelFrame
hintLabel.center = CGPoint(x: CGFloat(ceilf(Float(hintView.bounds.size.width*0.5))), y: CGFloat(ceilf(Float(hintView.bounds.size.height*0.5))))

return hintView
}
}

extension String {
func ext_size(withBoundingSize boundingSize: CGSize, font: UIFont) -> CGSize {
let option = NSStringDrawingOptions.usesLineFragmentOrigin
let attributes = [NSAttributedString.Key.font : font]
let contentSize = self.boundingRect(with: boundingSize, options: option, attributes: attributes, context: nil).size
return contentSize
}
}

在viewcontroller里使用 

import UIKit
import AVFoundation

let kBackgroundAudioAutoPlayOpenString = "后台自动播放音乐 - 开启"
let kBackgroundAudioAutoPlayCloseString = "后台自动播放音乐 - 关闭"

class ViewController: UIViewController {

let backgroundModeBtn = UIButton()

override func viewDidLoad() {
super.viewDidLoad()

self.backgroundModeBtn.setTitle(kBackgroundAudioAutoPlayOpenString, for: .normal)
self.backgroundModeBtn.setTitleColor(UIColor.black, for: .normal)
self.backgroundModeBtn.addTarget(self, action: #selector(backgroundModeBtnDidClick), for: .touchUpInside)
self.backgroundModeBtn.backgroundColor = UIColor.cyan
self.view.addSubview(self.backgroundModeBtn)

AudioManager.shared.openBackgroundAudioAutoPlay = false
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.backgroundModeBtn.sizeToFit()
self.backgroundModeBtn.center = self.view.center
}
@objc func backgroundModeBtnDidClick() {
guard let title = self.backgroundModeBtn.title(for: .normal) else {return}

if title == kBackgroundAudioAutoPlayOpenString {
AudioManager.shared.openBackgroundAudioAutoPlay = true
self.backgroundModeBtn.setTitle(kBackgroundAudioAutoPlayCloseString, for: .normal)
} else {
AudioManager.shared.openBackgroundAudioAutoPlay = false
self.backgroundModeBtn.setTitle(kBackgroundAudioAutoPlayOpenString, for: .normal)
}
}

func didBecomeActive() {
debugPrint("\(type(of:self)): 11111")
}

}

在applegate里初始化

private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

AudioManager.shared.openBackgroundAudioAutoPlay = true
return true
}

标签:

给我留言

Copyright © ios教程,苹果粉丝,苹果资讯,ios入门教程,ios学习,ios程序员,ios视频教程,ios粉丝网 保留所有权利.   Theme  Ality

用户登录