標籤:ios ios 音樂播放 後台播放
iOS 4開始引入的multitask,我們可以實現像ipod程式那樣在背景播放音頻了。如果音頻操作是用蘋果官方的AVFoundation.framework實現,像用AvAudioPlayer,AvPlayer播放的話,要實現完美的後台音頻播放,依據app的功能需要,可能需要實現幾個關鍵的功能。
首先,播放音頻之前先要設定AVAudioSession模式,通常只用來播放的App可以設為AVAudioSessionCategoryPlayback即可。模式意義及其他模式請參考文檔。
1 //後台播放音頻設定2 AVAudioSession *session = [AVAudioSession sharedInstance];3 [session setActive:YES error:nil];4 [session setCategory:AVAudioSessionCategoryPlayback error:nil];
1.通知IOS該app支援background audio。預設情況下,當按下home鍵時,當前正在啟動並執行程式被suspend,狀態從active變成in-active,也就是說如果現正播放音頻,按下HOME後就會停止。這裡需要讓app在按在HOME後,轉到後台運行而非被suspend,解決辦法是在程式的-info.plist中增加required background modes這個key項,並選擇App plays audio or streams audio/video using AirPlay這個value項(如果用過Xcode5.0,在TARGETS-Capabilities-Background Modes設定為ON,勾選Audio and AirPlay選項)。
2.如果你在背景播放使用的時載入網路音頻,恰巧網速很慢,音頻被停止下來這時候程式也隨之suspend,曾經有山寨的解決辦法是專門起一個player的執行個體連續不停的放同一無聲音片斷,阻止程式被suspend。這裡提供的方法是通過申請後台taskID達到後台切換播放檔案的功能。
即使聲明taskID也最多隻能在後台運行600秒鐘。(在ios7sdk中可以使用NSURLSession來實現後台緩衝)
(一般情況下,按HOME將程式送到後台,可以有5或10秒時間可以進行一些收尾工作,具體時間[[UIApplication sharedApplication] backgroundTimeRemaining]返回值,逾時後app會被suspend。)
3.ipod播放程式在後台時,雙擊HOME鍵,會有個控制介面,可以對它進行播放控制(暫停開始、上一曲、下一曲)。如果您想讓您的app可以像ipod一樣在後台也可以方便的通過雙擊HOME鍵來控制(在ios7中是使用上拉菜單控制),就要用到遠端控制事件了。
首先在viewdidload等初始化的地方聲明App接收遠端控制事件,並在相應地方結束聲明
- (void) viewWillAppear:(BOOL)animated{[super viewWillAppear:animated];[UIApplication sharedApplication] beginReceivingRemoteControlEvents];[self becomeFirstResponder];}- (void) viewWillDisappear:(BOOL)animated{[super viewWillDisappear:animated];[UIApplication sharedApplication] endReceivingRemoteControlEvents];[self resignFirstResponder];}- (BOOL)canBecomeFirstResponder{ return YES;}
當然也不一定是在viewcontroller中,也可以是在applicationDidEnterBackground:方法中開始接受遠端控制,applicationDidBecomeActive:中結束接受遠端控制,但是當前的appdelegate中要繼承與UIResponder,因為在啟用遠端控制以後要把當前類變成第一響應,重寫canBecomeFirstResponder方法。
最後定義 remoteControlReceivedWithEvent,處理具體的播放、暫停、前進、後退等具體事件
//重寫父類方法,接受外來事件的處理- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent { if (receivedEvent.type == UIEventTypeRemoteControl) { switch (receivedEvent.subtype) { case UIEventSubtypeRemoteControlTogglePlayPause: [self playAndStopSong:self.playButton]; break; case UIEventSubtypeRemoteControlPreviousTrack: [self playLastButton:self.lastButton]; break; case UIEventSubtypeRemoteControlNextTrack: [self playNextSong:self.nextButton]; break; case UIEventSubtypeRemoteControlPlay: [self playAndStopSong:self.playButton]; break; case UIEventSubtypeRemoteControlPause: [self playAndStopSong:self.playButton]; break; default: break; } }}
其它外來事件也可通過這種方式實現,如“搖一搖”響應等。
4. 至此,您有播放App已經基本完成了,其次插拔耳機是否響應停止播放時間需要進一步研究耳機檢測和聲音路由切換的問題,再次不詳細講述。
5. 還有一些開發人員可能會發現,有一些音視頻app在定義的時候自定一些控制項可以調節系統的音量大小,不需要使用者調整音量按鈕。經查看相關的資料總結出有兩種方法:
一種是調用控制項MPVolumeView在螢幕中建立一個音量條,拖動可以改變系統的音量大小。
另一種是使用MPMusicPlayerController類,可以自訂控制項調整系統音量的大小(但是在ios7sdk中已經被棄用,估計以後幾個版本中可能找不到這個方法了)。
MPMusicPlayerController *mpc = [MPMusicPlayerController applicationMusicPlayer];mpc.volume = 0; //0.0~1.0
6. 在一些其他的音樂播放軟體中如:酷我、qq音樂等,你會發在播放的時候,當裝置鎖屏以後依然可以看到使用者播放的音樂名稱、演唱者、專輯名稱、音樂時間長度、專輯圖片等資訊。這些就需要在使用者切換完歌去的時候,在程式中設定資訊了。
//設定鎖屏狀態,顯示的歌曲資訊-(void)configNowPlayingInfoCenter{ if (NSClassFromString(@"MPNowPlayingInfoCenter")) { NSDictionary *info = [self.musicList objectAtIndex:_playIndex]; NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; //歌曲名稱 [dict setObject:[info objectForKey:@"name"] forKey:MPMediaItemPropertyTitle]; //演唱者 [dict setObject:[info objectForKey:@"singer"] forKey:MPMediaItemPropertyArtist]; //專輯名 [dict setObject:[info objectForKey:@"album"] forKey:MPMediaItemPropertyAlbumTitle]; //專輯縮圖 UIImage *image = [UIImage imageNamed:[info objectForKey:@"image"]]; MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:image]; [dict setObject:artwork forKey:MPMediaItemPropertyArtwork]; //音樂剩餘時間長度 [dict setObject:[NSNumber numberWithDouble:self.player.duration] forKey:MPMediaItemPropertyPlaybackDuration]; //音樂當前播放時間 在計時器中修改 //[dict setObject:[NSNumber numberWithDouble:0.0] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; //設定鎖屏狀態下螢幕顯示播放音樂資訊 [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict]; }}
上面的if (NSClassFromString(@”MPNowPlayingInfoCenter”))語句,說是為了避免了版本相容問題,這個API貌似只出現在5裡面。
7. 下面就在計時器中不斷重新整理鎖屏狀態下的播放進度條了。
//計時器修改進度- (void)changeProgress:(NSTimer *)sender{ if(self.player){ //當前播放時間 NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[[MPNowPlayingInfoCenter defaultCenter] nowPlayingInfo]]; [dict setObject:[NSNumber numberWithDouble:self.player.currentTime] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; //音樂當前已經過時間 [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict]; }}
8. 當前的很多常見的播放器都可以在鎖屏狀態下顯示顯示歌詞,經過一番尋找後,終於找到方法(詳情:點擊查看),大致就是根據播放的時間和歌詞顯示時間,利用計時器不斷的用歌詞和專輯封面合成圖片,達到顯示歌詞的效果。還有就是在螢幕變暗停止這一操作、螢幕點亮的時候開始計時器,以節省電量和cpu,有兩種方法可以監聽上述現象:
一種是監聽核心層DarwinNotification,在Darwin中,有很多的系統事件,但apple的api文檔描述這些api使用有限制,也就是灰色地帶的api,所以能不用則不用;
另一種方法可以通過notify_get_state來擷取com.apple.springboard.hasBlankedScreen 的狀態值,通過狀態值我們可以判斷螢幕狀態,螢幕亮或者暗系統會給出不同狀態值,然後根據狀態值,通過NotificationCenter發送訊息通知給相應的函數處理。
from:http://www.cnblogs.com/easy-coding/p/3569227.html
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
IOS 後台運行 播放音樂