airplay适配 ios
2017-02-13 23:50:21 wirelessdisplay 阅读数 4630

AirPlay是苹果公司的在iOS4.2及OS X Mountain Lion中加入的一种播放技术,可以将iPhone、iPod touch、iPad及Mac(需要OS X Mountain Lion或更新版)上的视频镜像传送到支持Airplay的设备(如:音箱、Apple TV)中播放。使用Airplay需要iOS4.2版本的设备或Mac电脑上的iTunes10.1以上版本。视频镜像则需要iOS 5及OS X Mountain Lion。

 

当用户的设备(Mac, PC, iPod touch, iPhone, iPad)与支持AirPlay技术的音箱在同一无线局域网(WIFI)内的时候,用户在Mac或PC上打开iTunes 10或更高版本后,就会在iTunes音量条旁边(iTunes 10在窗口的右下角)看到一个AirPlay按钮。点击该AirPlay按钮,然后选择需要同步到的设备,就可以选择将音乐或视频无线同步到设备进行播放。而iPod touch, iPhone和iPad用户则可以在相应的“音乐”,“视频”以及支持AirPlay功能的第三方软件界面找到AirPlay按钮,操作同Mac和PC。

 

由于AirPlay并非是开源的而且需要逆向获得AirPlay key,所以要实现AirPlay的难度不小,网上流传的AirPlay协议都是非官方的,WirelessDisplay群里有下载好的协议,每次 IOS的升级都会对AirPlay协议进行一定的修改,给刚接触想学习AirPlay的朋友推荐几个简单的AirPlay实现

第一个流传出来的AirPlay是由James Laird大神发布的,原因就是他的女朋友想将自己的ipod无线投到音响上播放,当时只有苹果官方的盒子才能够支持,James Laird一怒之下破解了当时的AirPlay协议,并且公开了Private Apple AirPlay key。

https://github.com/abrasive/shairport  

这个daemon采用c语言编写,可以进行ios7及以下设备的音频投射,在公司用ipod实测可用。

https://github.com/gpfduoduo/AirPlay-Receiver-on-Android

我天朝人发布的开源项目,支持IOS8.4之前的音视频投屏以及图片推送,经过实测可用。

 

AirPlay版本繁多,协议也比较多:镜像,非镜像,图片,视频,音频,第三方app等等各种协议之间都有差别,以后会慢慢给大家介绍的。

 

要实现AirPlay的第一步就是要实现ios与AirPlay之间的相互发现,可以使用zeroconf,mdns等开源协议来实现,下一章会详细介绍介绍这几种发现协议。

 

 

     技术交流有兴趣请加:

     音视频技术交流群:308601278

     无线投屏技术交流群:582349005

     

     我司有成熟的无线投屏盒子销售,也可做音视频及无线投屏相关产品和技术的定制化开发

     可访问我司官网了解详细情况 必捷网络无线投屏SDK

     商务合作可发邮件marketing@bijienetworks.com

 

 

 

2019-02-20 10:19:01 wirelessdisplay 阅读数 2761

要实现airPlay的镜像Server端功能,要从以下几个方面来考虑

 

1.发现过程

 

 

2.协商过程

 

 

 

3.视频传输

 

 

4.解密过程

 

 

发现过程

使用Bonjour,可以参考mDNSResponder,jmdns,注册两个服务:airtunes和airplay,AirplayTxt以及RaopTxt照着demo填写就可以了,也可以根据自己的要求修改其中的值,

需要注意的如下:

airtunes:   “12345@wirelessdisplay” , ”_raop._tcp.”

airplay:    “wirelessdisplay” , ”_airplay._tcp.”

参数中”_airplay._tcp.”和’’_raop._tcp.”不可修改。

发布了服务之后,ios设备中应该就可以搜索到Server端了

 

主要有以下协商过程

c-s: pair-setup

 

s-c: xxx

 

c-s: pair-verify

 

s-c: xxx

 

c-s: fp-setup

 

s-c: xxx

 

c-s: fp-setup

 

s-c: xxx

 

setup

 

setup response

 

setup

 

setup respnose

 

 

