GOL @Wiki

地図アプリを作りたい

最終更新:

divadiva

- view
管理者のみ編集可


Google Maps APIなどを利用した地図アプリ、位置情報、写真、などを組み合わせたアプリケーションの作り方を勉強し始めました。サーバサイド、クライアントサイド、それぞれの製作時に気をつける点などをメモします。内容はさまざまですが、そのうちわかりやすくまとめます。。

  1. サーバサイド(JEE5)
    1. JAXBを使ってKMLのJavaクラスを生成する
  2. クライアントサイド(Flex, Flash, AIR)
    1. Google Maps API for Flashを使う
    2. Picasa Web Albums Data APIを使う

サーバサイド(JEE5)

JAXBを使ってKMLのJavaクラスを生成する

KMLドキュメントを処理結果として返すWebサービスをNetBeans6.1で作っていたところ、KML要素を返すオペレーションを記述したWSDLから、JAXBを使ってJavaクラスを生成するところで下記のようなエラーが発生しました(エラーメッセージは一部加工してあります)。

[ERROR] Two declarations cause a collision in the ObjectFactory class.
 line 1058 of file:ogckml22.xsd
[ERROR] (Related to above error) This is the other declaration.   
 line 255 of file:ogckml22.xsd
[ERROR] Two declarations cause a collision in the ObjectFactory class.
 line 350 of file:ogckml22.xsd
[ERROR] (Related to above error) This is the other declaration.   
 line 261 of file:ogckml22.xsd

ネットで調べてみると、これはよくあるエラーらしく、Googleでもバグとして扱われていました。エラー内容はXMLスキーマに同じ名前の要素があるよ!ということなのですが、実際のXMLスキーマでは、「scale」「Scale」あるいは「snippet」「Snippet」のように、文字列の先頭が大文字・小文字で分けてあります。JAXBはそれらを同じものとして扱ってしまうようです。

これを解決するためには2つの方法があります。1つはXMLスキーマを変えてしまう、というものですが、XMLスキーマがそもそも他人のものである場合は、これは無理です。そこでもう一つの方法、JAXBをカスタマイズする、という方法をとります。どの要素からどういう名前のクラスを生成するか、指定してしまう方法です。

実際の方法ですが、下記のようなJAXBバインディングファイルを記述して、wsimportツール(XMlスキーマファイルからJavaクラスを生成してくれるツール)に渡してやればOKです。

 <bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1" xmlns:kml="http://www.opengis.net/kml/2.2">
     <bindings scd="/element::kml:scale">
         <class name="LCScale"/>
     </bindings>
     <bindings scd="/element::kml:Scale">
         <class name="UCScale"/>
     </bindings>
     <bindings scd="/element::kml:snippet">
         <class name="LCSnippet"/>
     </bindings>
     <bindings scd="/element::kml:Snippet">
         <class name="UCSnippet"/>
     </bindings>
 </bindings>

wsimportコマンドを直接たたく場合は、-b <binding file name> オプションを指定します。私の場合はNetBeansですので、Antファイルの該当箇所をいぢればよいです。

 jaxws-build.xml
 <wsimport binding="<binding file name>" ...

ちなみに生成されたファイルのコンパイル時に無検査変換に対する警告が発生したりします。@SuppressWarnings("unchecked")を生成されたクラスで使用すればこの警告は消えるはずです。
が、NetBeansの場合、プロジェクトのアンデプロイ&デプロイ処理をする際にwsimportが再度走るので結局修正したソースは蒸発してしまい無意味。まぁ警告だけなので、とりあえず無視しよう。。

~antのxjcタスクでJAXBのコードを生成する~
NetBeansで、KML2.2のスキーマファイルを丸ごとJAXBコード生成処理にかけたところ、上記に加えてさらに要素名のコリジョンが発生。具体的には、ogckml22.xsd の name 要素が、ogckml22.xsd がインポートしている atom-author-link.xsd 内の name 要素と重なっているところです。
なので、バインディングファイルに下記をさらに追記しました。
<bindings scd="/element::kml:name">
    <class name="Kml22Name"/>
</bindings>
そしてJAXBクラスを生成するantタスクがバインディングファイルを呼び出すように修正。xjc要素に extension="true" 属性を付加し、binding 要素を追記します。
<xjc package="<パッケージ名> destdir="build/generated/jaxbCache/KML22" catalog="catalog.xml" extension="true">
  ・・・省略・・・
    <binding dir="<バインディングファイルのディレクトリ名>">
        <filename name="<バインディングファイル名>" />
    </binding>
  ・・・省略・・・
</xjc>
これで、xjcツール動作時にバインディングファイルが呼び出されます。

と思ったら、NetBeansのJAXBウィザードにちゃんと指定するところがありました。。そりゃそうだ、buildファイル、更新される度に書き換えるわけにはいかないものね。。

クライアントサイド(Flex, Flash, AIR)

Google Maps API for Flashを使う

ここに手順があります。

  1. Google CodeホームGoogle Maps APIホームにて、Google Maps API Keyを取得する。
  2. Google Maps API for FlashのSDKをダウンロードする。
  3. Google Maps API for Flash Developer Guideのセットアップ手順を実行する。
  4. Hello Worldをやってみる。

Picasa Web Albums Data APIを使う

Flexからインターネット・オンラインアルバムなどの写真画像にアクセスする際、flash.display.Loader クラスなどを使用することになりますが、ロードした画像に処理を加えると、サンドボックスのセキュリティ例外が出ます。いわゆる「crossdomain.xml」問題ですね。
ですのでFlash派としては crossdomain.xml ファイルを準備してくれているサービスを利用することが望ましいです。GoogleのPicasaウェブアルバムは下記に準備してくれているので、問題なしです。
http://photos.googleapis.com/data/crossdomain.xml
これについてはAPIのリファレンスガイドに記述してあります。
さて、Picasaウェブアルバム上の画像にアクセスする場合、Googleが提供してくれているAPIを利用するのが便利です。使い方は開発者ガイドを読めばすぐにわかります。いわゆるRESTってやつですね。実際に使用するにはさらに詳細な説明が必要ですので開発者ガイドにあわせてリファレンスガイドも読むようにしてください。

さて、そんなPicasa Web Albums Data APIですが、使い方はとても簡単。
たとえばアルバム一覧情報を取得する場合、
http://photos.googleapis.com/data/feed/api/user/<ユーザ名>?kind=album
に対して HTTP GET を発行すれば、このユーザのアルバムに関する情報がXMLで返されます。次にある特定のアルバムに登録されている画像一覧情報を取得します。アルバム名をURIに含めて指定できるのですが、アルバム名が日本語になっているケースも考え、アルバム名ではなくアルバムIDで指定してみます。アルバムIDは、先ほど発行したアルバム一覧情報内の <link rel='http://schemas.google.com/g/2005#feed'... 要素の href 属性を見れば、「albumid」というキーワードに続いて少し長めの数字が記載されていますのでわかります。
というわけで、アルバム内の画像一覧情報は下記のようなURIを HTTP GET することで取得できます。
http://photos.googleapis.com/data/feed/api/user/<ユーザ名>/albumid/<アルバムID>?kind=photo



記事メニュー
目安箱バナー