好久沒有寫東西了,最近加班太嚴重,今天抽空把用到的音樂播放器DOUAudioStreamer整理一下,由于項目之前用的是AVPlayer,這個也可以,但是就是要先緩存一段時間再播放,老板看了之后要求,要變緩存變播放(有網時,點擊播放按鈕就立刻播放),怎么不早說!怎么不早說!怎么不早說!還能怎樣?只能原諒他,繼續敲代碼。。。。。。(還是直接上代碼吧)
一、導入三方庫
pod 'DOUAudioStreamer'
或者GitHup下載地址:https://github.com/douban/DOUAudioStreamer
二、使用
1.從demo中獲取NAKPlaybackIndicatorView文件和MusicIndicator.h和MusicIndicator.m 文件,并導入頭文件
//音樂播放#import "DOUAudioStreamer.h"#import "NAKPlaybackIndicatorView.h"#import "MusicIndicator.h"#import "Track.h"
如圖:
2.創建一個Track類,用于音樂播放的URL存放
3.需要的界面.h中,添加DOUAudioStreamer,并用單利來初始化
+ (instancetype)sharedInstance ;@property (nonatomic, strong) DOUAudioStreamer *streamer;
如圖:
在.m中實現:
static void *kStatusKVOKey = &kStatusKVOKey;static void *kDurationKVOKey = &kDurationKVOKey;static void *kBufferingRatioKVOKey = &kBufferingRatioKVOKey;@property (strong, nonatomic) MusicIndicator *musicIndicator;@property (nonatomic, strong) Track *audioTrack;+ (instancetype)sharedInstance { static HYNEntertainmentController *_sharedMusicVC = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedMusicVC = [[HYNEntertainmentController alloc] init]; _sharedMusicVC.streamer = [[DOUAudioStreamer alloc] init]; }); return _sharedMusicVC;}
播放按鈕事件
#pragma mark ---音樂播放按鈕-(void)playMusicStart:(UIButton *)sender{ //通過按鈕獲取cell MusicCollectionViewCell *musicCell = (MusicCollectionViewCell *)[[sender superview] superview]; if(_playFirst == 0){//_playFirst == 0首次播放,其他為暫停 NSURL *url = [NSURL URLWithString:HttpImgUrl(musicCell.model.musicUrl)]; _audioTrack.audioFileURL = url; @try { [self removeStreamerObserver]; } @catch(id anException){ } //在DOUAudioStreamer進行播放時,必須先置為nil _streamer = nil; _streamer = [DOUAudioStreamer streamerWithAudioFile:_audioTrack]; [self addStreamerObserver]; [_streamer play]; } if([_streamer status] == DOUAudioStreamerPaused || [_streamer status] == DOUAudioStreamerIdle){ [sender setBackgroundImage:[UIImage imageNamed:@"music_play_icon"] forState:UIControlStateNormal]; [_streamer play]; }else{ [sender setBackgroundImage:[UIImage imageNamed:@"music_stop_icon"] forState:UIControlStateNormal]; [_streamer pause]; } _playFirst++; }
對添加監聽
- (void)addStreamerObserver { [_streamer addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:kStatusKVOKey]; [_streamer addObserver:self forKeyPath:@"duration" options:NSKeyValueObservingOptionNew context:kDurationKVOKey]; [_streamer addObserver:self forKeyPath:@"bufferingRatio" options:NSKeyValueObservingOptionNew context:kBufferingRatioKVOKey]; }/// 播放器銷毀- (void)dealloc{ if (_streamer !=nil) { [_streamer pause]; [_streamer removeObserver:self forKeyPath:@"status" context:kStatusKVOKey]; [_streamer removeObserver:self forKeyPath:@"duration" context:kDurationKVOKey]; [_streamer removeObserver:self forKeyPath:@"bufferingRatio" context:kBufferingRatioKVOKey]; _streamer =nil; } }- (void)removeStreamerObserver { [_streamer removeObserver:self forKeyPath:@"status"]; [_streamer removeObserver:self forKeyPath:@"duration"]; [_streamer removeObserver:self forKeyPath:@"bufferingRatio"];}- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == kStatusKVOKey) { [self performSelector:@selector(updateStatus) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; } else if (context == kDurationKVOKey) { [self performSelector:@selector(updateSliderValue:) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; } else if (context == kBufferingRatioKVOKey) { [self performSelector:@selector(updateBufferingStatus) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; }}- (void)updateSliderValue:(id)timer {}-(void)updateBufferingStatus{ }- (void)updateStatus { //self.musicIsPlaying = NO; _musicIndicator.state = NAKPlaybackIndicatorViewStateStopped; switch ([_streamer status]) { case DOUAudioStreamerPlaying: // self.musicIsPlaying = YES; _musicIndicator.state = NAKPlaybackIndicatorViewStatePlaying; break; case DOUAudioStreamerPaused: break; case DOUAudioStreamerIdle: break; case DOUAudioStreamerFinished: break; case DOUAudioStreamerBuffering: _musicIndicator.state = NAKPlaybackIndicatorViewStatePlaying; break; case DOUAudioStreamerError: break; } }
這樣就能播放了。
鎖屏時的音樂顯示、拔出耳機后暫停播放、監聽音頻打斷事件
-(void)viewWillAppear:(BOOL)animated{[super viewWillAppear:animated];//接受遠程控制[self becomeFirstResponder];[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];}//這個不能忘記了-(BOOL)canBecomeFirstResponder{return YES;}- (void)viewDidLoad {[super viewDidLoad];//音樂播放器[self initPlayer];}#pragma mark =========================音樂播放==============================//音樂播放器-(void)initPlayer{_audioTrack = [[Track alloc] init];AVAudioSession *session = [AVAudioSession sharedInstance];[session setActive:YES error:nil];[session setCategory:AVAudioSessionCategoryPlayback error:nil];//讓app支持接受遠程控制事件[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];//添加通知,拔出耳機后暫停播放[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil];// 監聽音頻打斷事件[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionWasInterrupted:) name:AVAudioSessionInterruptionNotification object:session];}// 監聽音頻打斷事件- (void)audioSessionWasInterrupted:(NSNotification *)notification{ //被打斷時if (AVAudioSessionInterruptionTypeBegan == [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue]){ [_streamer pause];UIButton *btn = (UIButton *)[self.view viewWithTag:2000];[btn setBackgroundImage:[UIImage imageNamed:@"music_stop_icon"] forState:UIControlStateNormal];}else if (AVAudioSessionInterruptionTypeEnded == [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue]){}}// 拔出耳機后暫停播放-(void)routeChange:(NSNotification *)notification{NSDictionary *dic=notification.userInfo;int changeReason= [dic[AVAudioSessionRouteChangeReasonKey] intValue];//等于AVAudioSessionRouteChangeReasonOldDeviceUnavailable表示舊輸出不可用if (changeReason==AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {AVAudioSessionRouteDescription *routeDescription=dic[AVAudioSessionRouteChangePreviousRouteKey];AVAudioSessionPortDescription *portDescription= [routeDescription.outputs firstObject];//原設備為耳機則暫停if ([portDescription.portType isEqualToString:@"Headphones"]) {[_streamer pause];UIButton *btn = (UIButton *)[self.view viewWithTag:2000];[btn setBackgroundImage:[UIImage imageNamed:@"music_stop_icon"] forState:UIControlStateNormal];}}}//鎖屏時音樂顯示(這個方法可以在點擊播放時,調用傳值)- (void)setupLockScreenInfoWithSing:(NSString *)sign WithSigner:(NSString *)signer WithImage:(UIImage *)image{// 1.獲取鎖屏中心MPNowPlayingInfoCenter *playingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];//初始化一個存放音樂信息的字典NSMutableDictionary *playingInfoDict = [NSMutableDictionary dictionary];// 2、設置歌曲名if (sign) {[playingInfoDict setObject:sign forKey:MPMediaItemPropertyAlbumTitle];}// 設置歌手名if (signer) {[playingInfoDict setObject:signer forKey:MPMediaItemPropertyArtist];}// 3設置封面的圖片//UIImage *image = [self getMusicImageWithMusicId:self.currentModel];if (image) {MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:image];[playingInfoDict setObject:artwork forKey:MPMediaItemPropertyArtwork];}// 4設置歌曲的總時長//[playingInfoDict setObject:self.currentModel.detailDuration forKey:MPMediaItemPropertyPlaybackDuration];//音樂信息賦值給獲取鎖屏中心的nowPlayingInfo屬性playingInfoCenter.nowPlayingInfo = playingInfoDict;// 5.開啟遠程交互[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];}//鎖屏時操作- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {if (receivedEvent.type == UIEventTypeRemoteControl) {UIButton *sender = (UIButton *)[self.view viewWithTag:2000];switch (receivedEvent.subtype) {//判斷是否為遠程控制case UIEventSubtypeRemoteControlPause:[[HYNEntertainmentController sharedInstance].streamer pause];[sender setBackgroundImage:[UIImage imageNamed:@"music_stop_icon"] forState:UIControlStateNormal];break;case UIEventSubtypeRemoteControlStop:break;case UIEventSubtypeRemoteControlPlay:[[HYNEntertainmentController sharedInstance].streamer play];[sender setBackgroundImage:[UIImage imageNamed:@"music_play_icon"] forState:UIControlStateNormal];break;case UIEventSubtypeRemoteControlTogglePlayPause:break;case UIEventSubtypeRemoteControlNextTrack:break;case UIEventSubtypeRemoteControlPreviousTrack:break;default:break;}}}
整體圖片:
上圖為未播放
上圖為播放中
上圖為鎖屏時狀態
應該沒有什么要添加的了,暫時告一段落,有不足之處,可以在下方的留言區討論,感謝對VEVB武林網的支持。
新聞熱點
疑難解答