pair-setup,pair-verify配对验证,Server端根据收到的信息进行回复,格式类似RTSP

fp-setup(第一次和第二次),Fairplay相关。

第一次setup阶段会收到一大串数据,是按照plist格式生成的,用相应的方法进行解析可以得到ekey和eiv等信息,用于后续的解密。

第二次setup阶段获得type,通过type来判断视频数据或音频数据,通知接收端建立传输通道准备进行音视频数据的发送,加密过的屏幕镜像数据通过指定的端口(一般为7100)发送到接收端。

接收端收到发送过来的数据后进行解密,解密后的数据就可以进行播放了。

中间也可能会有GET_PARAMETER,SET_PARAMETER来调整音量等信息。

 

关于解密部分目前主要有两种方法:

1.从apptv或macOS获取。

2.从市面上已有的可投屏产品中获取。

 

 技术交流有兴趣请加:
 音视频技术交流群:308601278
 无线投屏技术交流群:582349005
 
 详情可访问我司官网 必捷网络|因必捷而简单
 商务合作请至邮件marketing@bijienetworks.com

2018-09-06 14:55:00 weixin_34033624 阅读数 680

这篇文章注重于如何实现AirPlay投屏功能.具体AirPlay的实现逻辑这里不再赘述,网上帖子很多

首先.想要呼出AirPlay列表的话,需要将MPVolumnView控件声明且添加到UI.上使用之前需要引入头文件<MediaPlayer/MediaPlayer.h>.后续如果有AirPlay设备可用并且MPVolumnView存在于UI中的话.即可呼出列表
MPVolumnView:一个系统内置的控件.继承自UIView.内部自定义了三个控件:MPVolumeSlider(音量进度条)UILabel(显示文字)MPButton(点击呼出AirPlay选择器)
①如何解决MPVolumnView添加到UI中之后高亮效果会出现系统原生icon的问题
答:设置不同State的image为ni即可.
code:

MPVolumnView *volumnView = [[MPVolumnView alloc] init];
//此处btnSender的实际类型为MPButton
UIButton *btnSender = [volumnView objectWithBlock:^BOOL(UIView *obj) {
        return [obj isKindOfClass:[UIButton class]];
    }];
    [btnSender setImage:nil forState:UIControlStateNormal];
    [btnSender setImage:nil forState:UIControlStateHighlighted];
    [btnSender setImage:nil forState:UIControlStateSelected];

②如何解决在没有可用设备情况下点击MPVolumnView不会呼出AudioRoutePicker的问题
答:目前我找到的一个解决方案是完全无视MPVolumnView.将它在init时frame设置为0,0,0,0 然后在界面上自己添加一个UIButton.在它的点击事件中给MPVolumnView的MPButton发送一个UIControlEventTouchUpInside来触发MPVolumnView的_displayAudioRoutePicker事件
code:

//首先.自定义类.并且继承MPVolumnView
@interface SparkMPVolumnView : MPVolumeView

@property(nonatomic,weak)UIButton *MPButton;
@end

@implementation SparkMPVolumnView

-(instancetype)init{
    if(self = [self initWithFrame:CGRectZero]){
        self.backgroundColor = [UIColor clearColor];
        self.showsVolumeSlider = NO;
        self.tag = kTVMPVolumeViewTag;
        [self initMPButton];
    }
    return self;
}
//这个的目的是在AirPlay没有任何设备时也能呼出Picker使用
- (void)initMPButton{
    UIButton *btnSender = [self.subviews objectWithBlock:^BOOL(UIView *obj) {
        return [obj isKindOfClass:[UIButton class]];
    }];
    [btnSender setImage:nil forState:UIControlStateNormal];
    [btnSender setImage:nil forState:UIControlStateHighlighted];
    [btnSender setImage:nil forState:UIControlStateSelected];
    [btnSender setBounds:CGRectZero];
    self.MPButton = btnSender;
}
//在自定义按钮的按下事件中发送给MPButton
//此处sparkVolumView为一个SparkMPVolumnView实例
-(void)airPlayButtonAction:(UIButton *)sender{
        [self.sparkVolumView.MPButton sendActionsForControlEvents:UIControlEventTouchUpInside];
}

