在iOS上开始在后台播放声音?

我正在尝试做类似于Tile.app的事情 。 当它显示通知时,它会播放声音。 这似乎很简单 – 使用UILocalNotification并包含声音文件名。 但是本地通知将声音限制在不超过30秒,并且Tile的声音持续播放的时间比这长得多。 我希望它会循环播放,并且一直持续到我再也无法忍受噪音了。

即使手机的静音开关打开,声音也会播放,本地通知不会发生这种情况。 出于这些原因, UILocalNotification似乎已经出局。

我想也许我可以发布一个纯文本的本地通知,让我的应用播放声音。 但是使用AVAudioPlayerplay方法返回NO并且声音不播放。

其他问题表明这是设计的,应用程序不应该能够从后台播放声音 – 只能继续播放已经播放的声音。 我接受这个推理,除了Tile这样做,所以它显然是可能的。 一个建议的解决方法违反了Apple的指导方针,我很确定Apple现在会检查。

一些可能相关的细节:

  • 我在Info.plist中有audio后台模式
  • 我在音频会话上使用AVAudioSessionCategoryPlayback ,并且会话应该是活动的(至少, setActive:error:声明成功)。
  • 此应用程序使用蓝牙,但目前不使用bluetooth-central后台模式。

实际上你可以使用AudioServices...函数之一

  • AudioServicesPlaySystemSound
  • AudioServicesPlayAlertSound
  • AudioServicesPlaySystemSoundWithCompletion

开始在后台播放声音。

我不确定可以提交给AudioServicesCreateSystemSoundID的声音长度,因为我只用短循环声音检查振铃,但这个API与通知无关,因此可能超过30秒限制。

编辑:应用程序仍然需要UIBackgroundModes audio才能在后台播放

从我的测试项目appDelegate,iOS 9.3.1中删除

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // test sound in foreground. registerAndPlaySound() return true } func applicationDidEnterBackground(application: UIApplication) { var task = UIBackgroundTaskInvalid task = application.beginBackgroundTaskWithName("time for music") { application.endBackgroundTask(task) } // dispatch not required, it's just to simulate "deeper" background let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(5 * Double(NSEC_PER_SEC))) dispatch_after(delayTime, dispatch_get_main_queue()) { self.registerAndPlaySound() } } func registerAndPlaySound() { var soundId: SystemSoundID = 0 let bundle = NSBundle.mainBundle() guard let soundUrl = bundle.URLForResource("InboundCallRing", withExtension: "wav") else { return } AudioServicesCreateSystemSoundID(soundUrl, &soundId) AudioServicesPlayAlertSound(soundId) } 

更新

在那里我使用beginBackgroundTask来启动声音只是在另一个项目中在后台执行代码的最简单方法类似于registerAndPlaySound代码是从没有后台任务的PushKit回调中调用的。

从官方Apple文档 :

“播放时自定义声音必须低于30秒。如果自定义声音超过此限制,则会播放默认系统声音。”

您无法使UILocalNotication循环播放声音。 您可以使用30秒的时间间隔再次安排它,但那个将是另一个警报的调度。

要设置自定义通知声音:

 notif.soundName = @"sound.caf"; 

确保声音实际上在您的应用程序包中,格式正确(线性PCM或IMA4 – 几乎任何解释如何转换iOS声音的地方都会告诉您如何操作),并且不到30秒。