由于苹果推送会把一些敏感类消息外流,So 我们采用长连接试的推送服务,网上有此推送的开源项目 传送门在此mpush

此开源项目很好的帮助了国内一些企业对敏感消息推送的保护,但是针对苹果端的推送有一个问题就是后台长连接的时间很短,几分钟内就会被杀掉,So 我们想到在后台放置一个循环静音(是静音啊 不是无声)音频 保证应用程序不会被杀掉。

此代码是swift版的 有兴趣的同学可以翻译成OC

AudioManager.swift

import Foundation
import AVFoundation
@objc
open class AudioManager: NSObject {public static let shared = AudioManager()fileprivate let audioSession = AVAudioSession.sharedInstance()fileprivate var backgroundAudioPlayer: AVAudioPlayer?fileprivate var backgroundTimeLength = 0fileprivate var timer: Timer?// 是否开启后台自动播放无声音乐public var openBackgroundAudioAutoPlay = false {didSet {if self.openBackgroundAudioAutoPlay {self.setupAudioSession()self.setupBackgroundAudioPlayer()} else {if let player = self.backgroundAudioPlayer {if player.isPlaying {player.stop()}}self.backgroundAudioPlayer = niltry? self.audioSession.setActive(false, with: AVAudioSessionSetActiveOptions.notifyOthersOnDeactivation)}}}override init() {super.init()self.setupListener()}deinit {NotificationCenter.default.removeObserver(self)}private func setupAudioSession() {do {try self.audioSession.setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.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: "wusheng1", ofType: "mp3")!))} catch let error {debugPrint("\(type(of:self)):\(error)")}self.backgroundAudioPlayer?.numberOfLoops = -1self.backgroundAudioPlayer?.volume = 0self.backgroundAudioPlayer?.delegate = self}private func setupListener() {NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackground), name: Notification.Name.UIApplicationDidEnterBackground, object: nil)NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: Notification.Name.UIApplicationDidBecomeActive, object: nil)NotificationCenter.default.addObserver(self, selector: #selector(audioSessionInterruption(notification:)), name: Notification.Name.AVAudioSessionInterruption, object: nil)}}
// MARK: - 扩展 监听通知
extension AudioManager {/// 进入后台 播放无声音乐@objc fileprivate 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 fileprivate func didBecomeActive() {self.removeTimer()self.hintBackgroundTimeLength()self.backgroundTimeLength = 0guard self.openBackgroundAudioAutoPlay else {return}self.backgroundAudioPlayer?.pause()do {try self.audioSession.setActive(false, with: AVAudioSessionSetActiveOptions.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 == AVAudioSessionInterruptionType.began.rawValue {// 中断开始,音乐被暂停debugPrint("\(type(of:self)): 中断开始 userinfo:\(userinfo)")} else if interruptionType == AVAudioSessionInterruptionType.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: RunLoopMode.commonModes)}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 {public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {}public func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {debugPrint("\(type(of:self))" + error.debugDescription)}
}

HintTool.swift

import UIKitclass 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!.bringSubview(toFront: hintView)self.hintView = hintView// 消失DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {[weak self] inUIView.animate(withDuration: 0.5, animations: {[weak self] inself?.hintView?.alpha = 0.5}, completion: { (finished) inself?.hintView?.removeFromSuperview()self?.hintView = nil})}}private static func hintView(with message: String) -> UIView {let minWidth = 180.0let maxWidth = 260.0let padding = 10.0let 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 = falsehintView.backgroundColor = UIColor(white: 0, alpha: 0.7)hintView.layer.cornerRadius = 8hintView.layer.masksToBounds = truehintView.frame = viewFramehintView.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 = falsehintLabel.text = messagehintLabel.textColor = UIColor.whitehintLabel.textAlignment = .centerhintLabel.font = fonthintLabel.preferredMaxLayoutWidth = messageSize.widthhintLabel.numberOfLines = 0hintLabel.frame = labelFramehintLabel.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.usesLineFragmentOriginlet attributes = [NSFontAttributeName : font]let contentSize = self.boundingRect(with: boundingSize, options: option, attributes: attributes, context: nil).sizereturn contentSize}
}

使用

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {[AudioManager shared].openBackgroundAudioAutoPlay = YES;
}

