PhoneGapで各種センサーや音楽再生、電話帳などといったデバイスやプラットフォーム固有の機能を利用したい場合には、PhoneGap APIと呼ばれるJavaScriptベースのAPIを利用します。通常、これらの機能にアクセスする手段はプラットフォームごとに異なりますが、その差異はPhoneGap APIによって吸収されるため、開発者は対象とするプラットフォームの違いを意識することなくコーディングを行うことが可能です。

本稿ではそんなPhoneGap APIの中から、位置情報を利用するためのGeolocation APIの使い方を解説します。

Geolocation APIの概要

Geolocation APIは、PhoneGapを用いてモバイル端末の位置情報サービスにアクセスするためのAPIです。多くのモバイル端末では、GPSセンサーや無線LANのアクセスポイント情報などを元にして端末の現在位置を算出する機能を持っています。PhoneGapのGeolocation APIを使えば、それらの位置情報にアクセスするためのネイティブのサービスをJavaScriptから利用することができるようになります。

Geolocation APIはW3Cの「Geolocation API Specification」に準拠しています。多くのモバイル端末のネイティブAPIはこのW3C仕様に準拠しているので、PhoneGapのGeolocation APIとの互換性も極めて高いものとなっています。

Geolocation APIによって取得できるのは、端末の現在位置の座標(緯度・経度)や高度、移動方向や速度などといった情報です。これらの位置情報はPositionオブジェクトという読み込み専用のオブジェクトに格納されます。アプリ内ではgeolocation.getCurrentPositionというメソッドによってPositionオブジェクトを取得し、そこに格納された位置情報を参照することができます。

具体的には、Positionオブジェクトは端末の位置情報を次のようなプロパティの値として保持しています。

  • coords.latitude - 緯度
  • coords.longitude - 経度
  • coords.altitude - 高度
  • coords.accuracy - 位置精度
  • coords.altitudeAccuracy - 高度制度
  • coords.heading - 方向
  • coords.speed - 速度
  • timestamp - タイムスタンプ

パーミッションの設定

位置情報サービスを利用する場合、ほとんどのプラットフォームがパーミッションを要求します。したがって、アプリ側ではパーミッション申請のための設定ファイルを用意しておかなければいけません。本稿の例のようにPhoneGap Buildを利用する場合には、config.xmlに次の設定を追加します。PhoneGap Buildにおける設定についてはNotification API編も参考にしてください。

[サンプルコード: 位置情報サービスへのアクセス権限を申請する]

<feature name="http://api.phonegap.com/1.0/geolocation"/>

また、PhoneGap Buildを使わずにローカルの開発環境でビルドを行う場合の設定方法は公式サイトのAPIドキュメントに掲載されています。

位置情報を取得する

それでは、実際に端末から位置情報を取得してみましょう。前述のように、端末の現在の位置情報はgeolocation.getCurrentPositionメソッドを呼び出すことで取得できます。getCurrentPositionには引数として取得成功時のコールバック関数とエラー発生時のコールバック関数を指定します。成功時のコールバック関数には、位置情報が格納されたPositionオブジェクをが渡されます。一方エラー発生時のコールバック関数には、エラー情報を格納したPositionErrorオブジェクトが渡されます。

次のコードは、アプリの起動時に位置情報を取得し、その内容を表示するプログラムのサンプルです。

[サンプルコード: 起動時に位置情報を取得して表示する]

<!DOCTYPE html> <html> <head> <title>PhoneGapによる位置情報の利用</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /> <meta charset="utf-8"> <script type="text/javascript" charset="utf-8" src="phonegap.js"></script> <script type="text/javascript"> function onBodyLoad() { document.addEventListener("deviceready", onDeviceReady, false); } function onDeviceReady() { getGeolocation(); } // 位置情報の取得 function getGeolocation() { navigator.geolocation.getCurrentPosition(onSuccess, onError); } // 位置情報の取得成功時のコールバック関数 function onSuccess(position) { // Positionのプロパティから情報を取得してDOMを更新 document.getElementById("latitude").innerHTML = position.coords.latitude; // 緯度 document.getElementById("longitude").innerHTML = position.coords.longitude; // 経度 document.getElementById("altitude").innerHTML = position.coords.altitude; // 高度 document.getElementById("accuracy").innerHTML = position.coords.accuracy; // 位置精度 document.getElementById("altitudeAccuracy").innerHTML = position.coords.altitudeAccuracy; // 高度精度 document.getElementById("heading").innerHTML = position.coords.heading; // 方位 document.getElementById("speed").innerHTML = position.coords.speed; // 速度 document.getElementById("timestamp").innerHTML = position.timestamp; // タイムスタンプ } // エラー時のコールバック関数 function onError(error) { alert('コード: ' + error.code + '\n' + 'メッセージ: ' + error.message + '\n'); } </script> </head> <body onload="onBodyLoad()"> <h1>位置情報の取得</h1> <ul> <li>緯度:<span id="latitude"/></li> <li>経度:<span id="longitude"/></li> <li>高度:<span id="altitude"/></li> <li>位置精度:<span id="accuracy"/></li> <li>高度精度:<span id="altitudeAccuracy"/></li> <li>方位:<span id="heading"/></li> <li>速度:<span id="speed"/></li> <li>タイムスタンプ:<span id="timestamp"/></li> </ul> </body> </html>

