• 追加された行はこの色です。
  • 削除された行はこの色です。
[[ワーキンググループ/勉強会]]

* GPSで現在地を取得してみよう [#rb0a559b]

GPSから現在位置を取得するAPIを用いて、ロケーションベースサービスの基礎となるアプリケーションを作成してみましょう。

アンドロイドでは、携帯電話の現在位置を取得するサービスを、位置情報サービス(LBS: Location-Based Services)と呼んでいます。LBSは、通常は人工衛星の配置を利用したGPS(Global Positioning System)を利用して位置情報を取得します。しかし、無線LANのアクセスポイントを解析して位置を特定するなど、今後新たに登場する位置情報取得サービスを考慮して、GPSという名前ではなく、より一般化されたLBSという名前を使用しています。

以下、作成のポイントです。
- getSystemService(Context.LOCATION_SERVICE)で、LocationManagerを取得します
- requestLocationUpdatesで、位置情報が変化したときに通知を受け取るためのリスナーを登録します
- GPSなどにアクセスするために、android.permission.ACCESS_FINE_LOCATIONのパーミッションが必要です。
- エミュレータでの開発時にテスト用のGPSを使用するために、android.permission.ACCESS_MOCK_LOCATIONが必要です

** 手順1: 新規のプロジェクトを作成する [#j1193e08]

- "File -> New -> Project"を選択して、開いたダイアログで"Android Poroject"を選択して、"Next"ボタンを押します。
- 開いたダイアログで、以下のように入力してFinishボタンを押します。
-- Project Name: HelloGps
-- Package name: jp.hews.hellogps
-- Activity Name: HelloGpsActivity
-- Application Name: ハローGPS

** 手順2: マニフェストファイルを設定する [#p28d85fc]

- このアプリケーションは、GPSにアクセスするので、manifestの子要素に、以下のパーミッションの使用を宣言します
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-- ManifestEditorの下のPermissionタブを押して、addボタンで追加して、プルダウンメニューで値を設定します。
- 開発時にテスト用のGPSのエミュレータ(MOCK_LOCATION)を使用するので、manifestの子要素に、以下のパーミッションの使用を宣言します
 <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
-- ManifestEditorの下のPermissionタブを押して、addボタンで追加して、プルダウンメニューで値を設定します。
-- マップで現在値を表示するために、GoogleMapを表示するのに必要な設定を行います。設定内容は、[[勉強会/GoogleMap]]を参照してください。
- 上記の設定をしたマニフェストファイルの全体は、以下のようになります。
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="jp.hews.hellogps"
       android:versionCode="1"
       android:versionName="1.0.0">
     <application android:icon="@drawable/icon" android:label="@string/app_name">
         <activity android:name=".HelloGpsActivity"
                   android:label="@string/app_name">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
         <uses-library android:name="com.google.android.maps"/>
     </application>
     <uses-permission android:name="android.permission.INTERNET"/>
 
     <!-- GPSを使用するために必要なパーミッション -->
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
 </manifest> 
  

** 手順3: レイアウトを決定する [#y896312d]

- レイアウトの設定は、[[勉強会/GoogleMap]]と同様に、以下のmain.xmlを使用します。
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
 <com.google.android.maps.MapView
         android:id="@+id/mapview"
         android:layout_width="fill_parent" 
         android:layout_height="fill_parent"
         android:enabled="true"
         android:clickable="true"
         android:apiKey="<取得したAPIキー>"
         />	
 </LinearLayout>
 

** 手順4: MapActivityを継承して、LocationListenerを実装します。 [#zcc32804]

現在位置の変化を受け取るために、LocationListnerを実装します。また、現在位置を表示するために、MapActivityを継承します。

- srcの下のjp.hews.hellomapのHelloGpsActivity.javaを開いて、Activityを継承している部分を、以下のように置き換えます。
 public class HelloGpsActivity extends MapActivity implements LocationListener {
- 未実装のメソッドがあることが通知されるので、以下の未実装のメソッドを追加します。エラーの自動修正を利用すると便利です。
	protected boolean isRouteDisplayed() {}
	public void onLocationChanged(Location location) {}
	public void onProviderDisabled(String provider) {}
	public void onProviderEnabled(String provider) {}
	public void onStatusChanged(String provider, int status, Bundle extras) {}

** 手順5: LocationManagerにリスナーを登録します。 [#mb7fbc40]

- ロケーションマネージャーは、getSystemService(Context.LOCATION_SERVICE)で取得します。
 LocationManager l = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
- GPSからの現在位置の変更通知を受け取るためのリスナーを登録します。
 l.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

** 手順6: 現在位置を表示するために、MapViewを表示可能にします。 [#uc734a7f]

- 現在位置を表示するために取り出したMapControllerをフィールドに保持しておきます。その他の設定は、[[勉強会/GoogleMap]]と同様です。
 
 public class HelloGpsActivity extends MapActivity implements LocationListener {
 	
     // フィールドを追加
     MapController m_controller;
 	
     public void onCreate(Bundle savedInstanceState) {
         ...;
 
         // 解説はHelloMapを参照
         MapView m = (MapView)findViewById(R.id.mapview);
         m_controller = m.getController();
         m_controller.setZoom(15);
         
         ZoomControls zc = (ZoomControls) m.getZoomControls();
         zc.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
         zc.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
         m.addView(zc);
     }
 
** 手順7: 位置情報の変化を地図に表示します [#e2a55b24]
- onLocationChangedを実装します。引数のLocationをGeoPointに変換して、MapControllerに設定します。
- GeoLocationは、経度と緯度を10万倍して整数にしたものを使用します。
- 地図の表示は、animateToメソッドにGeoPointを渡すことで、現在位置からスムーズに指定した位置に移動します。
 	public void onLocationChanged(Location location) {
 		GeoPoint gp = 
 			new GeoPoint((int)(location.getLatitude()*1E6),
 				         (int)(location.getLongitude()*1E6));
 		m_controller.animateTo(gp);
 	}

- ここまでで、全体のソースコードは、以下のようになっています。
 package jp.hews.hellogps;
 
 import android.content.Context;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
 import android.os.Bundle;
 import android.view.Gravity;
 import android.view.ViewGroup;
 import android.widget.ZoomControls;
 
 import com.google.android.maps.GeoPoint;
 import com.google.android.maps.MapActivity;
 import com.google.android.maps.MapController;
 import com.google.android.maps.MapView;
 
 public class HelloGpsActivity extends MapActivity implements LocationListener {
 	
 	// フィールドを追加
 	MapController m_controller;
 	
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
         
         // 現在位置が変化に、メソッドが呼び出されよう登録する。
         LocationManager l = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
         l.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
 
         // 解説はHelloMapを参照
         MapView m = (MapView)findViewById(R.id.mapview);
         m_controller = m.getController();
         m_controller.setZoom(15);
         
         ZoomControls zc = (ZoomControls) m.getZoomControls();
         zc.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
         zc.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
         m.addView(zc);
         
     }
 
 	@Override
 	protected boolean isRouteDisplayed() {
 		return false;
 	}
 
 	public void onLocationChanged(Location location) {
 		GeoPoint gp = 
 			new GeoPoint((int)(location.getLatitude()*1E6),
 				         (int)(location.getLongitude()*1E6));
 		m_controller.animateTo(gp);
 	}
 
 	public void onProviderDisabled(String provider) {
 		// TODO 
 	}
 
 	public void onProviderEnabled(String provider) {
 		// TODO 
 	}
 
 	public void onStatusChanged(String provider, int status, Bundle extras) {
 		// TODO 
 	}
 }
- プロジェクトを右クリックして、"Run As"->"Android Application"で実行してみましょう。MapActivityの初期値に設定されている地図が表示されます。
#ref(gps.001.DefaultMapActivity.png)

** 手順5: エミュレータから現在位置を指定する [#k4c58187]
- EclipseのDDMS画面を開いて、Emulator Controlの中の、Location Controlから緯度と、経度の設定ができます。
#ref(gps.002.EmulatorControl.jpg)

** 手順6:KMLファイルで経路を設定する [#ae23b25d]
- Google Earthで経路をKMLファイルで作成して、Emulator Controlの中の、Location Controlから設定できます。
- http://earth.google.co.jp/からGoogle Earthをダウンロードして実行します
- 場所のウィンドウのお気に入りを右クリックして新しいフォルダーを作成します
- 好きな地点を表示して、フォルダーを右クリックして、「追加->目印」で、ポイントを追加します
#ref(gps.003.GoogleEarth.jpg)
- 数か所追加したら、フォルダーの右クリックで、「名前をつけて場所を保存」で、種類をKMLにしてファイルを保存します
#ref(gps.004.SaveKML.jpg)
- Emulator Controlの中の、Location ControlのKMLタブを開いて、Load KMLでファイルをロードする
#ref(gps.005.KML.jpg)
- KMLタブの下方の緑の開始ボタンを押すと、GPSの移動が開始します。