iOS音樂后臺(tái)播放、鎖屏封面及播放控制

前言

在默認(rèn)環(huán)境下App被切換到后臺(tái)時(shí),音樂的就停止播放了,但音樂類App的一般都會(huì)需要在后臺(tái)繼續(xù)播放,這樣用戶就可以一邊聽音樂,一邊操作其他的App。對(duì)于這種情況我們可以對(duì)App做一些簡單的配置,實(shí)現(xiàn)后臺(tái)播放功能。當(dāng)app切換到后臺(tái),用戶就無法控制和查看app當(dāng)前播放歌曲了。這個(gè)對(duì)于用戶來說并不是很友好。既然是后臺(tái)播放,那么就應(yīng)該提供便捷的播放控制方式。iOS系統(tǒng)已經(jīng)預(yù)留了接口,允許開發(fā)者在鎖屏界面顯示播放歌曲信息(以下稱為鎖屏封面),以及在底部菜單欄提供播放控制器。下面我們就來給App添加這些功能吧。

一、后臺(tái)播放

設(shè)置App的plist,使app可以在后臺(tái)播放音樂。

myApp-Info.plist中添加UIBackgroundModes鍵值,添加子鍵值為audio。

然后再程序中添加入下代碼:

AVAudioSession  *session  =  [AVAudioSession  sharedInstance];
[session setActive:YES error:nil];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];

二、添加播放控制器(Remote Control Events)

首先我們要告訴系統(tǒng),我要接受系統(tǒng)的播放控制消息,這樣系統(tǒng)才會(huì)給我們發(fā)送播放控制命令。流程是這樣的:

App啟動(dòng) -> 告訴系統(tǒng)我需要接受播放控制消息 -> 等待 -> 用戶點(diǎn)擊系統(tǒng)播放控制器按鈕 -> 系統(tǒng)傳遞消息給App -> 我們接受到消息,做出相應(yīng)的響應(yīng)。

想要接收播放控制消息,我們必須要做三件事:

  • 成為Frist Responder
  • 請(qǐng)求系統(tǒng),要求開始監(jiān)聽播放控制消息(Remote Control Events)
  • 開始播放音頻。

請(qǐng)注意第三點(diǎn),我們的App必須在開始播放音頻后,才能收到控制消息。否則,即使你滿足了前兩點(diǎn),也無法接收到控制消息。


//AppDelegate.m

-  (BOOL)application:(UIApplication  *)application didFinishLaunchingWithOptions:(NSDictionary  *)launchOptions

{

 //...

 //告訴系統(tǒng),我們要接受遠(yuǎn)程控制事件

    [[UIApplication  sharedApplication] beginReceivingRemoteControlEvents];

    [self  becomeFirstResponder];

}

-  (BOOL)canBecomeFirstResponder

{

    return  YES;

}

//響應(yīng)遠(yuǎn)程音樂播放控制消息

-  (void)remoteControlReceivedWithEvent:(UIEvent  *)receivedEvent  {

    if  (receivedEvent.type  ==  UIEventTypeRemoteControl)  {

        switch  (receivedEvent.subtype)  {

            case UIEventSubtypeRemoteControlTogglePlayPause:

                [[PlayController  sharedInstance] pause];

                NSLog(@"RemoteControlEvents: pause");

                break;

            case UIEventSubtypeRemoteControlNextTrack:

                [[PlayController  sharedInstance] playModeNext];

                NSLog(@"RemoteControlEvents: playModeNext");

                break;

            case UIEventSubtypeRemoteControlPreviousTrack:

                [[PlayController  sharedInstance] playPrev];

                NSLog(@"RemoteControlEvents: playPrev");

                break;

            default:

                break;

        }

    }

}

播放音頻的代碼,這里給出一段簡單的示例:


-  (void)playBtnClicked

{

    NSError  *error  =  nil;

    NSString  *path  =  [[NSBundle  mainBundle] pathForResource:@"music" ofType:@"mp3"];

    AVAudioPlayer  *player  =  [[AVAudioPlayer  alloc] initWithContentsOfURL:[NSURL URLWithString:path] error:&error];

    if  (error)  {

        NSLog(@"Error:%@",  [error localizedDescription]);

    }

    [player play];

}