③如何知道AirPlay的连接和断开状态?
答:其他资料大多是通过注册MPVolumeViewWirelessRouteActiveDidChangeNotification来进行判断的.但是这个通知有一个问题就是在存在多个MPVolumnView时会出现多次发送,并且如果在声明MPVolumnView控件时是连接AirPlay设备的,它会先发送一个属性wirelessRouteActive为NO的通知(即未连接任何设备),然后立马发送一个wirelessRouteActive位YES的通知(连接到了设备).故我并未采用此方案.
我注册了AVAudioSessionRouteChangeNotification通知.这个通知在音频通道发生变化时会进行调用(例如插入/拔出耳机 扬声器/听筒切换 连接/断开AirPlay设备).这个的通知是唯一且不重复的.在发生改变时[AVAudioSession sharedInstance]会发送此通知.在具体通知中通过获取当前的AirPlay通道名称来判断是否连接到了投屏设备
code:

-(void)registerNotification{
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteHasChangedNotification:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
}
- (void)audioRouteHasChangedNotification:(NSNotification *)notification{
    NSString *airplayDeviceName = [self activeAirplayOutputRouteName];
    BOOL isAirPlay = self.airplayDeviceName.length > 0;
}
//遍历当前设备所有通道.返回isEqualToString:AVAudioSessionPortAirPlay通道的具体名称,如果名称不为nil则为当前连接到了AirPlay
- (NSString*)activeAirplayOutputRouteName
{
    AVAudioSession* audioSession = [AVAudioSession sharedInstance];
    AVAudioSessionRouteDescription* currentRoute = audioSession.currentRoute;
    for (AVAudioSessionPortDescription* outputPort in currentRoute.outputs){
        if ([outputPort.portType isEqualToString:AVAudioSessionPortAirPlay])
            return outputPort.portName;
    }
    
    return nil;
}

④为什么播放过程中会电视端会出现暂停和退出播放的情况
答:AirPlay实现的原理是一个Socket通信.并且会在新的通道请求之后断开之前的.所有在项目中你理论上是有多处会播放视频的.只要调用一个新播放器的Play方法.设备端就会认为你重新发起了一个Socket请求,断开之前的播放并且发起新的视频播放.故需要保证在AirPlay连接的情况下不调用任何视频的暂停和播放代码.
在我的项目中逻辑是比较复杂的,故实现方式是通过一个单例的Manager强引用一个AVPlayer,所有的AirPlay播放和暂停请求都通过它来实现..其他代码只要保证在连接AirPlay的时候不进行操作就可以了.

⑤AirPlay在播放时播放新视频为什么可能会投屏失败?
答:这个我也无解.没有查到相关的资料.现在的解决方案是在投放新视频前检测,如果只有有视频,暂停播放并且将AVPlayer设置为nil.保证电视端退出投屏,随后增加1.5f延时再进行播放.基本解决了投屏失败的问题

其他问题欢迎大家在评论区讨论,做AirPlay时趟了许多坑.希望这篇文章能帮助大家少走弯路.有不对的地方希望指出,第一时间修正

2019-04-20 06:47:16 weixin_34378922 阅读数 7

苹果投屏功能主要基于 AirPlay,可以隔空播放音视频和图片。苹果原生的 AirPlay 有发送端和接收端之分,分别为以下设备

发送端

  1. iPhone
  2. iPad
  3. iPod touch
  4. Mac

接收端:Apple TV

按照常规的使用方法,只能投到 Apple TV 上面。

虽然 AirPlay 传输协议是苹果私有的,不过很多厂商逆向破解了 AirPlay 传输协议,所以只要国内的各种安卓电视盒子安装了对应的接收软件,也能够接收 iPhone 的投屏。

AirPlay 使用的时候有几种使用模式,在 iPhone 上目前主要分为两种模式:

  1. Mirror device's screen (屏幕镜像)
  2. AirPlay video (隔空播放音视频)

Mirror device's screen

屏幕镜像模式是一种全局的操作,在手机的控制面板开启。一般来说,在该模式下,手机上显示什么,TV 上就显示什么,直接将手机内容展示到 TV 的显示器上面。