iOS 后台播放静音音频保证应用不会被无端杀掉相关推荐

  1. iOS后台音频播放及锁屏界面显示音频信息

    iOS后台播放音乐及用户交互处理 后台播放是任何一个音频软件都支持的功能,在上一篇博客中,详细介绍了使用AVAudioPlayer播放音频的方法,这篇博客将对后台的处理做介绍,关于播放与设置音频的博客 ...

  2. AVAudioPlayer 本地音频设置第三弹:后台播放音频

    AVAudioPlayer 本地音频设置第三弹:后台播放音频 设备/引擎:Mac(11.6)/cocos 开发工具:Xcode(13.0) 开发语言:Objective-c/c++ 开发需求:满足后台 ...

  3. iOS开发系列-音频、视频以及摄像

    --iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制, ...

  4. iOS音频的后台播放总结(后台网络请求歌曲,Remote控制,锁屏封面,各种打断)...

    iOS音频的后台播放总结(后台网络请求歌曲,Remote控制,锁屏封面,各种打断) 2013-12-11 21:13 1416人阅读 评论(0) 收藏 举报  分类: cocoa SDK(139)  ...

  5. iOS - 音频后台播放设置及锁屏界面的显示与控制

    音频后台播放设置 1.先在项目 的Capabilities中进行设置,开启后台模式 2.激活音频会话 其它地方也可以,只要保证能执行到以下代码块的内容即可,这里我选择在AppDelegate.m里设置 ...

  6. iOS从零开始学习直播之音频2.后台播放和在线播放

    本篇主要讲音频的后台播放和在线播放. 后台播放   上一篇写的工程运行之后程序退至后台,发现运行不了,歌停止了,这显然不行,音乐后台播放是标配啊.今天就来讲一下后台播放. 1.在plist文件里,告诉 ...

  7. iOS音频的后台播放 锁屏

    初始化AudioSession和基本配置 音频播放器采用的AVPlayer ,在程序启动的时候需要配置AudioSession,AudioSession负责应用音频的设置,比如支不支持后台,打断等等, ...

  8. iOS音频的后台播放总结

    在没有网络的情况下,音频的后台播放比较简单,google一下可以搜到很多资料,但是如果每次歌曲的请求都是通过网络,就不成了,有时可以也扛不了几首,这里总结下实现方法,可以实现像电台一样的功能,后台播放 ...

  9. iOS 音频的录制、播放及音频文件管理

    文章目录 音频会话 音效播放 音乐播放 音频录制 音频管理 补充:音频队列服务 参考地址 音频会话 在使用Apple设备时,我们注意到有些应用打开音频播放时,其他音频就会终止,而有些应用却可以同时使用 ...

最新文章

  1. 通过构造函数来创建新对象
  2. 在VS2010里可以给JS函数添加代码提示\注释
  3. 如何从机器学习数据中获取更多收益 1
  4. 十步让你成为一名优秀的 Web开发人员
  5. 采访问题 What is your role at XX and what are your responsibilities
  6. ajax连接jsp或servlet,获取MySql为数据
  7. 2018java多线程面试题_2018年最全Java面试通关秘籍汇总集!
  8. 基于MNIST数据集的最优参数的方法的比较
  9. 声卡loopback有什么用_声卡购买须知,别买来又退整麻烦事的
  10. 【领域建模】UML类图工具推荐
  11. JAVA基本IO操作
  12. 计算机系一班班会,天津科技大学计算机学院读书节10102i1班班会.ppt
  13. NoSQLBooster for MongoDB 7.0.5
  14. 不会还有人不知道module、bundle和chunk的区别吧?
  15. 【1】机器人手眼标定:固定向上相机
  16. python 桑基图_流量结构分布图——桑基图(Sankey)
  17. DL实现semantic segmentation
  18. displayblock详解
  19. 微信小程序 瀑布流布局 终极解决方案
  20. 地图慧一直显示服务器,瑞友慧连接服务端

热门文章

  1. div随鼠标移动 酸奶公园
  2. vue emit 之 Property or method “$$v“ is not defined
  3. DRAM的三种刷新方式的刷新周期问题
  4. 梦想CAD提示过期问题的处理
  5. javac 与java_javac中使用-d,以及javac / java中使用-cp介绍
  6. QOS相关基础知识总结
  7. 下一次工业革命:机器人如何帮助人类实现智能化变革
  8. 炉石服务器维护时间,炉石传说维护时间到什么时候 炉石1月18日什么时候维护好...
  9. 博士申请 | 香港科大(广州)陈煌栒老师招收网络/信息物理系统与AI交叉领域全奖博士生...
  10. 小程序云开发无服务器实现实时通信