如何使用远程推送通知触发AVAudioPlayer播放?

时间:2019-06-15 00:22:21

标签: objective-c apple-push-notifications avaudioplayer avaudiosession

我正在创建一个具有远程触发警报的应用程序。本质上,当远程推送通知到达特定的有效负载时,我试图触发循环播放的MP3文件(当应用程序处于后台时)。

我尝试使用didReceiveRemoteNotification: fetchCompletionHandler:,以便可以通过接收带有特定userInfo有效负载的远程通知来运行代码。

这是我从AppDelegate.m尝试的didReceiveRemoteNotification: fetchCompletionHandler:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  NSString *command = [userInfo valueForKeyPath:@"custom.a.command"];
  if (command) {
    UIApplicationState applicationState = [[UIApplication sharedApplication] applicationState];
    if ([command isEqualToString:@"alarm"] && applicationState != UIApplicationStateActive) {
      // Play alarm sound on loop until app is opened by user
      NSLog(@"playing alarm.mp3");
      NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"alarm" ofType:@"mp3"];      
      NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
      NSError *error;
      self.player = nil;
      self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:&error];
      self.player.numberOfLoops = -1; // Infinitely loop while self.player is playing
      self.player.delegate = self;
      [self.player play];
    }
  }
  completionHandler(UIBackgroundFetchResultNewData);
}

我希望推送通知到达时(应用处于非活动状态或后台),循环音频文件将立即开始播放,但是没有。相反,当我随后将应用程序置于前台时,音频播放意外开始。

此方法缺少什么,和/或其他方法能否更好地工作?

1 个答案:

答案 0 :(得分:0)

您无法在后台启动该应用程序的音频会话。当应用程序处于前台状态时,必须初始化/启动音频会话。如果将应用程序推送到后台,并且前台的另一个应用程序不会中断音频会话,则音频会话可以正确初始化并继续运行。

基于此信息,我想说,您的应用程序可能必须在您处于控制状态和前台时启动音频会话,而在后台运行音频会话。收到推送通知后,使用现有的打开的音频会话将音频输出。

这有严重的局限性,因为其他任何使用专用音频会话的应用程序(例如Netflix)都可能会中断您应用程序的音频会话,并使其无法在播放MP3时播放。

您可能需要考虑预先打包和/或下载MP3,并在推送通知的Sound参数中直接引用它们。

您可以按照本教程来了解如何使用推送通知播放自定义声音:https://medium.com/@dmennis/the-3-ps-to-custom-alert-sounds-in-ios-push-notifications-9ea2a2956c11


func pushNotificationHandler(userInfo: Dictionary<AnyHashable,Any>) {
     // Parse the aps payload
    let apsPayload = userInfo["aps"] as! [String: AnyObject]

    // Play custom push notification sound (if exists) by parsing out the "sound" key and playing the audio file specified
    // For example, if the incoming payload is: { "sound":"tarzanwut.aiff" } the app will look for the tarzanwut.aiff file in the app bundle and play it
    if let mySoundFile : String = apsPayload["sound"] as? String {
        playSound(fileName: mySoundFile)
    }
}

// Play the specified audio file with extension
func playSound(fileName: String) {
    var sound: SystemSoundID = 0
    if let soundURL = Bundle.main.url(forAuxiliaryExecutable: fileName) {
        AudioServicesCreateSystemSoundID(soundURL as CFURL, &sound)
        AudioServicesPlaySystemSound(sound)
    }
}