網易雲音樂鎖屏界面實現

######最終效果: 鎖屏界面最終效果app

#完整的實現思路:atom

  1. App若是須要在鎖屏界面上顯示相關的信息和按鈕, 必須先開啓遠程控制事件(Remote Control Event), 不然鎖屏界面只顯示滑動解鎖.
  2. 實現鎖屏界面信息, 將歌曲的相關信息更新到鎖屏界面上
  3. 實現鎖屏界面的事件處理, 在鎖屏界面和上拉的快速功能菜單中實現播放控制

#遠程控制事件的實現 在iOS7.1以前, 遠程控制事件主要涉及如下三個方法:.net

  • 開始接收遠程控制事件
  • 結束接收遠程控制事件
  • 觸發遠程控制事件後的捕獲處理

官方文檔對這三個方法的描述以下, 這裏作了簡單的翻譯. ###開始接收遠程控制事件 ######Declaration翻譯

- (void)beginReceivingRemoteControlEvents

讓App開始接收遠程控制事件, 該方法屬於UIApplication類code

######Discussion 在iOS7.1以後, 使用MPRemoteCommandCenter的共享對象來註冊遠程控制事件. 當使用shared command center時, 不須要再調用該方法.
該方法會開始使用事件響應鏈來傳遞遠程控制事件. 遠程控制事件是當耳機和外部附件意圖控制App的多媒體表現時發出的命令. 要中止遠程控制事件的接收, 必須調用endReceivingRemoteControlEvents方法orm

###結束接收遠程控制事件 ######Declaration視頻

- (void)endReceivingRemoteControlEvents

讓App中止接收遠程控制事件, 該方法屬於UIApplication類對象

######Discussion 在iOS7.1以前, 使用shared MPRemoteCommandCenter對象來註冊遠程控制事件. 當使用shared command center時, 不須要再調用該方法. 該方法會中止經過事件響應鏈來傳遞遠程控制事件. 遠程控制事件是當耳機和外部附件意圖控制App的多媒體表現時發出的命令.事件

###遠程控制事件的捕獲處理 ######Declaration圖片

- (void)remoteControlReceivedWithEvent:(UIEvent *)event

當遠程控制事件發生時觸發該方法, 該方法屬於UIResponder類

######Discussion 遠程控制事件是由外部附件(包括耳機)所發出的命令. 應用須要響應這些命令來控制音頻或視頻媒體的對用戶的表示. 事件響應者經過檢查事件的subtype, 來判斷命令的意圖. 好比UIEventSubtypeRemoteControlPlay爲播放操做, 而後作相關處理

要容許遠程控制事件的傳遞, 須要調用UIApplication的beginReceivingRemoteControlEvents方法; 要關閉遠程控制事件的傳遞則調用endReceivingRemoteControlEvents

###項目中的代碼實現

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 在App啓動後開啓遠程控制事件, 接收來自鎖屏界面和上拉菜單的控制
    [application beginReceivingRemoteControlEvents];

    return YES;
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // 在App要終止前結束接收遠程控制事件, 也能夠在須要終止時調用該方法終止
    [application endReceivingRemoteControlEvents];
}

// 在具體的控制器或其它類中捕獲處理遠程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
{
    // 根據事件的子類型(subtype) 來判斷具體的事件類型, 並作出處理
    switch (event.subtype) {
        case UIEventSubtypeRemoteControlPlay:
        case UIEventSubtypeRemoteControlPause: {
            // 執行播放或暫停的相關操做 (鎖屏界面和上拉快捷功能菜單處的播放按鈕)
            break;
        }
        case UIEventSubtypeRemoteControlPreviousTrack: {
            // 執行上一曲的相關操做 (鎖屏界面和上拉快捷功能菜單處的上一曲按鈕)
            break;
        }
        case UIEventSubtypeRemoteControlNextTrack: {
            // 執行下一曲的相關操做 (鎖屏界面和上拉快捷功能菜單處的下一曲按鈕)
            break;
        }
        case UIEventSubtypeRemoteControlTogglePlayPause: {
            // 進行播放/暫停的相關操做 (耳機的播放/暫停按鈕)
            break;
        }
        default:
            break;
    }
}

#iOS7.1後, 更新了遠程控制事件的實現方式 相關方法的描述中, 已經說明, iOS7.1以後使用MPRemoteCommandCenter類來進行遠程控制事件的相關處理, 所以能夠再也不使用上面所描述的三個方法. 官方文檔對MPRemoteCommandCenter的描述以下:

###MPRemoteCommandCenter MPRemoteCommandCenter類提供了處理遠程控制事件的對象, 包括由外部附件和系統傳輸控制發送的遠程控制事件. 不須要本身建立該類的實例. 而是使用shareCommandCenter方法獲取默認的命令中心(share command center)對象. share command center對象的屬性包含了MPRemoteCommand對象(表示iOS支持的每種遠程控件事件). 若是要對響應的事件特殊處理, 使用適當的MPRemoteCommand對象註冊一個handler便可.

