2017-06-21 171 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

相關問題