最近、色々な仕組みと連携するために、JavaScriptを中心にしてWebSocketやSocketIOであれこれ試しています。
当然、FLASHでも連携したいと思い、AS3WebSocketを利用してHeroku WebSocketとAIR for Androidを連携したメモです。
参考記事
Socketと連携するFLASHの記事はもうだいぶ昔の記事が多いものの、今までサーバー側の仕組みを作るのに苦労していたところがHerokuで作れるようになってきました(個人的に)
この「フロントエンド側・バックエンド側両面で作りやすそう」という視点を軸に、改めて探しまして以下記事に出会いました。
AS3 と Python を WebSocket で接続するついでに mongodb でほげほげするメモ | デブ ハゲ
まさにこれでして!
サーバー側 今回はシンプルに * meinheld * flask * mongoengine という構成。
をHeroku NodeJS WebSocketに置き換えればいいなと。
まずHeroku WebSocketサーバーを立てる
ではHerokuでWebSocketサーバーを立てます。
ちゃんと本家にサンプルがある
Herokuにサンプルあります。
Using WebSockets on Heroku with Node.js | Heroku Dev Center
デプロイまで進む
途中、丁寧にソースコードが説明されていますが飛ばして、まずデプロイまでやってしまいます。
Option 1. Clone sample app を進める
git clone https://github.com/heroku-examples/node-ws-test.git mkdir node-ws-test cd node-ws-test
DeployのCreate the Heroku app to deploy to: 以降をすすめる。
heroku create git push heroku master
今回は hoge-hoge-ws-as3-test.herokuapp.com という例で進めます。
サーバーにアクセス
サーバーに
http://hoge-hoge-ws-as3-test.herokuapp.com/
アクセスすると、
と表示されます。WEB画面がメッセージを受け取っているだけです。
WebSocket自体は、タイムスタンプ 2015-05-28T05:41:24.494Z という文言を吐き続けています。
AIR側の実装
続いて、AIR側の実装です。ほぼ参考記事のとおりですが、もう少しアプリ上で状態が見えるように、テキストを吐き出すようにします。
ライブラリ持ってくる
からライブラリを持ってきて、以下のように書いてみましょう。
実際のコード
package { import flash.display.Sprite; import flash.text.TextField; import com.worlize.websocket.WebSocket; import com.worlize.websocket.WebSocketError; import com.worlize.websocket.WebSocketErrorEvent; import com.worlize.websocket.WebSocketEvent; import com.worlize.websocket.WebSocketMessage; import flash.display.Sprite; import flash.events.IOErrorEvent; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; [SWF(width="480",height="820",frameRate="60",backgroundColor="#000000")] public class WebSocketMain extends Sprite { public var txtMessage:TextField; public var txtStatus:TextField; private var _ws:WebSocket; public function WebSocketMain() { // 結果の文言の出力部部分 ////////////////////////////////////// var ftStatus:TextFormat = new TextFormat(); ftStatus.font = "Arial"; ftStatus.size = 24; ftStatus.color = 0xffffff; txtStatus = new TextField(); txtStatus.multiline = true; txtStatus.wordWrap = true; txtStatus.defaultTextFormat = ftStatus; txtStatus.x = 30; txtStatus.y = 60; txtStatus.width = 450; txtStatus.text = "--"; txtStatus.autoSize = TextFieldAutoSize.LEFT; addChild(txtStatus); var ftMessage:TextFormat = new TextFormat(); ftMessage.font = "Arial"; ftMessage.size = 36; ftMessage.color = 0xffffff; txtMessage = new TextField(); txtMessage.defaultTextFormat = ftMessage; txtMessage.text = "--"; txtMessage.autoSize = TextFieldAutoSize.LEFT; addChild(txtMessage); // WebSocketの実際のコードは以下から //////////////////////////// _ws = new WebSocket("ws://hoge-hoge-ws-as3-test.herokuapp.com/","*"); _ws.addEventListener( WebSocketEvent.OPEN, _connectedHandler); _ws.addEventListener( WebSocketEvent.CLOSED, _closeHandler ); _ws.addEventListener( WebSocketEvent.MESSAGE, _messageHandler ); _ws.addEventListener( WebSocketErrorEvent.CONNECTION_FAIL, _errorHandler ); _ws.addEventListener( IOErrorEvent.IO_ERROR, _ioErrorHandler ); _ws.connect(); } /** * 接続完了 * @param event WebSocketEvent */ private function _connectedHandler(event:WebSocketEvent):void { trace("connected!", event ); txtStatus.text = "connected! " + event.toString(); var text:String = String(new Date().time) + "hoge" _ws.sendUTF(text); } /** * 接続終了 * @param event WebSocketEvent */ private function _closeHandler(event:WebSocketEvent):void { trace("closed...", event); txtStatus.text = "closed... " + event.toString(); } /** * メッセージ受信 * * @param event WebSocketEvent */ private function _messageHandler( event:WebSocketEvent ):void { trace("msg!"); trace("event.message.utf8Data"); // 文言の出力 ここがHeroku WebSocketの文言と同様になる // つまりタイムスタンプ txtMessage.text = event.message.utf8Data; txtStatus.text = "msg! [event.message.utf8Data] " + event.toString(); } /** * WebSocketError * * @param event WebSocketErrorEvent */ private function _errorHandler( event:WebSocketErrorEvent ):void { trace("ws error...", event.text ); txtStatus.text = "ws error..." + event.text; } /** * IOError * * @param event IOErrorEvent */ private function _ioErrorHandler( event:IOErrorEvent ):void { trace("io error...", event.text ); txtStatus.text = "io error..." + event.text; } } }
書き換える部分
http://hoge-hoge-ws-as3-test.herokuapp.com/
にサーバが立った場合ですが、接続先を変えればすぐ使えます。
ws://hoge-hoge-ws-as3-test.herokuapp.com/
以下のようにコードを書き換えています。
_ws = new WebSocket("ws://hoge-hoge-ws-as3-test.herokuapp.com/","*");
動作確認
こちらを敢えてだいぶ前のSDK flex4.13.0 air15.0.0.302 でAPKを出力しAndroidで読み込んだところ、無事動きました。
アプリとして動いているもののキャプチャです。
上部テキストが実際のメッセージの受信部分。下部テキストはいろいろな状態を出力してます。
Androidのパーミッション
パーミッションは特に難しいことはなくINTERNETを解放しておきましょう。
<uses-permission android:name="android.permission.INTERNET"/>
おわりに
テンション上がる!
Socket系は最近はかなり実装しやすくなっている印象です。
これでリアルタイムに色々と繋げられつつ、サポートしている範囲も広くなってきているので、ネタ同士の優れた接着剤になっていきそうですね!
それでは、よき Adobe AIR + Heroku + NodeJS + WebSocket Lifeを!(長いw)