静止画をAirPlayする方法について
使っている人は結構使っているAirPlay。
弊社アプリでも多数の要望があり、静止画/動画のAirPlay機能を提供しています。
もう随分前になりますが、iOS4.3から動画の配信がサポートされ、MPMoviePlayerControllerについてはallowsAirPlayというオプション1つでAirPlayでの再生が可能となりました。それなら静止画もきっとAPIがあるだろうと思い色々と探してみたのですが、残念ながら該当する項目はありませんでした。
ということで自力で実装するしかなかったのですが、該当する情報がほぼない状態で大変でしたので、今回はこの静止画のAirPlay実装について紹介したいと思います。
調査に必要なもの
下記3点が必要です。AirPlayerはお手軽でいいのですが、残念ながらLionでは正常に動作しませんのでSnow LeoperdまでのOSが必要です。(通信内容を確認しなくてよいのであればAppleTVでも大丈夫)
- AirPlayer
- Bonjour Brower
- Packet Peeper (あるいは他のパケットキャプチャツール)
AirPlay機器を検出する
Bonjour Browerは同一ネットワークのbonjourデバイスを検出してくれるツールです。AirPlay機器を起動後、Bonjour Browerでチェックしてみると、_airplay._tcp. という項目を発見できると思います。結論から言ってしまうと、ここに表示されるIPアドレスへ直接リクエストを送信することでAirPlay機器上で画像を表示することが可能となります。
AirPlayの通信仕様を探る
ではどのようなリクエストを飛ばせばよいのかを調べます。AirPlayerを起動している端末でPacket Peeperを起動後 "tcp port 7000" でフィルタリングし、パケットを確認できる状態にしておきます。
この状態で標準の写真アプリから該当のAirPlay機器に対してAirPlayを開始すると、こんな感じでガンガン流れてきます。
これでAirPlayのリクエストとしては下記の4種類あることが分かります。photoが写真の送信で、stopがAirPlay終了です。開始時にserver-infoとslideshow-featuresがリクエストされていますが、動作には直接関係がなく、実際には初めてphotoリクエストを受け取った時点でAirPlayが開始されます。
GET /server-info GET /slideshow-features PUT /photo POST /stop
AirPlayを実装する
AirPlayの実装自体は単純です。Bonjour Browerで見つけたIPに対して上記リクエストを送信するだけで静止画が表示されます。色々端折ってますがこんな感じ。終了させる場合は、stopリクエストです。
#import "GTMHTTPFetcher.h" - (void)pushImage{ NSURL *url = [NSURL URLWithString:@"http://192.168.101.6:7000/photo"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"PUT"]; [request addValue:@"MediaControl/1.0" forHTTPHeaderField:@"User-Agent"]; [request setHTTPBody:UIImageJPEGRepresentation(image, 0.8)]; GTMHTTPFetcher *fetcher = [GTMHTTPFetcher fetcherWithRequest:request]; [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError*error){ if(error){ // エラー処理 } }]; }
1つ注意点としては、AirPlay機器にしばらくリクエストを送信しない状態が続くとAirPlayが終了してしまいます。正しい方法はよく分からないのですが、定期的にserver-infoリクエストを送信するという対策で上手く行っています。
その他必要なこと
今回はテストなのでIPを直接指定しましたが、実際には自分で機器を検出する必要があります。Bonjour Browerを実装するようなものなのですが、こちらについては、iPhoneでBonjour使ってホストを見つける/見つけてもらうが大変参考になりました。