虽然这种模式叫镜像模式,但是,其实在这种模式下,APP 内部可以写代码检测是否开启了镜像模式,可以针对 Apple TV 的屏幕写一屏新的 UI,也就是手机和 TV 的显示屏展示内容可以不同,相当于外接了一个屏幕,展示新的内容。通过这种方法,可以把手机页面作为一个遥控器,真正展示内容可以放到 TV 的屏幕。

在使用镜像模式的时候,如果手机锁屏,TV 端也看不到任何内容了。也就是说,在这种模式下,手机必须一直是常亮的。个人认为这种模式比较适合用来做操作演示,不太适合用来播放视频。

镜像方式开启方法:support.apple.com/zh-cn/HT204…

AirPlay video

隔空播放的方式其实是在嵌入在某个 APP 内部的,在 APP 内部进行操作之后,可以隔空将音视频和图片投送到 TV 上播放。

这种方式就像是把一个文件推送到 TV 端,然后用 TV 的屏幕进行播放,例如:

  1. 腾讯视频 APP 投视频
  2. 得到 APP 投音频
  3. 系统相册投图片

该方式需要 APP 开发者在软件内部写一些代码来支持投屏,比较适合单个视频的播放。比如用腾讯视频看电影的时候就可以把视频投到 TV 上去播放,这个时候手机是可以直接锁屏的,投放的效果也非常不错。

但是这种方式仅仅是对文件的隔空播放,尚未发现可以自定义 TV 端播放页面的 API。

隔空播放开启方法:support.apple.com/zh-cn/HT204…

Apple TV 之外的设备接收 AirPlay

一般来说只能用 Apple TV 作为接收端,不过有很多第三方破解了苹果的传输协议,所以很多平台通过安装一个接收端软件来模仿 Apple TV 接收 iPhone 等设备投送的数据。

以下为一些第三方接收软件

AirServer

该软件有 PC 和 Mac 版本的接收端,安装后可以直接接收 iPhone 投送的数据。如果想将 Mac 作为 AirPlay 接收端进行投屏,该软件是首选。

产品官网:www.airserver.com

乐播投屏

乐播投屏有安卓电视盒子的 TV 版本的接收端,电视盒子安卓该软件之后可以直接接受数据。

目前国内的很多厂商的电视盒子都内置了乐播投屏的 TV 版本的接收端软件,安装该软件之后,即可直接接收 iPhone 的 AirPlay 投屏。

而且乐播投屏不仅有接受端的软件,还有 Android 手机和 PC 的发送端软件,安装该软件之后,可以像 iPhone 一样直接投屏,然后乐播投屏的 TV 端可以接收到数据。

产品官网:www.hpplay.com.cn

玄学问题

在镜像模式下手机端频繁切换和播放视频,AirPlay 会莫名其妙地断开。因为我是在 Mac 上安装 AirServer 进行测试的,所以不知道是 AirPlay 本身的问题,还是 AirServer 的问题。

参考

转载于:https://juejin.im/post/5cbac0446fb9a0687b7ddd01

2016-09-05 15:24:00 weixin_33924770 阅读数 3

前言

  • 什么是适配:
    • 适应、兼容各种不同的情况。
  • iOS 开发中,适配的常见种类:
    • 1)系统适配, 针对不同版本的操作系统进行适配。

    • 2)屏幕适配,针对不同大小的屏幕尺寸进行适配。
      • iPhone 的尺寸:3.5 inch、4.0 inch、4.7 inch、5.5 inch 。
      • iPad 的尺寸:7.9 inch、9.7 inch、12.9 inch 。
      • 屏幕方向:竖屏、横屏。

1、系统适配

  • Objective-C

        // 获取系统版本
        float systemVersion = [UIDevice currentDevice].systemVersion.floatValue;
    
        // 判断系统版本
        if ([UIDevice currentDevice].systemVersion.floatValue > 9.0) {
    
            // iOS 9 及其以上系统运行
    
        } else {
    
            // iOS 9 以下系统系统运行
        }
  • Swift

        // 获取系统版本
        let systemVersion:Float = NSString(string: UIDevice.current.systemVersion).floatValue
    
        // 判断系统版本
        if NSString(string: UIDevice.current.systemVersion).floatValue > 9.0 {
    
            // iOS 9 及其以上系统运行
    
        } else {
    
            // iOS 9 以下系统系统运行
        }
    
        // 判断系统版本
        if #available(iOS 9.0, *) {
    
            // iOS 9 及其以上系统运行
    
        } else {
    
            // iOS 9 以下系统系统运行
        }

