AVPlayer循環(huán)播放音頻、鎖屏界面遠程控制省核、

AVPlayer可以用來播放音頻和視頻稿辙,今天要說的就是用AVPlayer的一個子類 AVQueuePlayer來播放音頻、這個類可以用來播放隊列气忠,當前AVPlayerItem播放完了邓深,如果nextItem存在就會自動播放下一個Item,比AVPlayer要方便一點笔刹。

一芥备、后臺播放設置
先導入兩個框架

#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>

設置后臺播放

   AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setActive:YES error:nil];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
屏幕快照 2017-08-24 下午2.09.25.png

二、AVQueuePlayer初始化

-(void)initPlayer{
    //準備數據 一個本地MP3和一個URL MP3
    AVPlayerItem*firstItem = [AVPlayerItem playerItemWithURL:[NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:@"那些花兒" ofType:@"mp3"]]];
    AVPlayerItem*secondItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://sc1.111ttt.com/2015/1/06/06/99060941326.mp3"]];
    
    SongModel*firstModel = [[SongModel alloc]init];
    firstModel.songName = @"那些花兒";
    firstModel.singer = @"樸樹";
    firstModel.picture = [UIImage imageNamed:@"pushu.jpg"];
    firstModel.duration = 294;
    firstModel.item = firstItem;
    
    SongModel*secondModel = [[SongModel alloc]init];
    secondModel.songName = @"演員";
    secondModel.singer = @"薛之謙";
    secondModel.picture = [UIImage imageNamed:@"xue.png"];
    secondModel.duration = 262;
    secondModel.item = secondItem;
    _songInfoArray = @[firstModel,secondModel];
    
//這里初始化設置一個或多個都是可以的舌菜,這里我設置一個的原因主要是上一曲和下一曲的時候會清空items
    self.player = [[AVQueuePlayer alloc]initWithItems:@[firstItem]];
    
    _index = 0;
// item和player都有status 屬性 通常我們觀察item的status 是因為可以檢測資源是否可以播放萌壳,當然這里直接調用play方法也是可以直接播放的
    [firstItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playeyEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
}

初始化完成之后直接調用[AVPlayer play]也是可以直接播放的,但是資源出現(xiàn)問題的話還是需要手動處理的所以我們在這里對Item添加了一個觀察者,并對AVPlayer播放完成添加了一個通知袱瓮。

通知和觀察者模式實現(xiàn)代碼

///播放結束
-(void)playeyEnd:(NSNotification*)notify{
    NSLog(@"end");
    [self nextSong];
    
}

///AVPlayerItem observer
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    AVPlayerItem*item = (AVPlayerItem*)object;
    if ([keyPath isEqualToString:@"status"]) {
        if (item.status==AVPlayerItemStatusReadyToPlay) {
            NSLog(@"play");
            
            [self setLockScreenNowPlayingInfo];
            
            [item removeObserver:self forKeyPath:@"status"];
            
            [self.player play];

        }
        
        if (item.status==AVPlayerItemStatusFailed) {
            
            NSLog(@"filad");
            
            [self setLockScreenNowPlayingInfo];
            
            [item removeObserver:self forKeyPath:@"status"];
            
            [self nextSong];
        }
    }
}

切歌控制

