Google Mapで現在地を表示 - MapActivity, MapView, MyLocationOverlay, LocationManagerの連携
今回は以前postしたLocationManagerとGoogle Maps APIを使った実装をしてみたいと思います
やりたいこと
-
- MapActivity、MapViewを使用しmapを表示/ちょっとした操作
- LocationManagerを使用しUser location情報を取得
- MyLocationOverlayを使用しUser location(現在地)をmap上に表示
実装の要点は下記です
1. AndroidManifest.xmlにGoogle Maps libraryを使用する為のtagを記載
<uses-library android:name="com.google.android.maps" />
2. AndroidManifest.xmlにInternetとLocation情報にaccessする為のPermissionを記載
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
3. Layout xmlにMapViewを定義し、apiKey attributeを記載
<com.google.android.maps.MapView android:id="@+id/map_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="自分のGoogle maps api key" />
4. MapActivityを拡張したclassを作成
public class MyMapActivity extends MapActivity{ @Override protected boolean isRouteDisplayed() { return false; } }
5. MapView objectを取得し、MapView#setBuiltInZoomControls()をtrueで実行
mMapView = (MapView)findViewById(R.id.map_view);
mMapView.setBuiltInZoomControls(true);
6. MapController objectを取得(MapのAnimationとかの為)
mMapController = mMapView.getController();
7. MyLocationOverlayを取得しMapViewのOverlay listに登録
mMyLocationOverlay = new MyLocationOverlay(this, mMapView); List<Overlay> overlays = mMapView.getOverlays(); overlays.add(mMyLocationOverlay);
気付いた点です
-
- Layout xmlに定義するMapViewのnameはpackage名からきちんと記載(当たり前かな?)
んで実装です
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.practice.map" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MyMapActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--AndroidManifest.xmlにGoogle Maps libraryを使用する為のtagを記載 --> <uses-library android:name="com.google.android.maps" /> </application> <!-- AndroidManifest.xmlにInternetとLocation情報にaccessする為のPermissionを記載 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> </manifest>
Layout 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" > <!-- MapViewをLayout xmlに定義 --> <!-- apiKeyを記載 --> <com.google.android.maps.MapView android:id="@+id/map_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="自分のGoogle maps api key" /> </LinearLayout>
MapActivityなど
package com.android.practice.map; import java.util.List; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import com.google.android.maps.MyLocationOverlay; import com.google.android.maps.Overlay; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import android.widget.Toast; //MapActivityを拡張したclassを作成 public class MyMapActivity extends MapActivity { private static final String TAG = "MyMapActivity"; private static final boolean DEBUG = true; private static final String ACTION_LOCATION_UPDATE = "com.android.practice.map.ACTION_LOCATION_UPDATE"; private MapController mMapController; private MapView mMapView; private MyLocationOverlay mMyLocationOverlay; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initMapSet(); } @Override protected void onResume() { super.onResume(); setOverlays(); setIntentFilterToReceiver(); requestLocationUpdates(); } @Override protected void onPause() { super.onPause(); resetOverlays(); removeUpdates(); } @Override protected void onDestroy() { super.onDestroy(); } @Override protected boolean isRouteDisplayed() { return false; } private void initMapSet(){ //MapView objectの取得 mMapView = (MapView)findViewById(R.id.map_view); //MapView#setBuiltInZoomControl()でZoom controlをbuilt-in moduleに任せる mMapView.setBuiltInZoomControls(true); //MapController objectを取得 mMapController = mMapView.getController(); } private void setOverlays(){ //User location表示用のMyLocationOverlay objectを取得 mMyLocationOverlay = new MyLocationOverlay(this, mMapView); //初めてLocation情報を受け取った時の処理を記載 //試しにそのLocationにanimationで移動し、zoom levelを19に変更 mMyLocationOverlay.runOnFirstFix(new Runnable(){ public void run(){ GeoPoint gp = mMyLocationOverlay.getMyLocation(); mMapController.animateTo(gp); mMapController.setZoom(19); } }); //LocationManagerからのLocation update取得 mMyLocationOverlay.enableMyLocation(); //overlayのlistにMyLocationOverlayを登録 List<Overlay> overlays = mMapView.getOverlays(); overlays.add(mMyLocationOverlay); } private void resetOverlays(){ //LocationManagerからのLocation update情報を取得をcancel mMyLocationOverlay.disableMyLocation(); //overlayのlistからMyLocationOverlayを削除 List<Overlay> overlays = mMapView.getOverlays(); overlays.remove(mMyLocationOverlay); } private void setIntentFilterToReceiver(){ final IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_LOCATION_UPDATE); registerReceiver(new LocationUpdateReceiver(), filter); } private void requestLocationUpdates(){ final PendingIntent requestLocation = getRequestLocationIntent(this); LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE); for(String providerName: lm.getAllProviders()){ if(lm.isProviderEnabled(providerName)){ lm.requestLocationUpdates(providerName, 0, 0, requestLocation); if(DEBUG)Log.d(TAG, "Provider: " + providerName); } } } private PendingIntent getRequestLocationIntent(Context context){ return PendingIntent.getBroadcast(context, 0, new Intent(ACTION_LOCATION_UPDATE), PendingIntent.FLAG_UPDATE_CURRENT); } private void removeUpdates(){ final PendingIntent requestLocation = getRequestLocationIntent(this); LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE); lm.removeUpdates(requestLocation); if(DEBUG)Toast.makeText(this, "Remove update", Toast.LENGTH_SHORT).show(); } public class LocationUpdateReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if(action == null){ return; } if(action.equals(ACTION_LOCATION_UPDATE)){ //Location情報を取得 Location loc = (Location)intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED); //試しにMapControllerで現在値に移動する mMapController.animateTo(new GeoPoint((int)(loc.getLatitude() * 1E6), (int)(loc.getLongitude() * 1E6))); if(DEBUG)Toast.makeText(context, "latitude:" + loc.getLatitude() + "\nlongitude:" + loc.getLongitude(), Toast.LENGTH_SHORT).show(); } } }
とこんな感じです。簡単にUser location(現在地)情報がGoogle map上に表示されたり、そこまでAnimationして移動したり出来るという事が分かります。ただ、MyLocationOverlayだと、その他、出来ることが限られて来るかなと思いますので今度は大元のOverlayやItemizedOverlayを試しに使用してみたいなと思います
HashTag #Java, #Android, #MapActivity, #MapView, #MapController, #MyLocationOverlay, #LocationManager, #Location, #GeoPoint, #BroadcastReceiver, #IntentFilter