2、屏幕适配

2.1 屏幕适配的发展历史

  • iPhone3GS  iPhone4
    • 没有屏幕适配可言,全部用 frame、bounds、center 进行布局。
    • 很多这样的现象:坐标值、宽度高度值全部写死。

          UIButton *btn1 = [[UIButton alloc] init];
          btn1.frame = CGRectMake(0, iPhone3GS0, 320 - b, 480 - c);
  • iPad 出现、iPhone 横屏
    • 出现 Autoresizing 技术,让横竖屏适配相对简单,让子控件可以跟随父控件的行为自动发生相应的变化。
      • 前提:关闭 Autolayout 功能。
      • 局限性:只能解决子控件跟父控件的相对关系问题,不能解决兄弟控件的相对关系问题。
  • iOS 6.0(Xcode 4)开始
    • 出现了 Autolayout 技术。
    • 从 iOS 7.0 (Xcode 5) 开始,开始流行 Autolayout。

2.2 Autoresizing

2.2.1 Storyboard/Xib 中使用

  • 关闭 Autolayout 功能

    • 在 SB 的 Show the File Inspector 选项卡中取消对 Use Auto Layout 和 UseSize Classes 的勾选。

      Fitter10

    • 关闭 Autolayout 后,SB 的 Show the Size Inspector 选项卡中将出现 Autoresizing 设置模块,如下图。

      Fitter11

      • 此设置模块左侧方框内为设置选项,右侧矩形为设置效果预览。
      • 需要在子视图上设置。

      • 小方框四周的四个设置线,选中时,子视图与父视图的边距将保持不变。
        • 左和右、上和下,只能二选一,若同时选中,只有左和上起作用。
      • 小方框内部的两个线,选中时,子视图的宽或高将随父视图的变化而变化。

  • 设置示例:

    • 示例 1:

      • 设置子视图在父视图的右下角。
        • 将子视图放在父视图的右下角。
        • 设置子视图的 Autoresizing 右和下选项线。

          Fitter12Fitter13

      • 设置效果。
        • 子视图与父视图的右和下边距保持不变。
        • 子视图的宽和高保持不变。

          Fitter14

    • 示例 2:

      • 设置子视图在父视图的下边,且宽度与父视图的宽度相等。
        • 将子视图放在父视图的下边。
        • 设置子视图的 Autoresizing 下和内部小方框的宽度选项线。

          Fitter15Fitter16

      • 设置效果。
        • 子视图与父视图的下和左右边距保持不变。
        • 子视图的高保持不变。
        • 子视图的宽随父视图的变化而变化。

          Fitter17