#warning 在同一時間內一個item只能占用一個位置缤骨、所以這里是先刪除,再添加
-(void)nextSong{
    //下一首
    if (_index==_songInfoArray.count-1) {
        _index =0;
    }else{
        _index++;
    }
    SongModel*model = _songInfoArray[_index];
    [model.item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    [self.player removeAllItems];
    [self.player insertItem:model.item afterItem:nil];
    [self.player seekToTime:kCMTimeZero];
    
    [self setLockScreenNowPlayingInfo]; 
}

-(void)lastSong{
    //上一首
    if (_index==0) {
        _index =_songInfoArray.count-1;
        
    }else{
        _index--;  
    }
    SongModel*model = _songInfoArray[_index];
    [model.item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    [self.player removeAllItems];
    [self.player insertItem:model.item afterItem:nil];
    [self.player seekToTime:kCMTimeZero];
    [self setLockScreenNowPlayingInfo];
}

這里有一個小坑尺借、AVQueuePlayer提供了跳轉到下一個Item的方法

- (void)advanceToNextItem;

卻沒有提供LastItem的方法绊起,所以要實現(xiàn)LastItem的方法我是通過來實現(xiàn)的

[self.player insertItem:model.item afterItem:nil]; 

特別提醒在同一時間同一個Item只能加入一次,所以在insert之前需要將之前的Item刪除掉燎斩、我選擇了刪除全部虱歪、這樣同一時間PlayerQueue中就只存在一個Item了、我覺得這樣更容易控制一點栅表。而關于 [self.player seekToTime:kCMTimeZero]; 這個是為了讓Item上一次的播放時間置零笋鄙,如果不置零就會繼續(xù)播放(感覺這個功能播放視頻的時候這個還是比較好用的);

三怪瓶、注冊遠程控制(鎖屏界面控制和耳機控制)

需要先讓應用能夠接受遠程控制萧落,并成為第一響應者

屏幕快照 2017-08-24 下午2.11.29.png
#pragma mark - 遠程控制接收方法的設置
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    if (event.type == UIEventTypeRemoteControl) {  //判斷是否為遠程控制
        switch (event.subtype) {
            case  UIEventSubtypeRemoteControlPlay:
            {
                if (!_isPlaying) {
                    [self.player play];
                }
                _isPlaying=!_isPlaying;
            }
                break;
            case UIEventSubtypeRemoteControlPause:
            {
                if (_isPlaying) {
                    [self.player pause];
                }
                _isPlaying = !_isPlaying;
            }
                break;
            case UIEventSubtypeRemoteControlNextTrack:
            {
                [self nextSong];
            }
                break;
            case UIEventSubtypeRemoteControlPreviousTrack:
            {
                [self lastSong];
            }
                break;
            default:
                break;
        }
    }
}

四、設置鎖屏信息
期間我看了網易云音樂的鎖屏效果洗贰、設置了lyrics,結果我這里設置了并沒有什么效果找岖。。敛滋。

///設置鎖屏信息
- (void)setLockScreenNowPlayingInfo
{
    SongModel*model = self.songInfoArray[_index];
    //更新鎖屏時的歌曲信息
    MPMediaItemArtwork *artWork = [[MPMediaItemArtwork alloc] initWithImage:model.picture];
    
    NSDictionary *dic = @{MPMediaItemPropertyTitle:model.songName,
                          MPMediaItemPropertyArtist:model.singer,
                          //                          MPMediaItemPropertyLyrics:@"hello lyrics break ",
                          //                          MPMediaItemPropertyReleaseDate:@"2017-08-23",//唱片發(fā)布日期
                          MPMediaItemPropertyPlaybackDuration:@(model.duration),//設置鎖屏界面歌曲時間
                          MPMediaItemPropertyArtwork:artWork//鎖屏界面圖片
                          };
    [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dic];
}

最后附上真機鎖屏的效果以及Demo地址
https://github.com/LuoCongMing/AVQueuePlayerDemo.git

IMG_1878.PNG
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末宣增,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子矛缨,更是在濱河造成了極大的恐慌,老刑警劉巖帖旨,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件箕昭,死亡現(xiàn)場離奇詭異,居然都是意外死亡解阅,警方通過查閱死者的電腦和手機落竹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來货抄,“玉大人述召,你說我怎么就攤上這事⌒返兀” “怎么了积暖?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長怪与。 經常有香客問我夺刑,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任遍愿,我火速辦了婚禮存淫,結果婚禮上,老公的妹妹穿的比我還像新娘沼填。我一直安慰自己桅咆,他們只是感情好,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布坞笙。 她就那樣靜靜地躺著岩饼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羞海。 梳的紋絲不亂的頭發(fā)上忌愚,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天,我揣著相機與錄音却邓,去河邊找鬼硕糊。 笑死,一個胖子當著我的面吹牛腊徙,可吹牛的內容都是我干的简十。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼撬腾,長吁一口氣:“原來是場噩夢啊……” “哼螟蝙!你這毒婦竟也來了?” 一聲冷哼從身側響起民傻,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤胰默,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后漓踢,有當地人在樹林里發(fā)現(xiàn)了一具尸體牵署,經...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年喧半,在試婚紗的時候發(fā)現(xiàn)自己被綠了奴迅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡挺据,死狀恐怖取具,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情扁耐,我是刑警寧澤暇检,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站婉称,受9級特大地震影響占哟,放射性物質發(fā)生泄漏心墅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一榨乎、第九天 我趴在偏房一處隱蔽的房頂上張望怎燥。 院中可真熱鬧,春花似錦蜜暑、人聲如沸铐姚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽隐绵。三九已至,卻和暖如春拙毫,著一層夾襖步出監(jiān)牢的瞬間依许,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工缀蹄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留峭跳,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓缺前,卻偏偏與公主長得像蛀醉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子衅码,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內容