ライブラリの読み込みが完了した際に呼び出されるonDeviceReadyメソッドでgetGeolocationメソッドを実行しています。

図2は、iPhone上でこのプログラムを実行してみた例です。現在地の座標等の情報が取得できていることがわかります。

なお速度は移動していないので-1になっています。方位も-1になっていますが、これはGeolocation APIでは一定速度で移動したときにしか方角を取得できないためです。方位の取得はGeolocation APIではなくCompass APIを用いて行う方が適しています。

位置情報の変化を監視する

Geolocation APIでは、位置情報を監視して、変化があった場合にその値を取得するといったこともできます。監視はgeolocation.watchPositionメソッドとgeolocation.clearWatchメソッドによって行います。

まず、watchPositionで次のようにして監視を開始します。

[サンプルコード:位置情報の監視を開始する]

var options = { enableHighAccuracy: true }; var watchId = navigator.geolocation.watchPosition(onSuccess, onError, options);

第1引数には位置情報の取得が成功した際に呼び出されるコールバック関数を、第2引数にはエラー発生時に呼び出されるコールバック関数を指定します。第3引数は位置情報の取得のためのオプションを指定するもので、次のプロパティが使用できます。

  • enableHighAccuracy - GPSなどを利用したより制度の高い位置情報を使用するかどうかtrue/falseで指定する。デフォルトはfalseで、ネットワークベースでの位置情報を使用する。
  • timeout - コールバック関数が呼ばれるまでのタイムアウト時間をミリ秒単位で指定する。
  • maximumAge - キャッシュされた位置情報を利用する有効時間をミリ秒単位で指定する。

watchPositionメソッドは固有のwatch IDを返します。このwatch IDは監視を終了する際に使用されます。監視の終了はclearWatchメソッドにwatch IDを指定して次のように行います。

[サンプルコード:位置情報の監視を終了する]

navigator.geolocation.clearWatch(watchId);

次の例は、先ほどのgetCurrentPositionメソッドの使用例に、watchPosition/clearWatchメソッドによる監視の開始と終了を追加したものです。

[サンプルコード:位置情報をリアルタイムに取得して画面に表示する]

<!DOCTYPE html> <html> <head> <title>PhoneGapによる位置情報の利用</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /> <meta charset="utf-8"> <script type="text/javascript" charset="utf-8" src="phonegap.js"></script> <script type="text/javascript"> var watchId = null; function onBodyLoad() { document.addEventListener("deviceready", onDeviceReady, false); } function onDeviceReady() { getGeolocation(); } // 位置情報の取得 function getGeolocation() { navigator.geolocation.getCurrentPosition(onSuccess, onError); } // 位置情報の取得成功時のコールバック関数 function onSuccess(position) { // Positionのプロパティから情報を取得してDOMを更新 document.getElementById("latitude").innerHTML = position.coords.latitude; // 緯度 document.getElementById("longitude").innerHTML = position.coords.longitude; // 経度 document.getElementById("altitude").innerHTML = position.coords.altitude; // 高度 document.getElementById("accuracy").innerHTML = position.coords.accuracy; // 位置精度 document.getElementById("altitudeAccuracy").innerHTML = position.coords.altitudeAccuracy; // 高度精度 document.getElementById("heading").innerHTML = position.coords.heading; // 方位 document.getElementById("speed").innerHTML = position.coords.speed; // 速度 document.getElementById("timestamp").innerHTML = position.timestamp; // タイムスタンプ } // エラー時のコールバック関数 function onError(error) { alert('コード: ' + error.code + '\n' + 'メッセージ: ' + error.message + '\n'); } // 監視の開始 function watchStart() { var options = { enableHighAccuracy: true }; watchId = navigator.geolocation.watchPosition(onSuccess, onError, options); document.getElementById("stopButton").disabled = null; document.getElementById("startButton").disabled = "disabled"; } // 監視の終了 function watchStop() { navigator.geolocation.clearWatch(watchId); document.getElementById("startButton").disabled = null; document.getElementById("stopButton").disabled = "disabled"; } </script> </head> <body onload="onBodyLoad()"> <h1>位置情報の監視</h1> <ul> <li>緯度:<span id="latitude"/></li> <li>経度:<span id="longitude"/></li> <li>高度:<span id="altitude"/></li> <li>位置精度:<span id="accuracy"/></li> <li>高度精度:<span id="altitudeAccuracy"/></li> <li>方位:<span id="heading"/></li> <li>速度:<span id="speed"/></li> <li>タイムスタンプ:<span id="timestamp"/></li> </ul> <input type="submit" id="startButton" value="監視スタート" onClick="watchStart()"/> <input type="submit" id="stopButton" value="監視ストップ" onClick="watchStop()" disabled="disabled"/> </body> </html>

このプログラムをiPhone上で実行すると、まず現在の位置情報を取得して図3のように表示します。ここまでは先程の例と同様です。ここで[監視スタート]ボタンを押すと位置情報の監視をはじめて、もし端末が移動した場合には、図4のようにその都度表示されている値が変化するはずです。監視の終了は[監視ストップ]ボタンによって行います。

位置情報の利用は、モバイル端末を使う醍醐味のひとつと言えます。Geolocation APIは極めてシンプルに作られているので、すぐに使いこなすことができるでしょう。