Twitter Streaming APIを使って関連TLをテレビにオーバーレイ表示するAIRアプリを作ってみた

一昨年の記事、テレビにTwitterの関連TLをオーバーレイ表示するAIRアプリを作ってみた - Tosshi Note で紹介したアプリを Twitter Streaming API に対応してみました。 AIRアプリ自体の公開は反応をみることにして、Twitter Streaming API を ActionScript で実装する例があまり見つからなかったので、とりあえず載せときます。 ちなみに URLStream を使って実装していますが、URLStream の Progress イベントは HTTP chunk レスポンスの受信とは別に起こります。そのため、流れの速いTLでないと TweetReceived イベントにタイムラグが発生するかもしれません。 URLStreamから取得できるデータ本体は、[ツイートJSON][CRLF][ツイートJSON][CRLF][ツイートJSON][CRLF] となります。 ツイートがないときに、Keep-Aliveのためのパケットも[CRLF]となるため、バッファに文字列をためつつ、[CRLF]を探しては切り出して、文字列長0でなければJSONをパースしてツイート受信イベント発生という流れです。 以下、ソースをべた貼りしておきます。 TwitterStreamLoader.as コンストラクタ引数にBASIC認証のTwitterスクリーン名とパスワードを指定します。 package com.tilfin.tvtwlayer.twitter { import com.adobe.serialization.json.JSON; import flash.events.EventDispatcher; import flash.events.HTTPStatusEvent; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.net.URLRequest; import flash.net.URLRequestHeader; import flash.net.URLRequestMethod; import flash.net.URLStream; import flash.net.URLVariables; import mx.utils.Base64Encoder; /** * Tweet Received イベント / [Event(name=“tweetReceived”, type=“com.tilfin.tvtwlayer.twitter.TwitterStreamEvent”)] /* * Twitter Stream API Loader / public class TwitterStreamLoader extends EventDispatcher { private static const ROOT_URL:String = “http://stream.twitter.com/1/statuses/"; private var _authHeader:URLRequestHeader; private var _stream:URLStream; private var _streamBuffer:String = “”; /* * コンストラクタ * * @param screenName スクリーン名 * @param password パスワード / public function TwitterStreamLoader(screenName:String , password:String) { super(); var encoder:Base64Encoder = new Base64Encoder(); encoder.encode(screenName + “:” + password); _authHeader = new URLRequestHeader(“Authorization”, “Basic " + encoder.flush()); } /* * 各種フィルタをかけたストリームの受信を開始します。 * * @param params クエリパラメータ / public function loadFilterStream(params:Object):void { var variables:URLVariables = new URLVariables(); for (var key:String in params) { variables[key] = params[key]; } var request:URLRequest = new URLRequest(ROOT_URL + “filter.json”); request.method = URLRequestMethod.POST; request.requestHeaders = [ _authHeader ]; request.data = variables; _stream = new URLStream(); _stream.addEventListener(IOErrorEvent.IO_ERROR, onIoError); _stream.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, onHttpResponseStatus); _stream.addEventListener(ProgressEvent.PROGRESS, onProgress); _stream.load(request); } /* * ストリームを閉じます。 */ public function close():void { _stream.removeEventListener(IOErrorEvent.IO_ERROR, onIoError); _stream.removeEventListener(ProgressEvent.PROGRESS, onProgress); _stream.close(); _stream = null; } private function onProgress(event:ProgressEvent):void { var buffer:String = _stream.readUTFBytes(_stream.bytesAvailable); _streamBuffer += buffer; var twstr:String; var splitpos:int = _streamBuffer.indexOf(”\r\n”); while (splitpos > -1) { twstr = _streamBuffer.substr(0, splitpos); if (twstr.length > 0) { receivedTweet(twstr); } _streamBuffer = _streamBuffer.substr(splitpos + 2); splitpos = _streamBuffer.indexOf("\r\n"); } } private function receivedTweet(str:String):void { var tweet:Object = JSON.decode(str); dispatchEvent(new TwitterStreamEvent(TwitterStreamEvent.TWEET_RECEIVED, tweet)); } private function onIoError(event:IOErrorEvent):void { trace(“IO Error.”); } } } ...

