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

时间:2016-05-20 16:43:44

标签: ios iphone audio avfoundation avaudioplayer

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

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

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

Other questions已经建议这是设计的,应用程序不应该能够从后台播放声音 - 只能继续播放已经播放的声音。我接受这个推理,除了Tile这样做,所以它显然是可能的。一个suggested workaround违反Apple的指导方针,我非常肯定苹果现在会检查。

可能相关的一些细节:

  • 我在Info.plist
  • 中有audio后台模式
  • 我在音频会话中使用AVAudioSessionCategoryPlayback,会话应该处于活动状态(至少setActive:error:声称成功)。
  • 此应用使用蓝牙,但目前不使用bluetooth-central后台模式。

2 个答案:

答案 0 :(得分:2)

实际上,您可以使用AudioServices...个功能之一

  • AudioServicesPlaySystemSound
  • AudioServicesPlayAlertSound
  • AudioServicesPlaySystemSoundWithCompletion

开始在后台播放声音。

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

修改 应用仍然需要audio中的UIBackgroundModes才能在后台播放

从我的测试项目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回调调用的。

答案 1 :(得分:1)

来自官方Apple documentation

  

&#34;播放时自定义声音必须低于30秒。如果是自定义声音   超过该限制,而是播放默认的系统声音。&#34;

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

设置自定义通知声音:

notif.soundName = @"sound.caf";

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