iOS Remote Control

Demetria935 8年前發布 | 8K 次閱讀 iOS開發 移動開發

前言

RemoteControl,這里就翻譯為遠程控制吧。

遠程控制是為用戶提供操作App多媒體的。遠程控制事件源于外部附件或由系統顯示的傳輸控制,并通過媒體播放器框架的類傳送到應用程序。播放音頻或視頻內容的應用程序使用這些事件來開始和停止播放,更改曲目,甚至速度的項目。所有的媒體應用程序應該支持這些事件。

除了支持遠程控制事件,應用程序可以使用媒體播放器框架,以提供播放信息的曲目。該系統在適當的地方顯示播放信息,如鎖屏和控制中心。有關媒體播放器框架類的更多信息,見媒體播放器框架參考 Media Player Framework Reference .

Remote Control功能

RemoteControl可以用來在不打開app的情況下控制app中的多媒體播放,主要包括:

  1. 鎖屏界面雙擊Home鍵后出現的播放操作區域
  2. iOS7之后控制中心的播放操作區域
  3. iOS7之前雙擊home鍵后出現的進程中向左滑動出現的播放操作區域
  4. AppleTV,AirPlay中顯示的播放操作區域
  5. 耳機線控
  6. 車載系統的設置

讓App支持Remote Control

要接收遠程控制事件,需要做到以下的幾點:

  1. 接收者必須可以成為第一響應者;
  2. 接收者必須顯示聲明接收RemoteControl事件;
  3. 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

參考

蘋果官方文檔:Remote Control Events

關注我

如果在使用過程中遇到問題,或者想要與我交流,可加入有問必答 QQ群: 324400294

關注微信公眾號: iOSDevShares

關注新浪微博賬號:標哥Jacky

標哥的GITHUB地址: CoderJackyHuang

支持并捐助

如果您覺得文章對您很有幫忙,希望得到您的支持。您的捐肋將會給予我最大的鼓勵,感謝您的支持!

支付寶捐助 微信捐助

來自: http://www.henishuo.com/ios-remote-control/

 本文由用戶 Demetria935 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!