2.2.2 纯代码中使用

  • Objective-C

    • 子视图设置选项:

          UIViewAutoresizingNone                 = 0,         // 不跟随
          UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,    // 左边距 随父视图变化,右边距不变
          UIViewAutoresizingFlexibleRightMargin  = 1 << 2,    // 右边距 随父视图变化,左边距不变
          UIViewAutoresizingFlexibleTopMargin    = 1 << 3,    // 上边距 随父视图变化,下边距不变
          UIViewAutoresizingFlexibleBottomMargin = 1 << 5     // 下边距 随父视图变化,上边距不变
      
          UIViewAutoresizingFlexibleWidth        = 1 << 1,    // 宽度 随父视图变化,左右边距不变
          UIViewAutoresizingFlexibleHeight       = 1 << 4,    // 高度 随父视图变化,上下边距不变
    • 设置示例:

      • 示例 1:

        • 设置子视图在父视图的右下角。

              UIView *blueView = [[UIView alloc] init];
              blueView.backgroundColor = [UIColor blueColor];
              CGFloat x = self.view.bounds.size.width - 100;
              CGFloat y = self.view.bounds.size.height - 100;
              blueView.frame = CGRectMake(x, y, 100, 100);
          
              // 设置父视图是否允许子视图跟随变化
              /*
                  default is YES
              */
              self.view.autoresizesSubviews = YES;
          
              // 设置子视图的跟随效果
              /* 
                  子视图的左边距和上边距随父视图的变化而变化,即右边距和下边距保持不变
              */
              blueView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin 
                                        | UIViewAutoresizingFlexibleTopMargin;
          
              [self.view addSubview:blueView];
        • 设置效果。
          • 子视图与父视图的右和下边距保持不变。
          • 子视图的宽和高保持不变。

            Fitter14

      • 示例 2:

        • 设置子视图在父视图的下边,且宽度与父视图的宽度相等。

              UIView *blueView = [[UIView alloc] init];
              blueView.backgroundColor = [UIColor blueColor];
              CGFloat w = self.view.bounds.size.width;
              CGFloat y = self.view.bounds.size.height - 100;
              blueView.frame = CGRectMake(0, y, w, 100);
          
              // 设置父视图是否允许子视图跟随变化
              /*
                  default is YES
              */
              self.view.autoresizesSubviews = YES;
          
              // 设置子视图的跟随效果
              /* 
                  子视图的宽度和上边距随父视图的变化而变化,即左右边距和下边距保持不变
              */
              blueView.autoresizingMask = UIViewAutoresizingFlexibleWidth 
                                        | UIViewAutoresizingFlexibleTopMargin;
          
              [self.view addSubview:blueView];
        • 设置效果。
          • 子视图与父视图的下和左右边距保持不变。
          • 子视图的高保持不变。
          • 子视图的宽随父视图的变化而变化。

            Fitter17

2.3 Autolayout

3、App 图标和启动图片

3.1 App 图标设置

  • App 图标尺寸

    Fitter4

  • App 图标设置

    Fitter18

    Fitter19

    • 默认从 AppIcon 中加载 App 图标。

    Fitter20

    Fitter21

    Fitter22

    • 20pt 表示 20 个点,即 2x 图片的像素为 (20 * 2) * (20 * 2) 像素,3x 图片的像素为 (20 * 3) * (20 * 3) 像素。

3.2 启动图片设置

  • 启动图片尺寸

    Fitter1

  • 启动图片设置

    Fitter18

    Fitter23

    • Launch Images Sources :从指定的位置加载启动图片。
    • Launch Screen Files :默认,从指定的文件(xib 或 sb 文件)加载启动屏幕(启动图片)。

    Fitter24

    • 修改为从指定的位置加载启动图片,清除 Launch Screen Files 项内容,点击 Use Asset Catalog... ,按照默认设置,点击 Migrate 。

    Fitter25

    Fitter26

    • 在 Assets.xcassets 中将自动添加 LaunchImage(或者 Brand Assets)。

    Fitter27

    Fitter28

    • Retina HD 5.5 为 5.5 寸屏的设备,Retina HD 4.7 为 4.7 寸屏的设备,Retina HD 4 为 4.0 寸屏的设备;Portrait 为竖屏,Landscape 为横屏。

4、iOS 设备各种尺寸

4.1 iOS 设备尺寸

Fitter1

4.2 Resolutions 分辨率

Fitter2

4.3 Displays 显示

Fitter3

4.4 Dimensions App 图标尺寸

Fitter4

4.5 Common Design Elements 常见控件尺寸

Fitter5

4.6 Icons 控件图标尺寸

Fitter6

4.7 Default Font Sizes iPhone 5/5C/5S/6 控件字体大小

Fitter7

4.8 Default Font Sizes iPhone 6 Plus 控件字体大小

Fitter8

4.9 Size Classes For Adaptive Layout

Fitter9

转载于:https://www.cnblogs.com/QianChia/p/5849618.html

iOS - iOS 适配

阅读数 17

iOS - iOS 适配

阅读数 13

iOS - iOS 适配

阅读数 10

ios适配

阅读数 630

iOS适配

阅读数 489

没有更多推荐了,返回首页