使用 AirPlay 发送图片

时间:2023-01-28 19:55:46

原文:http://livevision.us/wordpress/2011/02/16/airplay-without-private-api/

如果不是 Erica Sadun 的努力以及 AirPlayer、AirFlick、AirPDF以及 AirSay 这样类似的工具的出现,我可能不会兴起尝试一把的念头。在这篇文章中,我将演示创建一个 iOS app( camThis)将图片发送到Apple TV,既不需要使用任何私有 API,也不需要越狱。我没有提交到苹果商店,但如果有任何新的消息我将随时奉上。

更新:camThis 目前已被苹果接受。

所需工具:

译者注:这个链接中 AirPlayer的下载链接已经被删除,读者可以在此处下载: http://download.cnet.com/AirPlayer/3001-13632_4-75330532.html?spi=cc4808989275f217e583547fa2bef669

运行 AirPlayer:

  • 在本文中,我们将采取一点类似于欺骗的技巧,以便对 Apple TV 的网络通信进行嗅探...下载并运行 AirPlayer。

译者注:AirPlayer 已经不可用,请用其他类似软件代替。

  • AirPlayer 通过广播 _ariplay._tcp 消息并被 bonjour 发现,以此来伪装成 Apple TV,因此你的 Mac 可以被看成一台 Apple TV 。
  • 当 AirPlayer 运行时,处于同一网络中的 iOS 设备可以向 AirPlayer 推送图片。

运行 Bonjour Browser: (download)

  • Bonjour Browser 是一个杰出的 Mac 应用程序,它能够发现网络中的所有bonjour 设备。
  • 我们只是用 Bonjour Browser 找出 Apple TV(AirPlayer) 的IP地址而已,因此我不会告诉你如何编写一个 iOS bonjour 应用程序。

一旦获得 IP 地址,请将地址+端口记下来(在下图中,我用Mac 模拟出的AppleTV的IP地址和端口是 192.168.1.102:7000)。

使用 AirPlay 发送图片

BonjourBrowser

用Packet Peeper嗅探iOS Airplay 设备发出的网络包:

  • Packet Peeper 是一个用于嗅探 Mac 上发出/接收到的网络包的开源工具
  • 它支持 tcpdump 过滤器。我们将使用它来过滤网络包,以便我们将注意力集中到 Apple TV的网络包。
  • 当你开始一个回话后,你可以设置一个类似于 “tcp port 7000”之类的过滤器

选择一张AirPlayer的图片:

  • 如果一切顺利,你会在照片应用程序的右上角看到一个 airplay的标记。

按下 airplay 按钮。可以观察到Packet Peeper中的监控到大量网络包。

  • 一旦监控到网络包,你可以选中会话中的所有网络包,然后选择 “View 菜单->View TCP Stream” ,结果类似下图所示。
使用 AirPlay 发送图片

PacketPeeper results

  • 看到左边的会话吗?那是最开始从设备发向AppleTV的请求,请求交换客户端/服务器关系。这就是大家所知的ReverseHTTP——没错,实际上它已经列入了  RFC 草案
  • 为了让我的 iPhone app能够初始化并处理ReverseHTTP,我头疼了数个小时——但你没有必要关心它,你只需关心诸如 /server-info,/photo之类的即可。

示例代码:

  • ok, 现在你已经具备了所有条件,可以发送一张图片到AppleTV了。
  • 假设使用ASIHTTPRequest框架。如果你不熟悉它,请参考 这里
  • 这是代码 (简单,不是吗?)

- (void) sendUIImage {

UIImage *img = [UIImageimageNamed:@"test.png"];

NSData *data = UIImageJPEGRepresentation(img,1.0);

NSMutableData *mdata = [[[NSMutableData alloc]initWithData:data] autorelease];

 

NSLog(@"PUT photo...");

NSURL *url = [NSURLURLWithString:@"http://192.168.2.32:7000/photo"];

request = [ASIHTTPRequest requestWithURL:url];

[request setRequestMethod:@"PUT"];

[requestaddRequestHeader:@"User-Agent" value:@"MediaControl/1.0"];

[request setPostBody:mdata];

[requestsetShouldAttemptPersistentConnection:YES];

[request startSynchronous];

NSError *error = [request error];

if (!error) {

NSLog(@"success");

} else {

NSLog(@"%@",[errorlocalizedDescription]);

}

}