LocalConnectionとは?
今回は、flash.net.LocalConnection
クラスについての解説を行う。
LocalConnection
クラスとは、AIR以前からも存在した、Flex/Flashアプリケーション同士で通信を行うための仕組みである。同じマシン上で動作するSWFアプリケーション同士で行うことのできる、プロセス間通信だと思ってよい。APIが非常にシンプルな割には、ActionScriptのオブジェクトをそのまま渡す事ができるなど、かなり強力な仕組みだ。
AIRではLocalConnection
はさらにパワーアップしており、AIRアプリケーション同士で通信をできるのみならず、ブラウザ上で動作しているFlexアプリケーションとも通信が可能だ。
では、まずはLocalConnection
の使用法を見ていこう。
LocalConnectionの使用法
LocalConnectionは単純に言えば、文字列で名前を指定した接続を介して、クライアントとサーバが通信を行う仕組みだ。なので、送信側のコードと受信側のコードに分けて見ていくと分かりやすい。
ということで、データを送信する側のコードを先に見ていこう。 送信側のコードは、簡単に書くと次のようになる。
// (1) LocalConnectionのインスタンス作成
var con:LocalConnection = new LocalConnection();
// (2) 送信結果をハンドリングするためのリスナを追加
con.addEventListener(StatusEvent.STATUS,
function(event:StatusEvent):void {
switch (event.level) {
// 正常に送信完了
case "status":
break;
// エラー
case "error":
break;
// 警告
case "warning":
break;
}
});
// (3) データ送信
con.send("接続名", "受信側のメソッド名", 引数...);
(1) LocalConnection
のインスタンスを作成している。引数なしのコンストラクタを呼び出すだけだ。
(2) 送信がエラー終了した時のために、イベントリスナを追加している。送信結果は、リスナメソッドの引数に渡されるflash.events.StatusEvent
クラスのlevel
プロパティを参照すれば良い。
(3) データの送信には、LocalConnection
クラスのsend
メソッドを使用する。send
メソッドの第一引数に渡す「接続名」については後述。第二引数は、受信側でデータを受け取るために用意するメソッドの名前。第三引数以降がデータで、任意のオブジェクトを複数渡すことができる。
では、send()メソッドの第一引数に渡す「接続名」について解説する。「接続名」とは、通信を行うアプリケーション同士で共有する文字列だ(例えば"myConnection"など)。さらに送信する側としては、受信側を特定するための情報を接続名の前に付与する必要がある。 これは以下のルールに則っている。
受信側がFlexアプリケーションの場合は、そのSWFの配布元となったドメイン名を接続名の前に付与する。つまり、接続名は「www.example.com:myConnection」などとなる。間の「:」は、ドメイン名と接続名の間の区切り文字だ。
受信側がAIRアプリケーションの場合は、「app#アプリケーションID」という文字列を接続名の前に付与する。アプリケーションIDとは、アプリケーションディスクリプタファイルのルート要素
application
の、appId
属性で指定する任意の文字列だ(アプリケーションディスクリプタファイルについては、連載第3回にて解説を行っている)。例えば、アプリケーションIDが「jp.co.mycom.journal.App」だった場合、接続名は「app#jp.co.mycom.journal.App:myConnection」などとなる。
では次に、受信側のコードを見ていこう。LocalConnection
経由でデータを受信する側のコードは以下のようなものになる。
// LocalConnectionのインスタンス作成
var con:LocalConnection = new LocalConnection();
// (1) 接続を許可するドメイン/アプリケーションIDを指定
con.allowDomain("jp.co.mycom.journal.App");
// (2) データの受信に失敗したイベントのリスナを登録
con.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
// (3) セキュリティ上許可していないドメイン/アプリから接続されたイベントのリスナを登録
con.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
// (4) データを受け取るメソッドを持つインスタンスを、
// `client`プロパティに指定
con.client = this;
// (5) 接続名を指定してconnectメソッドを呼び出す。
con.connect("接続名");
...
// (6) データ受信用のメソッド
function onReceived(msg:String):void {
...
}
ポイントを解説していこう。
(1) LocalConnection
のインスタンスを作成した後、(4)でconnect()
メソッドを呼び出す前に、allowDomain()
メソッドを使用して接続を許可するクライアントのドメイン、もしくはアプリケーションIDを指定する必要がある。受信側がFlexアプリケーションの場合は必須。AIRアプリケーションの接続では、これを行う必要はない。「*」(アスタリスク)を使用すると、接続名さえ正しければあらゆる接続を受け入れる。
(2) クライアントが送ってきたデータを受信するのに失敗した(受信用のハンドラメソッドが存在しない、など)場合に発生するエラーを処理するためのリスナメソッドを登録している。
(3) セキュリティ上許可していないドメイン/アプリケーションから接続された際に発生するエラーを処理するためのリスナメソッドを登録している。
(4) 送信されたデータを受け取るメソッド(そのメソッド名は送信側のsend()
メソッドで指定される)を持つインスタンスを、LocalConnection
のclient
プロパティに代入する。データが到着した際、そのメソッドがランタイムによって呼び出される。
(5) 接続名を指定してconnect()
メソッドを呼び出す。受信側は、送信側と違って接続名だけを使用する。
(6) 送信側が送ったデータを引数に取るメソッドを用意しておく。メソッド引数の数と型は、送信側がsend()
メソッドを呼び出す時に指定した引数と一致する必要がある。
以上で、LocalConnection
を使用したコードの説明は終わりだ。では、今回のサンプルアプリケーションの解説に入ろう。
サンプルアプリケーションの解説
今回用意したサンプルは、データの送信側と受信側に分かれている。
送信側のテキストエリアに文字を入力すると、ローカルコネクション経由で文字列が送られ、受信側のテキストエリアに反映される。
また、受信側のコードを変えることなくFlexアプリケーションにしたとしても、送信側の接続文字列を変えるだけで同じように動作する。
まず、送信側のソースコードは以下の通り。
リスト: 送信側のAIRアプリケーション「AIRLocalConnectionExample.mxml」
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
import flash.net.LocalConnection;
// LocalConnection.send()メソッドに渡す接続名
// 受信側がローカルホスト上で動作するFlexアプリケーションの場合
private static const CONNECTION_NAME:String = "localhost:myConnection";
// 受信側がAIRアプリケーションの場合
//private static const CONNECTION_NAME:String = "app#AIRLocalConnectionReceiver:myConnection";
// ローカルコネクション
private var con:LocalConnection = new LocalConnection();
// creationCompleteで呼び出される初期化メソッド
private function init():void {
// 送信結果をハンドリングするためのリスナを追加
con.addEventListener(StatusEvent.STATUS, onSend);
}
// テキストエリアの状態が変更されたら呼び出されるメソッド
private function onTextChanged():void {
con.send(CONNECTION_NAME, "onTextReceived", textInput.text);
}
// send()メソッドの結果を処理するリスナメソッド
private function onSend(event:StatusEvent):void {
if (event.level == "error") {
trace("Send Error");
}
}
]]>
</mx:Script>
<mx:TextArea id="textInput" x="10" y="28" width="453" height="318" change="onTextChanged()"/>
<mx:Label x="10" y="2" text="ローカルコネクションのサンプル"/>
</mx:WindowedApplication>
次に示すのが受信側のコードだ。
リスト: 受信側のFlexアプリケーション「AIRLocalConnectionReceiver.mxml」
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
import flash.net.LocalConnection;
// ローカルコネクション
private var con:LocalConnection = new LocalConnection();
// creationCompleteで呼び出される初期化メソッド
private function init():void {
// 接続を許可するドメイン/アプリケーションIDを指定
con.allowDomain("*");
// データの受信に失敗したイベントのリスナを登録
con.addEventListener(AsyncErrorEvent.ASYNC_ERROR, function(event:AsyncErrorEvent):void {
textOutput.text += (event.text + "\n");
});
// セキュリティ上許可していないドメイン/アプリから接続されたイベントのリスナを登録
con.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(event:SecurityErrorEvent):void {
textOutput.text += (event.text + "\n");
});
try {
// データを受け取るメソッドを持つインスタンスを、clientプロパティに指定
con.client = this;
// 接続名を指定してconnectメソッドを呼び出す
con.connect("myConnection");
} catch (e:ArgumentError) {
trace("接続名が既に使用されています。");
}
}
// データ受信用のメソッド
public function onTextReceived(msg:String):void {
textOutput.text = msg;
}
]]>
</mx:Script>
<mx:TextArea id="textOutput" x="10" y="28" width="453" height="318" editable="false"/>
<mx:Label x="10" y="2" text="LocalConnection経由で受けとったテキストが下に表示されます。"/>
</mx:Application>
今回は、ローカルコネクションに関する説明は既に詳しく行ったため、ソースコード中のコメントをもって解説と代えさせていただきたい。