2011年8月27日 · Toshimitsu Takahashi

Adobe AIR 2.6 マスターシリーズの連載してます

僭越ながら Adobe Developer Connection にて Adobe AIR 2.6 マスターシリーズの連載をさせていただいております。 第1回 ネイティブ機能の拡張 カーソルやメニューなどデスクトップ系の機能追加をメインに紹介しています。 第2回 iOSやAndroid向けモバイルアプリ開発環境の新機能 iOS 4 のサポート, Android の USB デバッグなど AIR for iOS, Android 開発の新しい機能について紹介しています。 http://www.adobe.com/jp/joc/devnet/air/articles/adobe_air_03.html CameraUI, カメラロール, マイクなどモバイルアプリケーション向けAPIについて紹介しています。 (2011/07/06) http://www.adobe.com/jp/joc/devnet/air/articles/adobe_air_04.html StageWebView、仮想キーボードについて紹介しています。 (2011/08/24) 上記の全4回が公開中です。

2011年6月18日 · Toshimitsu Takahashi

Adobe AIR 2 のデータグラムソケットを使って Wake on LAN でリモート PC を起動するには

Adobe Developer Connection に AIR 2 マスターシリーズの連載が始まりました。 僭越ながら を寄稿いたしました。こちらでは Echo プロトコルクライアント・サーバーを UDP, TCP でそれぞれ実装しているサンプルを載せています。 上記に付随して後から思いついたサンプルの1つということで、Wake on LAN でリモートホストをブートするアプリケーションを作りました。これをスタートアップなどに登録しておけば、自分のメインPCを起動したと同時にホームサーバーなどを起動することができます。 見えないアプリケーション コンソールアプリケーションというべきですが、Window レスな AIR アプリケーションを作るには 新規 Flex プロジェクトの作成ウィザードにおいて、メインアプリケーションに AS ファイルに指定します。 Main.as マジックパケットを送信してアプリケーションを終了するだけです。 package { import com.tilfin.wakeup.MagicPacket; import flash.desktop.NativeApplication; import flash.display.Sprite; /** \* Wakeup On LAN 用のマジックパケットを投げてリモートPCをブートします。 */ public class Main extends Sprite { public function Main() { var packet:MagicPacket = new MagicPacket("FF-0A-E4-8A-74-67"); packet.broadcast("192.168.1.255"); NativeApplication.nativeApplication.exit(); } } } マジックパケット マジックパケットは Wake-on-LAN 用に送信するパケットです。 先頭の6バイトには 0xFF を置きます。さらにターゲットのホストの NIC の MAC アドレスのバイトデータを16回連続で並べたものになります。 ...

2010年9月29日 · Toshimitsu Takahashi

Flash Professional CS5 の Package for iPhone で AIR 2 のネットワーク機能をチェック

Package for iPhone が復活の兆しだということで、AIR 2 の機能が現状どれくらい使えるのか、とりあえずネットワーク系クラスの isSupported プロパティを確認してみました。 残念ながら isSupported はどれも false になってしまった。

2010年9月12日 · Toshimitsu Takahashi

ActionScript 3 で Vector クラスの配列を動的に生成するには