遠程命令中心(remote command center)對象爲許多不一樣類型的事件提供了命令(command)對象. 若是你的App不須要支持某些特定類型的事件, 能夠經過設置其enabled屬性爲NO來禁用關聯的MPRemoteCommand對象. 使用command對象註冊一個handler, 以便讓系統知道你的App已經作好了接收事件的準備. 只有當你的App是當前正在播放(Now Playing App)時才能接收到事件的傳遞.

###項目中的代碼實現 :

// 在須要處理遠程控制事件的具體控制器或其它類中實現
- (void)remoteControlEventHandler
{
    // 直接使用sharedCommandCenter來獲取MPRemoteCommandCenter的shared實例
    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];

    // 啓用播放命令 (鎖屏界面和上拉快捷功能菜單處的播放按鈕觸發的命令)
    commandCenter.playCommand.enabled = YES;
    // 爲播放命令添加響應事件, 在點擊後觸發
    [commandCenter.playCommand addTarget:self action:@selector(playAction:)];

    // 播放, 暫停, 上下曲的命令默認都是啓用狀態, 即enabled默認爲YES
    // 爲暫停, 上一曲, 下一曲分別添加對應的響應事件
    [commandCenter.pauseCommand addTarget:self action:@selector(pauseAction:)];
    [commandCenter.previousTrackCommand addTarget:self action:@selector(previousTrackAction:)];
    [commandCenter.nextTrackCommand addTarget:self action:@selector(nextTrackAction:)];

    // 啓用耳機的播放/暫停命令 (耳機上的播放按鈕觸發的命令)
    commandCenter.togglePlayPauseCommand.enabled = YES;
    // 爲耳機的按鈕操做添加相關的響應事件
    [commandCenter.togglePlayPauseCommand addTarget:self action:@selector(playOrPauseAction:)];
}

######效果如圖: 開啓遠程控制事件後鎖屏界面

#鎖屏界面相關信息更新 實現了遠程控制事件後, App在進行音樂播放時, 上拉快捷功能菜單都會提供遠程控件按鈕, 鎖屏界面會有改動, 出現遠程控制按鈕, 以及歌曲進度等信息, 接下來須要將歌曲的相關信息更新到鎖屏界面上. 主要經過MPNowPlayingInfoCenter類來實現, 下面是官方文檔的描述:

###MPNowPlayingInfoCenter 使用now playing info center來設置App當前正在播放的媒體文件的信息(now-playing information).

系統會在設備的鎖屏界面和上劃的快捷控制面板的多媒體控制部分顯示當前播放文件的信息. 若是用戶直接經過AirPlay在Apple TV上播放媒體文件時, now-playing信息會顯示在電視屏幕上. 若是用戶將設備鏈接到iPad附件, 好比汽車(經過CarPlay鏈接)上, 附件上可能會顯示now-playing的信息.

你不能直接控制哪些信息要被顯示出來, 以及這些信息顯示的樣式. 只須要設置now playing info center dictionary的相關value, 將這些相關信息提交給系統便可. 系統或已經鏈接的附件, 會用一致的方式爲全部的App處理這些信息的展現.

###能夠配置的鎖屏界面信息 可使用的information屬性, 是定義在MPMediaItem類的General Media Item Property Keys屬性中的子集(即其中的某些屬性). 在iOS5.0後, now playing info center支持下列media item屬性的Key: (僅列舉了經常使用的Key!)

  • MPMediaItemPropertyAlbumTitle 專輯的標題, value是NSString對象
  • MPMediaItemPropertyArtist media item的創做者, value是NSString對象
  • MPMediaItemPropertyArtwork media item的插圖. value是MPMediaItemArtwork類的對象
  • MPMediaItemPropertyPlaybackDuration media item的播放總時長. value是表示包裝了時長秒數(NSTimeInterval)的NSNumber類型
  • MPMediaItemPropertyTitle media item的名字或標題. 該屬性與MPMediaItemPropertyAlbumTitle屬性無關, value是NSString對象

額外添加的一些可使用的屬性在MPNowPlayingInfoCenter類的描述文檔中的Additional Metadata Properties中做了聲明. (僅列舉了經常使用的Key!)

  • MPNowPlayingInfoPropertyElapsedPlaybackTime 當前播放的item所消逝的時間(歌曲當前時間), 單位爲秒. value是包裝了double值的NSNumber對象. elapsed time是由系統根據以前提供elapsed tiime和playback rate進行自動進行計算的. 請不要頻繁的更新該屬性, 這是沒有必要的.
  • MPNowPlayingInfoPropertyPlaybackRate 當前播放的item的播放速率, value爲1.0表示正常的播放速率. value是包裝了double值的NSNumber對象. 默認值是1.0. playback rate的值爲2.0表示普通播放速率的2倍; 此時media從播放到結束只須要一半時間.

###項目中的代碼實現

