iOS Remote Control
前言
RemoteControl,這里就翻譯為遠程控制吧。
遠程控制是為用戶提供操作App多媒體的。遠程控制事件源于外部附件或由系統顯示的傳輸控制,并通過媒體播放器框架的類傳送到應用程序。播放音頻或視頻內容的應用程序使用這些事件來開始和停止播放,更改曲目,甚至速度的項目。所有的媒體應用程序應該支持這些事件。
除了支持遠程控制事件,應用程序可以使用媒體播放器框架,以提供播放信息的曲目。該系統在適當的地方顯示播放信息,如鎖屏和控制中心。有關媒體播放器框架類的更多信息,見媒體播放器框架參考 Media Player Framework Reference .
Remote Control功能
RemoteControl可以用來在不打開app的情況下控制app中的多媒體播放,主要包括:
- 鎖屏界面雙擊Home鍵后出現的播放操作區域
- iOS7之后控制中心的播放操作區域
- iOS7之前雙擊home鍵后出現的進程中向左滑動出現的播放操作區域
- AppleTV,AirPlay中顯示的播放操作區域
- 耳機線控
- 車載系統的設置
讓App支持Remote Control
要接收遠程控制事件,需要做到以下的幾點:
- 接收者必須可以成為第一響應者;
- 接收者必須顯示聲明接收RemoteControl事件;
- App必須是Now Playing App.
若應用程序還提供了正在播放的信息,使用 MPNowPlayingInfoCenter 對象在適當的時候更新信息。
環境準備
要使App支持Remote Control,需要設置一下info.plist文件,添加required background modes,并添加一個值為:
App playsaudioorstreamsaudio/videousingAirPlay
接下來,播放音頻之前先要設置AVAudioSession模式:
AVAudioSession *session = [AVAudioSession sharedInstance]; [sessionsetCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
擴展UIApplication作為第一響應者
在iOS上,響應者鏈如上圖,由圖可知,若其它視圖沒有處理,最終會傳到UIApplication,因此使用UIApplication作為第一響應者是最合適的。
擴展頭文件聲明,我們在監聽到對應的事件時,發送通知。
// // UIApplication+RemoteControl.h // IOSAudioRemoteControl // // Created by huangyibiao on 15/3/25. // Copyright (c) 2015年 huangyibiao. All rights reserved. // #import <UIKit/UIKit.h> // 播放 extern NSString *kRemoteControlPlayTapped; // 暫停 extern NSString *kRemoteControlPauseTapped; // 停止 extern NSString *kRemoteControlStopTapped; // 前一首 extern NSString *kRemoteControlPreviousTapped; // 后一首 extern NSString *kRemoteControlNextTapped; // 其它 extern NSString *kRemoteControlOtherTapped; @interface UIApplication (RemoteControl) /** * 注冊對remote control事件的監聽 * * @param observer 監聽者 * @param selector 回調 */ - (void)observeRemoteControl:(id)observerselector:(SEL)selector; @end
在實現文件中,我們需要處理監聽:
// // UIApplication+RemoteControl.m // IOSAudioRemoteControl // // Created by huangyibiao on 15/3/25. // Copyright (c) 2015年 huangyibiao. All rights reserved. // #import "UIApplication+RemoteControl.h" const NSString *kRemoteControlPlayTapped = @"kRemoteControlPlayTapped"; const NSString *kRemoteControlPauseTapped = @"kRemoteControlPauseTapped"; const NSString *kRemoteControlStopTapped = @"kRemoteControlStopTapped"; const NSString *kRemoteControlPreviousTapped = @"kRemoteControlForwardTapped"; const NSString *kRemoteControlNextTapped = @"kRemoteControlBackwardTapped"; const NSString *kRemoteControlOtherTapped = @"kRemoteControlOtherTapped"; @implementation UIApplication (RemoteControl) - (BOOL)canBecomeFirstResponder { return YES; } - (void)remoteControlReceivedWithEvent:(UIEvent *)event { switch (event.subtype) { caseUIEventSubtypeRemoteControlPlay: [selfpostNotification:kRemoteControlPlayTapped]; break; caseUIEventSubtypeRemoteControlPause: [selfpostNotification:kRemoteControlPauseTapped]; break; caseUIEventSubtypeRemoteControlStop: [selfpostNotification:kRemoteControlStopTapped]; break; caseUIEventSubtypeRemoteControlNextTrack: [selfpostNotification:kRemoteControlNextTapped]; break; caseUIEventSubtypeRemoteControlPreviousTrack: [selfpostNotification:kRemoteControlPreviousTapped]; break; default: [selfpostNotification:kRemoteControlOtherTapped]; break; } } - (void)postNotification:(const NSString *)notificationName { [[NSNotificationCenter defaultCenter] postNotificationName:(NSString *)notificationNameobject:nil]; } - (void)observeRemoteControl:(id)observerselector:(SEL)selector { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [centeraddObserver:observerselector:selectorname:(NSString *)kRemoteControlNextTappedobject:nil]; [centeraddObserver:observerselector:selectorname:(NSString *)kRemoteControlPauseTappedobject:nil]; [centeraddObserver:observerselector:selectorname:(NSString *)kRemoteControlStopTappedobject:nil]; [centeraddObserver:observerselector:selectorname:(NSString *)kRemoteControlPreviousTappedobject:nil]; [centeraddObserver:observerselector:selectorname:(NSString *)kRemoteControlPlayTappedobject:nil]; [centeraddObserver:observerselector:selectorname:(NSString *)kRemoteControlOtherTappedobject:nil]; } @end
在播放audio視圖中監聽通知
在播放音頻的界面,可以是在UIViewController里,也只可以是某個UIView里,因此在對應的類在創建或者初始化時調用監聽:
UIApplication *app = [UIApplication sharedApplication]; [appobserveRemoteControl:self selector:@selector(onRemoteControleStateChanged:)];
然后處理一下事件回調:
#pragma mark - remote control - (void)onRemoteControleStateChanged:(NSNotification *)notification { if ([notification.nameisEqualToString:kRemoteControlPlayTapped]) { [self play]; } else if ([notification.nameisEqualToString:kRemoteControlPauseTapped]) { [self pause]; } else if ([notification.nameisEqualToString:kRemoteControlNextTapped]) { [self playNext]; } else if ([notification.nameisEqualToString:kRemoteControlPreviousTapped]) { } else if ([notification.nameisEqualToString:kRemoteControlStopTapped]) { [self_requestPauseAudioPlaying:nil]; } else if ([notification.nameisEqualToString:kRemoteControlOtherTapped]) { } }
配置NowPlaying顯示數據
要想在當前播放中心中顯示當前播放的音頻的信息,需要通過 MPNowPlayingInfoCenter 類,它是一個單例。我們要顯示什么就在它的 nowPlayingInfo 屬性中設置相關配置數據。
要使用這個類及其相關屬性定義,需要引入這兩個頭文件:
#import <MediaPlayer/MPNowPlayingInfoCenter.h> #import <MediaPlayer/MPMediaItem.h>
這里只設置幾項,更多設置,請到MPMediaItem.h頭文件中查看:
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init]; // 設置歌曲播放時長 if (self.time != nil && self.time.length != 0) { [dictsetObject:@(self.time.doubleValue)forKey:MPMediaItemPropertyPlaybackDuration]; } // 設置歌曲名稱 if (self.title != nil && self.title.length != 0) { [dictsetObject:self.titleforKey:MPMediaItemPropertyTitle]; } // 設置鎖屏時的圖片 if (self.iconView.image && [self.iconView.imageisKindOfClass:[UIImage class]]) { MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc]initWithImage:self.iconView.image]; [dictsetObject:artworkforKey:MPMediaItemPropertyArtwork]; } [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = dict;
到此就可以實現我們遠程控制的功能。不過這里只考慮實現,并不考慮什么時候接收,什么時候不再接收,而這里的做法時什么時候都接收遠程控制。這此事就留給大家去學習吧!
源代碼
大家可以到我的GITHUB下載demo: https://github.com/CoderJackyHuang/IOSAudioRemoteControl
參考
關注我
如果在使用過程中遇到問題,或者想要與我交流,可加入有問必答 QQ群: 324400294
關注微信公眾號: iOSDevShares
關注新浪微博賬號:標哥Jacky
標哥的GITHUB地址: CoderJackyHuang
支持并捐助
如果您覺得文章對您很有幫忙,希望得到您的支持。您的捐肋將會給予我最大的鼓勵,感謝您的支持!
支付寶捐助 | 微信捐助 |
---|---|
![]() |
![]() |