swfアプリからLingr APIのroom.observeを実行する
スマートじゃないとは思いつつ、実装そのものは難しくもなさそうなので、JavaScript経由でのリクエストを実際に試してみました。
- swfからJavaScript経由でroom.observeのリクエスト(クロスドメインの制限によりswfからは直接GETできないため)
- JSONPのコールバック関数経由でswfで結果を取得
という2点さえなんとかなれば、その他の機能はLingrサーバへのリクエストを仲介できるCGIに対してswfから直接POSTすればいいわけです。ということで、以下room.observeに絞って実験。
room.observeのリクエストに必要なパラメータは、
- session(セッションID)
- ticket(チケット)
- counter(イベントカウンタ)
の3つ。いずれも最初に取得するのはPOSTでのリクエストの際になるので、swf側ですべて管理してしまった方がよさそう。そこで、JavaScript側はswfから渡されたパラメータをそのままLingr APIにパスするものとして実装してみます。
<script language="JavaScript" src="swfobject.js"></script> <script language="JavaScript" src="odj.js"></script> <script language="JavaScript"> function thisMovie(movieName) { if (navigator.appName.indexOf("Microsoft") != -1) { return window[movieName]; } else { return document[movieName]; } } function doObserve(sid, ticket, cnt) { var url = 'http://www.lingr.com/api/room/observe/' + '?format=json&session=' + sid + '&ticket=' + ticket + '&counter=' + cnt; var oOdj = new onDemandJavaScript(); oOdj.request(url, getObserveResult, 'callback'); } function getObserveResult(r) { alert(r.messages[0].text); thisMovie('roomObserveTestSWF').flexCallBack(r.messages[0].text, r.counter); } </script> <div id="flashcontent"></div> <script language="JavaScript"> var so = new SWFObject("rotest.swf", "roomObserveTestSWF", "500", "300", "7", "#336699"); so.addParam('allowScriptAccess', 'always'); so.write("flashcontent"); </script>
今回、JSONPの扱いにはkyo氏のodj.js(onDemandJavaScriptクラス)を利用させて頂きました。
ActionScript側も単純で、initializeのタイミングでExternalInterface.addCallbackでjs側から呼び出せるコールバック関数を設定し、ExternalInterface.callでjs側の関数を実行するだけ。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="initApp()"> <mx:Script> <![CDATA[ import mx.controls.*; import flash.external.*; public function initApp():void { ExternalInterface.addCallback("flexCallBack", getObserveResult); } public function getObserveResult(r:String, c:String):void { Alert.show(r); counter.text = c; } public function startObserve():void { ExternalInterface.call("doObserve", session.text, ticket.text, counter.text); } ]]> </mx:Script> <mx:Panel title="Lingr API Test" width="100%" height="100%" id="main_panel" paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10"> <mx:Form width="100%" height="100%"> <mx:FormHeading label="Enter parameters into the form below"/> <mx:FormItem label="session"> <mx:TextInput id="session" width="200"/> </mx:FormItem> <mx:FormItem label="ticket"> <mx:TextInput id="ticket" width="200"/> </mx:FormItem> <mx:FormItem label="counter"> <mx:TextInput id="counter" width="200"/> </mx:FormItem> </mx:Form> <mx:Button label="Start Observe Room" click="startObserve()" /> </mx:Panel> </mx:Application>
本当はExternalInterface.addCallbackの前にjs側の準備が整ったかどうかチェックするべきですが、面倒なので今回はばっさり省略。後はmxmlcでswfにコンパイルしてHTMLを開き、フォームに別の手段で確保した3引数を入れてボタンを押せば発言が一個ずつ取れます。
思ったよりシンプルなソースで実現できたものの、ローカル環境では動作しなくて随分詰まりました。allowScriptAccessはちゃんとalwaysにしてるし、何でだろう‥‥