2010年10月3日日曜日

TwitterUserStreamをAdobeAIRで使う

先日、TwitterのUserStreamが一般公開されましたね!
空うさぎでも早速取り込んでみました。

UserStreamはbeta期間を経て、今回の一般公開になったのですが、beta期間中はそのAPIを使ったツールは公開できないので、開発用空うさぎでのみ使用できるようにしていました。
一般公開になったタイミングですぐ反映できるね!と思っていたのですが、いざ公開されたものを見ると、https通信のみ許可されている形になっていました。

空うさぎは、AdobeAIRを使用しているのですが、AdobeAIRでhttpsのSecureなSocket通信をするには、
Flex4から採用された SecureSocketというものがあるようです。
Flex3(AdobeAIR1.5)を使用していたので、Flex4(AdobeAIR2.0)にアップしようとまずは試みたのですが...断念。
そんなにすんなり移行できるものではなかったようです。。

NativeApplication.nativeApplication.undo()
NativeApplication.nativeApplication.redo()
のメソッドは無くなっている。

UIについてもmxmlのネームスペースをすべて変更が必要。
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">

sのsparkコンポーネントにすると、無くなった(設定方法が変わった?)プロパティが数多くある。
mxにしてみても、無くなった(設定方法が変わった?)プロパティがちょいちょいある。
無理矢理やってみても、見た目が結構ガラっと変わってしまっていて、すんなり移行できない感。

traceを書いても、コンソールに表示されない。
FlashPlayerをデバッグ版にしたらみれる...という記事もありましたが、AIRだとどうなるかは見きれてません。。

その他、
Flex3で作成したアプリケーションを、Flex4でコンパイルしなおすと、違うアプリと認識されるようでした。
ApplicationDescriptor.xmlのxmlsネームスペースのバージョンを変えると違うアプリになってしまう?
何か方法があったのかもしれませんが...

ということで、AIR1.5で、作成する方向を探しました。
結論としては、as3cryptoのライブラリを使って無事にアクセス成功。

import com.hurlant.crypto.tls.TLSSocket;

public static const STREAM_PATH:String = "userstream.twitter.com";
public static const FILTER_URL:String = "/2/user.json";
private static const STREAM_PORT:int = 443;

public function connect():void {
var socket:TLSSocket = new TLSSocket();
socket.addEventListener(Event.CONNECT, connectHandler);
socket.addEventListener(ProgressEvent.SOCKET_DATA, handleData);
socket.connect(STREAM_PATH, STREAM_PORT);
}

private function connectHandler(event:Event):void {
var path:String = "GET " + FILTER_URL + " HTTP/1.1\r\n";
socket.writeUTFBytes(path);
socket.writeUTFBytes("Host: " + STREAM_PATH + "\r\n");

var oauthParameter:String = ...;
socket.writeUTFBytes("WWW-Authenticate: OAuth\r\n");
socket.writeUTFBytes("Authorization: " + oauthParameter + "\r\n");

socket.writeUTFBytes("\r\n");
socket.flush();
}

private function handleData(event:ProgressEvent):void{
var available:int = socket.bytesAvailable;
var value:String = socket.readUTFBytes(available);
trace(value);
}

こんな感じのイメージで。
• • •