2017-06-21 208 views
1

我正在使用[MPMusicPlayerController applicationMusicPlayer]播放Apple音乐。 (AVPlayer和AVAudioPlayer不适用于Apple Music。)在后台播放Apple音乐

在背景中,我需要知道歌曲何时结束,以便播放下一首歌曲。不幸的是,当应用程序在后台时,MPMusicPlayerControllerPlaybackStateDidChangeNotification未被触发。

所以我创建了一个后台任务,使用beginBackgroundTaskWithExpirationHandler,它每秒触发一次NSTimer检查歌曲的结尾。我有音频背景模式设置,但我的任务仍然只有3分钟。这是我的理解,如果我使用音频背景模式,我的任务将获得无限的时间。这不正确吗?如果不是,我该如何处理?其他人肯定会遇到这种情况。

回答

0

我在AppStore中发布了几乎相同的应用程序。 它使用[MPMusicPlayerController applicationMusicPlayer]播放歌曲。

是的,MPMusicPlayerControllerPlaybackStateDidChangeNotification没有来到后台应用程序。 因此,我使用NSTimer确定歌曲何时结束。 您将NSTimer设置为1秒。我将NSTimer设置为歌曲播放时间段。即当歌曲有3分15秒时,我将NSTimer设定为3分15秒。

当用户暂停音乐时,我暂停NSTimer。 当用户恢复音乐时,我将NSTimer设置为歌曲的休息时间。

它工作得很好。 我希望这可以帮助你。 对不起我的英语。


您可能需要的步骤;

  1. 在能力设置中设置音频背景模式。 (你完成)
  2. 在App Delegate中使用beginBackgroundTaskWithExpirationHandler。
 
    - (void)applicationWillResignActive:(UIApplication *)application 
    { 
     _bgid = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) 
     { 
      [[UIApplication sharedApplication] endBackgroundTask:_bgid]; 

      _bgid = UIBackgroundTaskInvalid; 
     }]; 
    } 

    - (void)applicationDidBecomeActive:(UIApplication *)application 
    { 
     if (_bgid != UIBackgroundTaskInvalid) 
     { 
      [[UIApplication sharedApplication] endBackgroundTask:_bgid]; 
     } 
    } 


3.使用的NSTimer在非重复模式。

 

    #import "NMCountdownTimer.h" 

    @interface NMCountdownTimer() 
    { 
    @private 
     NSTimer *_timer; 
     NSTimeInterval _rest; 
     NMMethodCompletion _completion; 
    } 
    @end 

    @implementation NMCountdownTimer 

    - (void)start:(NSTimeInterval)secs completion:(NMMethodCompletion _Nullable)completion 
    { 
     _completion = completion; 

     if (secs > 0.0f) 
     { 
      NSLog(@"[ ] start (secs:%f)", secs); 
      _timer = [NSTimer scheduledTimerWithTimeInterval:secs target:self selector:@selector(fired) userInfo:nil repeats:FALSE]; 
      _rest = 0.0f; 
     } 
    } 

    - (void)pause 
    { 
     if (_timer && (_rest == 0.0f)) 
     { 
      _rest = [[_timer fireDate] timeIntervalSinceReferenceDate] - [[NSDate date] timeIntervalSinceReferenceDate]; 

      NSLog(@"[ ] pause (rest:%f)", _rest); 

      [_timer invalidate]; 
      _timer = nil; 
     } 
    } 

    - (void)resume 
    { 
     if ((! _timer) && (_rest > 0.0f)) 
     { 
      NSLog(@"[ ] resume (rest:%f)", _rest); 
      _timer = [NSTimer scheduledTimerWithTimeInterval:_rest target:self selector:@selector(fired) userInfo:nil repeats:FALSE]; 
      _rest = 0.0f; 
     } 
    } 

    - (void)kill 
    { 
     [_timer invalidate]; 
     _timer = nil; 
     _rest = 0.0f; 
     _completion = nil; 

     NSLog(@"[ ] kill"); 
    } 

    - (void)fired 
    { 
     [_timer invalidate]; 
     _timer = nil; 
     _rest = 0.0f; 

     if (_completion) 
     { 
      _completion (nil); 
     } 

     NSLog(@"[ ] fired"); 
    } 

    - (void)dealloc 
    { 
    #if (Namera_SHOW_DEALLOC && FALSE) 
     NSLog(@"[DEA] %@ NMCountdownTimer", self); 
    #endif 

     _timer = nil; 
     _completion = nil; 
    } 

    @end 
 
    somewhere in your code like this; 

    NSTimeInterval playback_duration = [[song valueForProperty: MPMediaItemPropertyPlaybackDuration] doubleValue]; 

    .... 

    MPMediaItemCollection *collection = [MPMediaItemCollection collectionWithItems:[NSArray arrayWithObject:song]]; 

    [_musicCtr setQueueWithItemCollection:collection]; 
    [_musicCtr play]; 
    [_countdown_timer start:playback_duration completion:^(id _Nullable object) 
    { 
     [weakSelf execute_next_song]; 
    }]; 
+0

我觉得重复模式下的NSTimer在背景中效果不好。我以非重复模式使用它。 –

+0

我已经尝试了完全相同的事情,但3分钟后我的NSTimer不再触发。所以我真正的问题是,我如何获得超过3分钟的时间?我有音频背景模式设置。 –

0

以供将来参考:

我发现MPMusicPlayerController从未从事音频UIBackgroundMode,即使用applicationMusicPlayer或systemMusicPlayer。所以你永远不能超过3分钟的背景时间。但是,AVAudioPlayer会使用enagage音频背景模式。所以我的(丑陋的)解决方案是在后台使用AVAudioPlayer来循环播放无声MP3。我打算假设苹果不会抗议,这似乎是无声音频的合法使用。请注意,对于AVAudioPlayer和MPMusicPlayerController同时播放,您必须为AVAudioSession设置AVAudioSessionCategoryOptionMixWithOthers。

+0

您是否能够想出一个解决方案来设置控制中心现在正在播放的信息?我正在使用applicationQueuePlayer,我可以播放音乐,但控制中心不会使用MPNowPlayingInfoCenter进行更新。它保持股票音乐应用程序的信息。 – Benr783