在開始播放音頻后,使用耳機(jī)線控的播放暫停等按鍵,或者鎖屏封面上的播放控制按鍵,就能夠收到控制消息了。

關(guān)于耳機(jī)線控的一點(diǎn)說明

蘋果耳機(jī)的線控上有三個(gè)按鈕:加號(hào),中部,減號(hào)。其中加號(hào)和減號(hào)是用于控制音量,這兩個(gè)按鈕點(diǎn)擊是收不到消息的——UIEventSubtype沒有音量改變的事件類型。而中部按鈕的點(diǎn)擊,是可以收到消息的,按一下是播放/暫停切換,快按兩下是播放下一首,快按三下是播放上一首,快按兩下并摁住是快進(jìn),快按三下并摁住是快退。

三、在鎖屏界面顯示播放歌曲信息

代碼如下,其實(shí)就是設(shè)置一個(gè)全局變量的值,當(dāng)系統(tǒng)處于音樂播放狀態(tài)時(shí),鎖屏界面就會(huì)將NowPlayingInfo中的信息展示出來??上У氖牵@里的定制性不是太強(qiáng),例如歌曲圖片無法平鋪整個(gè)屏幕大小,根據(jù)我的測試,歌曲圖片在320×320時(shí),可以完整顯示在屏幕中央位置,兩側(cè)不會(huì)留下黑邊。


Class playingInfoCenter = NSClassFromString(@"MPNowPlayingInfoCenter");
    
    if (playingInfoCenter) {
        NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
        UIImage *image = [UIImage imageNamed:@"image"];
        MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:image];
        //歌曲名稱
        [songInfo setObject:@"深夜地下鐵" forKey:MPMediaItemPropertyTitle];
        //演唱者
        [songInfo setObject:@"陶鈺玉" forKey:MPMediaItemPropertyArtist];
        //專輯名
        [songInfo setObject:@"深夜地下鐵" forKey:MPMediaItemPropertyAlbumTitle];
        //專輯縮略圖
        [songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
        [songInfo setObject:[NSNumber numberWithDouble:[audioY getCurrentAudioTime]] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; //音樂當(dāng)前已經(jīng)播放時(shí)間
        [songInfo setObject:[NSNumber numberWithFloat:1.0] forKey:MPNowPlayingInfoPropertyPlaybackRate];//進(jìn)度光標(biāo)的速度 (這個(gè)隨 自己的播放速率調(diào)整,我默認(rèn)是原速播放)
        [songInfo setObject:[NSNumber numberWithDouble:[audioY getAudioDuration]] forKey:MPMediaItemPropertyPlaybackDuration];//歌曲總時(shí)間設(shè)置
        
        //        設(shè)置鎖屏狀態(tài)下屏幕顯示音樂信息
        [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
    }

經(jīng)過了如上配置后,程序應(yīng)該就能夠正常顯示了。

四、遇到的問題

  • 1.只添加MPMediaItemPropertyPlaybackDuration(歌曲總時(shí)間)

問題:不顯示當(dāng)前進(jìn)度
解決:添加MPMediaItemPropertyPlaybackDuration同時(shí)也出現(xiàn)問題,剩余時(shí)間每次減2秒

  • 2.添加了MPMediaItemPropertyPlaybackDuration和MPNowPlayingInfoPropertyElapsedPlaybackTime

問題:出現(xiàn)了剩余時(shí)間每次減2秒的情況
解決:要添加MPNowPlayingInfoPropertyPlaybackRate就可以

  • 3.暫?;謴?fù)播放更新 鎖屏進(jìn)度條


NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[[MPNowPlayingInfoCenter defaultCenter] nowPlayingInfo]];
[dict setObject:[NSNumber numberWithDouble:audioPlayer.playableDuration] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; //音樂當(dāng)前已經(jīng)過時(shí)間
 [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict];

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容