マップアプリのソース公開
2006.03.15
昨日のエントリーで書いた「シアトル近郊の交通情報表示アプリ」、コメント欄で励まされたこともあり、全ソースを公開することにした。ただし、会社のサーバーで公式に遊ぶことになったので、発表の際にはまず英語で解説を書かねばならなくなってしまった。とりあえず、これが解説ページである。
たいしたことが書いてあるわけではないので、全部を日本語に訳すこともないとは思うが、肝となる How it works (どうやって動いているか)だけは日本語での解説が必要そうだ。そこだけ抜き出して意訳すると、
このアプリは、三つのUJMLファイル(クライアント側でマップを表示して、ユーザーとのやり取りをするもの)と、二つのPHPファイル(サーバー側で元画像を細かくスライスしてキャッシュするもの)から出来ている。
Main.ujbc(Main.ujmlをコンパイルしたもの) が最初に UIEPlayer(UIEngineのクライアント側の描画エンジン)がサーバーからロードするモジュール。それが初期化の後に、 Update.ujbc をロードするのだが、直接ではなく waupdate.php というサーバー側のスクリプトに対してリクエストするところがミソ。
waupdate.phpは、cache というフォルダー内にスライスしたイメージをキャッシュしており、クライアントからリクエストが来ると、一番左上のスライスのタイムスタンプを調べ、3分以上前のものであれば再度イメージを元のサーバーに取得し、それを元にキャッシュをアップデートする。実際のキャッシュのロジックは全てImageSlicer.phpというファイルにImageSlicerというクラスの形でまとめてある。
その後waupdate.phpは、キャッシュの準備が整ったことを知らせる意味で、Update.ujbcを返す。ロードされたUpdate.ujbcは、Main.ujbcのonImageReady()関数を呼び、自分がロードされたこと、つなわちキャッシュ上の画像ファイルが十分に新しいものであることを知らせる。
onImageReady()を呼ばれたMain.ujbcは、イメージビューアーであるMapViewer.ujbcをロードし、その語はMapViewer.ujbcが必要に応じてスライスされた画像をサーバーからロードして表示する。それに加えて、ユーザーからの方向キーの入力を受けて、上下左右にスムーズスクロールをする。
となる。大して難しいことはしていないのだが、一番工夫をこらしたのは、画像をスライスするロジックに複数のスレッドが同時に入って来ないようにする仕組み。ファイルロックも含めて、色々なものを書いてみたのだが、結局のところ、最初にキャッシュされた画像が古いことに気がついたスレッドが間髪をおかずにキャッシュされた画像ファイルのタイムスタンプを新しいものにしてしまう、というものすごくシンプルなロジックが一番適していることに気がついた。こうしておくと、後から実行されたスレッドはキャッシュ画像が新しいものと解釈してスルーしてしまうので、ファイルロックを使った時のようなスレッド渋滞の起こる心配がない。唯一の問題は、後から来た方のリクエストを発行したほうのデバイスに少し古い画像が表示される可能性があることだが、サーバーへのアクセスが多いときは最大でも6分前の画像になるだけだし、サーバーへのアクセスが少ない時には、めったにこの状況にはならないので、これで十分なはずである。
ちなみに、ソースコードへのリンクは英文のページにも張ってあるが、ここにも張っておく(ダウンロード)。ちなみに、このアプリをデバッグしたりビルドしたりするのに必要なSDKは、http://developer.uievolution.com/ からダウンロードできる。SDKは1.5とベータ版が出たばかりの2.0があるが、このサンプルに限って言えば、1.5の機能しか使っていないので、どちらのSDKでも走るはずだ。なお、デバッガー上のこのアプリを走らせる場合、RETAILモードのままで実行するとサーバーにアクセスしてくれないので、DEBUGモードで走らせる必要があるので要注意。
【追記】 DoCoMo版のUIEPlayerがPHPから返されたUJBCファイルをUJBCとして認識してくれないというバグを発見(大勢の人の時間を無駄にする前に、見つけてよかった^^;)。原因は判明したので、今は担当者の速やかな対応を待つのみ。早くしてくれ~。
UIEのSDKのダウンロードページがちょっとわかりにくかったです。
http://developer.uievolution.com/sdk/download_1_5.html
どこでDLするのかなとちょっと迷ったらQuicklinksの中にあったので、そこは外部リンクだろうからないだろうと、かん違いして戻ったりして探しまくりました。
僕の感覚では、ページタイトルのところ、もしくは本文内にダウンロードリンクがあったほうが良いのではないかなと思いました。
Posted by: & | 2006.03.15 at 16:39
申し訳ありません。確かに仰るとおり、分かりにくいですね。改善するように指示をしておきます。
Posted by: Satoshi | 2006.03.15 at 17:21
むむ、これまで個人的にUIEのSDKを試してましたが、さすがに単なるプロデューサーレベルでは扱えなくなってきました(笑)
誰か技術者に遊ばせてみるかな…
Posted by: kuga | 2006.03.15 at 23:54
ダウンロードしたzipファイルに含まれる
build
server
フォルダの中のものをサーバーの同じディレクトリにアップロードすることと、UIEPlayerのアプレットバージョン1.5もアップロードする(SDK内に含まれる)こと、それと、アップロードしたディレクトリにcacheなるディレクトリを作成し、適宜パーミッションを設定する必要があるといった感じでしょうか?
Posted by: UIEngineだ | 2006.03.16 at 14:47
UIEngineださん、その通りです。その部分を訳し忘れていました。
まず動かすにはserverとbuildフォルダー内にあるファイルを全て同一のフォルダーに入れ、cache という名のサブフォルダーを書き込み可能にして作っておけばOKです。
client内にあるUJMLファイルを変更した場合には、自分でSDKを使ってコンパイルし、それをbuildフォルダーからコピーしたファイルの代わりにサーバーにおいてあげます。
Posted by: Satoshi | 2006.03.16 at 15:39
こんにちは。もうこの投稿は3ヶ月の前のものなんですね。時が経つのは早いものです。
今日偶然このアプリを私の携帯電話Docomo902iで表示させたのですが、画像が2006年4月16日のものです。どこかに不具合があるようです。
ソースコードを見ずに憶測で行きますが、クライアント側のキャッシュを廃棄せずそのまま使っているなんてことは無いですか?サーバーに取りに行く通信をしていないように見えるので。
Posted by: UIEngineだ | 2006.06.20 at 08:04
クライアント側のキャッシュの破棄がうまく働いていないようですね。_discard("/*")というラインがその役目を果たすはずです。
Posted by: satoshi | 2006.06.20 at 14:01
ということは、アーリーリリース版のDojaUIEPlayerのバグですね。最新版では問題無いはずです。うっかり古いUIEPlayerで動かしてました。とほほ。お騒がせしました。
この投稿は現在から考えると「ずいぶん昔」になりますが、「ずいぶん昔」の投稿に出した自分のコメントの場所を記憶するのは難しいものです。忘れてしまったり、返事の確認に戻ってくるときに迷子になったりします。未来のブログでは良い方法が現れることを期待してます。
Posted by: UIEngineだ | 2006.06.27 at 02:21