- (void)updatelockScreenInfo 
{
    // 直接使用defaultCenter來獲取MPNowPlayingInfoCenter的默認惟一實例
    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];

    // MPMediaItemArtwork 用來表示鎖屏界面圖片的類型
    MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc]     initWithImage:image];

    // 經過配置nowPlayingInfo的值來更新鎖屏界面的信息
    infoCenter.nowPlayingInfo = @{
                                  // 歌曲名
                                  MPMediaItemPropertyTitle : music.name,
                                  // 藝術家名
                                  MPMediaItemPropertyArtist : music.singer,
                                  // 專輯名字
                                  MPMediaItemPropertyAlbumTitle : music.album,
                                  // 歌曲總時長 
                                  MPMediaItemPropertyPlaybackDuration : @(duration),
                                  // 歌曲的當前時間
                                  MPNowPlayingInfoPropertyElapsedPlaybackTime : @(currentTime),
                                  // 歌曲的插圖, 類型是MPMeidaItemArtwork對象
                                  MPMediaItemPropertyArtwork : artwork,

                                  // 無效的, 歌詞的展現是經過圖片繪製完成的, 即將歌詞繪製到歌曲插圖, 經過更新插圖來實現歌詞的更新的
                                  // MPMediaItemPropertyLyrics : lyric.content,
                                  };
}

######效果如圖: 更新鎖屏界面信息後效果

#相似網易新聞的鎖屏控制按鈕實現 經過上述代碼實現後, 鎖屏界面已經能夠展現出歌曲信息與控制按鈕, 經過按鈕或耳機的按鍵也能夠實現相關的控制效果. 但網易的控制按鈕中最左邊並是上一曲, 而是列表按鈕, 點擊後還能在鎖屏界面彈出一個ActionSheet界面. 該功能實際上是經過修改MPRemoteCommandCenter的反饋功能(提供喜歡, 不喜歡, 標記(bookmark)操做)來實現的.

涉及到的反饋功能, 先了解MPFeedbackCommond這個類, 如下是文檔的描述

###MPFeedbackCommond MPFeedbackCommand對象反映了當前App所播放的反饋狀態. MPRemoteCommandCenter對象提供feedback對象用於對媒體文件進行喜歡, 不喜歡, 標記的操做. 使用這些對象爲App支持的回饋(feedback)方式進行註冊handler, 並在反饋狀態修改時執行適當的任務(task). 在當前播放的item改變時, 也可使用該對象爲新的item設置反饋狀態.

當item的反饋狀態改變時, 系統傳遞適當的事件到該對象註冊的handler上. handler的代碼必須決定哪個media item來接收反饋, 而後再爲該item執行更新反饋狀態的操做. 你也能夠執行與接收到反饋相關的其它任務. 好比, 當用戶喜歡當前播放的歌曲時你可能要在UI上作出適當調整, 並使用該信息來進行相關歌曲的推薦.

###MPRemoteCommandCenterr提供了相關屬性(反饋按鈕)

@property (nonatomic, readonly) MPFeedbackCommand *likeCommand;  // 喜歡命令
@property (nonatomic, readonly) MPFeedbackCommand *dislikeCommand;  // 不喜歡命令
@property (nonatomic, readonly) MPFeedbackCommand *bookmarkCommand; // 標記(書籤)命令

事實上, 系統的鎖屏界面並不支持自定義. 這裏邊只須要添加反饋按鈕, 則系統默認的鎖屏界面就是網易雲音樂所展現的樣式. 包括點擊後彈出的ActionSheet都是系統針對反饋按鈕所提供了, 網易雲音樂只是巧妙的將"不喜歡"按鈕的標題修改爲"上一曲", 並在該按鈕的響應事件裏實現上一曲的代碼, 即完成相關功能.

###項目中的代碼實現

// 添加"喜歡"按鈕, 須要啓用, 而且設置了相關Action後纔會生效
[MPRemoteCommandCenter sharedCommandCenter].likeCommand.enabled = YES;
[[MPRemoteCommandCenter sharedCommandCenter].likeCommand addTarget:self action:@selector(likeItemAction)];
[MPRemoteCommandCenter sharedCommandCenter].likeCommand.localizedTitle = @"喜歡";

// 添加"不喜歡"按鈕
[MPRemoteCommandCenter sharedCommandCenter].dislikeCommand.enabled = YES;
// 自定義該按鈕的響應事件, 實如今點擊"不喜歡"時去執行上一首的功能
[[MPRemoteCommandCenter sharedCommandCenter].dislikeCommand 
addTarget:self action:@selector(previousCommandAction)];
[MPRemoteCommandCenter
// 自定義"不喜歡"的標題, 假裝成"上一首"
sharedCommandCenter].dislikeCommand.localizedTitle = @"上一首";

注意: 反饋按鈕默認不啓用, 所以須要將enabled設置爲YES, 同時必須添加對應的響應事件, 按鈕纔會在鎖屏界面顯示.

######完成效果: 鎖屏界面

相關文章
相關標籤/搜索