オブジェクトのシリアライズに関する実装をする上で、Vector クラスのリフレクションはできるのか調べてみた。 Vectorクラス名を取得 var classInfo:Object = ObjectUtil.getClassInfo(Vector.); trace(classInfo.name); とすると出力は下記のようになった。 __AS3__.vec::Vector.com.tilfin.sample::Entity こんどは、getDefinitionByName を使って生成してみると var cls:Class = getDefinitionByName("__AS3__.vec::Vector.com.tilfin.sample::Entity") as Class var vector:Vector. = new cls(); もちゃんと上手くいった。ということで色々できそうです。 Vectorユーティリティクラス サンプルとして試しに書いてみた。 package { import flash.utils.getDefinitionByName; import flash.utils.getQualifiedClassName; public class VectorUtil { /** * 指定されたオブジェクトをエレメントとするVectorクラスの配列を返します。 * * @param args 1つ以上のオブジェクトもしくは配列 * @return Vectorインスタンス * / public static function toVector(…args): { var item:; var items:Array; if (args.length == 1) { item = args[0]; if (item is Array) { items = item as Array; } else { items = [ item ]; } } else { items = args as Array; } if (!items || items.length == 0) { throw new ArgumentError(“requires at least one argument.”); } item = items.shift(); var vectorClass:Class = getVectorClass(item); var vector: = new vectorClass(); vector.push(item); for each (var i:* in items) { vector.push(i); } return vector; } /** * 指定されたオブジェクトクラスを格納するVectorクラスオブジェクトを返します。 * * @param value 完全修飾クラス名が必要なオブジェクト * @return Vectorクラスオブジェクト * / public static function getVectorClass(value:):Class { var className:String; if (value is String) { className = value; } else { className = getQualifiedClassName(value); } return getDefinitionByName("__AS3__.vec::Vector.<" + className + “>”) as Class; } } } ...

2010年7月24日 · Toshimitsu Takahashi

ActionScript 3 らしく書いてみたシングルトンのサンプル

Java ライクなシングルトンのサンプルが多いので自分なりに ActionScript らしく書いてみました。 AIR 2 の flash.filesystem.StorageVolumeInfo - Adobe® Flex® 4.1 リファレンスガイド クラスのシングルトン実装が良さそうなのでこれを参考にしてみました。 StorageVolumeInfo は静的な storageVolumeInfo プロパティでシングルトンインスタンスを提供している。 new StorageVolumeInfo() すると、ArgumentError #2012 例外が投げられるようになって-いる。 package { import flash.utils.getQualifiedClassName; /** * シングルトンのサンプル / public class SingletonSample { private static var _instance:SingletonSample = new SingletonSample(); /* * シングルトン提供プロパティ名をクラス名のLowerCamelにする */ public static function get singletonSample():SingletonSample { return _instance; } public function SingletonSample() { if (_instance) { throw new ArgumentError(getQualifiedClassName(this) + " クラスをインスタンス化することはできません。"); } // 初期化処理 _name = “sample name”; } private var _name:String; public function get name():String { return _name; } } } ...

2010年7月22日 · Toshimitsu Takahashi

テレビにTwitterの関連TLをオーバーレイ表示するAIRアプリを作ってみた

部屋にアプリキャストというガジェット機能が使えるブラビアがあるんですが、このガジェットはオーバーレイできないので実際の映像がHD見られなくなってしまいます。そもそも放送法とやらでテレビ上に別の表示を出すのはNGらしいです。まったく不便な話ですね。 で、最近PCでデジタル放送を見たり録画する環境が整ったので、専用PCにHDMIでそのブラビアを繋げてモニターにしてます。F1とか見るときは横目でPCで上げてるTweetDeckを追ってたんですがやっぱり映像に重ねてみたいなと思い、Adobe AIR を使って作ってみました。 できたのが↓です。(F1モナコGPの予選) ちょうど、アナログ→デジタルの過渡期なんで、スーパーが表示されないスペースが左右にあります。そこに乗っけると文字に文字が被って見づらいこともなくなります。 最近覚えた BlendMode = ERASE によるアルファチャネルグラーデーションをかけたりしてます。一応、技術ブログなのでこの部分のソースも書いておきます。下記のコンポーネントの parent には BlendMode.LAYER を設定します。 public class AlphaMask extends UIComponent { public function Overlay() { super(); blendMode = BlendMode.ERASE; } protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); var matrix:Matrix = new Matrix(); matrix.createGradientBox(unscaledWidth, unscaledHeight, Math.PI / 2, 0, 0); var g:Graphics = graphics; g.clear(); g.beginGradientFill(GradientType.LINEAR, [0, 0, 0, 0], [1, 0, 0, 1], [0, 25, 230, 255], matrix); g.drawRect(0, 0, unscaledWidth, unscaledHeight); g.endFill(); } } ...

2010年5月15日 · Toshimitsu Takahashi

Adobe AIR 2.0 airhttpd でサーバ側でロードした swf のフレームショットをHTML5対応ブラウザで簡易アニメ表示させてみた

なんか airhttpd を使って面白いものを作れないかと思い、SWFLoader を使って外部 swf ファイルをロードし、そのフレームのスナップショットをHTTPクライアントに返すサーバーアプリを思いついた。 HTML 5 の Canvas 対応をブラウザであればそれを JavaScript で描画していくことができる。 開発環境とライブラリ Flex 3.5 Adobe AIR 2.0 β2 airhttpd - http://code.google.com/p/airhttpd/ ファイル構成 lib/ airhttpd-0.5.swc src/ docroot/ index.html webapp/ CGIService.as Main.mxml CGI処理 airhttpd の FileService クラスを継承して CGIService クラスを作ります。 package webapp { import com.tilfin.airthttpd.server.HttpRequest; import com.tilfin.airthttpd.server.HttpResponse; import com.tilfin.airthttpd.services.FileService; import flash.filesystem.File; public class CGIService extends FileService { private var _snapShotFunc:Function; public function CGIService(snapShotFunc:Function, docroot:File) { super(docroot); _snapShotFunc = snapShotFunc; } override public function doService(request:HttpRequest, response:HttpResponse):void { if (request.path == “/action”) { response.contentType = “image/png”; response.body = _snapShotFunc(); return; } super.doService(request, response); } } } ...

2010年2月21日 · Toshimitsu Takahashi

Adobe AIR 2.0 のローカルサーバー機能で HTTP サーバを実装してみた

Adobe AIR | Adobe AIR 3 | Deploy applications Adobe - Adobe AIR 2.0 beta サンプルアプリケーション AIR 2.0 から ServerSocket が提供されて、ローカルサーバを実装することが可能になりました。 まだパブリックベータですがクライアント一辺倒だった AIR の大きな変更なので注目です。 試しに HTTP サーバを実装してみました。拙速ですけど Google Code Hosting で公開しています。 ActionScriptで簡易なサーバサイドプログラミングというのも特殊な要件に使えるかもしれません。 airhttpd - Httpd for Adobe AIR 2.0 SDK http://code.google.com/p/airhttpd/ ServerSocket の不具合 サーバーソケットを一旦bindしたポートはソケットを閉じても解放してくれないようです。まあ、ベータ版なので。 FXUG 勉強会 (2009/12/11) で話します airhttpd の実装を通してサーバーソケットについて紹介します。 B-Wiki - Flex勉強会第93回@東京参加受付 - Flex User Group

2009年11月18日 · Toshimitsu Takahashi

Ajax Web アプリケーションを Adobe AIR に移植しようとして気づいたこと

Web サービス(Ajax アプリケーション)を Adobe AIR に移植しようとして気づいたことをメモしておく。 ruby-MySQL のサーバーサイド(ビジネスロジックはなくストレージ機能)は AIR の SQLite データベースで実現する。 気づいたことを徒然なるままに。 AIR は Webkit ベースなので、IE, Firefox, Safari, Opera, Chrome × Win, Mac ブラウザで動いていた Ajax が余裕でそのまま動くと思っていたが、『jQuery のプラグインが動かなかったり、 eval が上手く使えなかったり、:hover が適用されない。』と手痛いことが多い。 Ajax AIR はデバッグがきつい。Firebug が使えないので Trace 地獄になる。Flex (Builder) で開発させたいのが本音だろうなぁ。 ローカルストレージが SQLite なのも微妙。これは Gears でも思ったがローカルストレージを RDB にする意味がわからない。REST や webDAV みたいにあくまでも ターゲット URI を切り替えて使えるような I/F の方が好ましいと思う。 Flex 版も含めての話だが、正式な証明書ではないとしてもインストール時に制作者を表示してほしい。UNKNOWN になってしまうのは。。。 ということでインターフェイスの切り替えで済むような移植を考えていましたが断念しました。 Flex 同様、AIR も バージョン 2 あたりから期待した方がいいかもしれない。 ※蛇足だが Aptana Studio をアップデートしたら AIR の出力がエラーで不能になってしまった。

2009年2月15日 · Toshimitsu Takahashi