Flashコンテンツとローカルアプリケーションの連携を考える

今日は Flash コンテンツとローカルアプリケーションの連携を色々と試行錯誤してみた。備忘録代わりにメモしておく。

Flash Player8(ActionScript3.0)からは ExternalInterfaceクラスというものが使えて、fscommand() なんかよりも柔軟に外部と連携できるらしい。

External Interface – Macromedia Flex 2.0 MXML and ActionScript Language Reference

このドキュメントを読む限りでは、JavaScript と Flash 間で関数呼び出しが可能。またそれだけでなく、Flash Control Object を使えばローカルで動作する C# アプリケーションからブラウザ上(Flash Player Plugin)で動作する Flash コンテンツの関数を呼び出すことが出来るらしい。でも僕が持っているオーサリングツールは Flash MX 2004 のみなので使えず。

そこで、少し斜め下方向からのアプローチで攻めてみることに。

まず Flash にはローカルに情報を保存する方法として、「SharedObject」というものがある。これを使えばユーザ毎のローカルコンピュータにプレファレンスなどを保存しておくことができる。

SharedObjectがどこにどうやって保存されているかというと、実体はローカルファイルで要するに Cookie みたいなもの。保存場所は WindowsXP なら、例えば

C:\Documents and Settings\< username>\ Application Data\Macromedia\Flash Player\#SharedObjects\YGVVQUWG\ flickr.com\slideShow\slideShow.swf

のよう感じで #SharedObject の下に、衝突を避けるためドメイン名などのサブフォルダ階層を作って格納されているようだ。ローカルの Flash Player で再生した場合には上の例の「flickr.com」のところが「localhost」になっている。

この中に、「*.sol」というファイルが出来ているのだが、これが SharedObject の実体らしい。中身をエディタで覗いてみるとどうやら独自バイナリ形式っぽい。色々検索してみると既に解析されているわけで、Sourceforge.net にある SolVE というプロジェクトに解析資料を発見できた。

cvs: solve/SolVE/etc/SharedObjectFile.html

これを参考にしながら C++ で .sol ファイルをホゲホゲするアプリをでっちあげ、Flash 側で SharedObject から値を取得してやると一応アプリと連携できる。ただフォーマットも変更されるかもしれないし、.sol ファイルのパスも Flash コンテンツを置くドメインによって変わってしまう。だからアプリ側で保存場所を特定できるかどうかもちと微妙なのでこの方法は断念。

他に Flash から外部からデータを取得する方法として、

  • LocalConnection (MX~)
  • loadVariable (5~)
  • LoadVars (MX~)
  • XMLSocket (5~)

などがあり、この中で一番よさそうだったのが LocalConnection。通常二つの(同じPC上で再生する)SWF 間で通信する場合にはこれを使うらしい。異なるブラウザ間でも通信できるようなので、この通信をうまくアプリでエミュレートできればもしや、と考える。

それでどんなプロトコルで通信しているのかググって見たら、やはりネット上に解析資料発見。

OSFlash : The LocalConnection explained

で、読んでみると次のような文言が。

The Win32 implementation

Notes:

  • the LocalConnection is very OS-dependent but it should be similar for the Linux and Mac systems. Feel free to describe other implementations.
  • these observations and sample codes may not be a very reliable source for you own developments!
  • apparently these information & code samples only work with Flash 6 SWFs.

気にせず読み進めてみると、要するに Win32 では共有メモリとミューテックスを使ってプロセス間通信しているとのこと。プロトコルは独自バイナリ。まあ、そんなところだろうという気はしていた。

これをうまく使えれば確かにパフォーマンスは確保できそうだけれども、実装は時間がかかるわりに動作保障はできなそうなので却下。

残りの中から、とりあえず XML である必要はないので、loadVariable を使ってみることに。

Java でコードを書いてごく簡単な Web サーバをでっち上げ、ポート 999 で Listen。Flash 側から「loadVariables(“http://localhost:999/”, target_mc);」とかやってみた。で、Java のサーバ側は GET されたらとにかく独自のデータをレスポンスするようにしてみる。

これで Flash からデータが読めることを確認。

要するにネイティブアプリでも同じように実装すれば連携は可能だろう。ただ問題は、常に Flash 側からポーリングする必要がある。ただしこれでも SWF を外のサーバに置いたときはうまくいかない。

これは既に分かっていたことで、Flash7 からセキュリティ機構が強化され異ドメイン間でアクセスするためには仕掛けが必要になっていて、通常はロードされる側のサーバ上に「crossdomain.xml」をおき、アクセスコントロールする。

とりあえず、Java 側で「GET /crosdomain.xml」された場合に、「allow-access-from domain=”*”」な XML を返すようにしたらうまく動いた。(セキュリティー的にはよくないかもしれませんが、まあ実験なので)

で、最後に IE で動かしてみたらうまくいかない。Flash 側は onEnterFrame で loadVariable するようにしてポーリングしているのだが、サーバに来るリクエストを見ると 1~3 回程度でとまってしまう。どうしてだろう。

Similar Posts: