勉強会

GPSで現在地を取得してみよう

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: 新規のプロジェクトを作成する

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

手順2: マニフェストファイルを設定する

  • このアプリケーションは、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: レイアウトを決定する

  • レイアウトの設定は、勉強会/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を実装します。

現在位置の変化を受け取るために、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にリスナーを登録します。

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

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

  • 現在位置を表示するために取り出した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: 位置情報の変化を地図に表示します

  • 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の初期値に設定されている地図が表示されます。
    gps.001.DefaultMapActivity.png

手順5: エミュレータから現在位置を指定する

  • EclipseのDDMS画面を開いて、Emulator Controlの中の、Location Controlから緯度と、経度の設定ができます。
    gps.002.EmulatorControl.jpg

手順6:KMLファイルで経路を設定する

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