AndroidでGoogleMapアプリ開発
第1回 表示
第2回 表示形式 衛星、地図、地形図
第3回 マーカーと直線
第4回 googleMapのエラー
第5回 PlaceAPIとマーカーのセット
第6回 現在地 GPSの実装
第7回 トラッキング
第8回 様々な技法
googleMapを使ったアプリの開発です。GoogleMapAPIを使用します。Androidアプリの場合は無制限で利用可能です。(対してJavaScript版は制限があります)
プロジェクト作成から簡単にgoogleMapを表示させるアプリを作ることができます。ただし、今回は仕組みを理解する意味で手動でgoogleMapを表示させるアプリを作ります。通常通り空のプロジェクトを作成します。HelloWorldの表示のみのプロジェクトです。
gradle設定
Appのgradle(Module:App)のdependenciesにplay-services-mapsを追加する。
dependencies { implementation 'com.google.android.gms:play-services-maps:11.8.0' }
Manifestの設定
以下を追記することとなります。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" />
android.permission | 目的 |
---|---|
.ACCESS_COARSE_LOCATION | Wifiなどのネットワーク情報を利用して位置情報を取得する。そのため.INTERNETの必要となります。 |
.INTERNET | ネットワーク接続 |
.ACCESS_FINE_LOCATION | GPSを含めた位置情報の取得 |
ACCESS_FINE_LOCATIONはACCESS_COARSE_LOCATIONを含みます。ですから実際はACCESS_COARSE_LOCATIONを記述する必要はありません。
APIキーの設定
<meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" />
stringにキーを設定します。
<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR_KEY_HERE</string>
YOUR_KEY_HEREの部分に取得したAPIキーを記述します。translatable属性は多言語化しない場合は特に必要はありませんが言語問わず一定値ですから記述しておいたほうが良いでしょう。templateMergeStrategyはキーの保存に関する属性ですが深く考える必要はありません。
Manifestはまとめますと以下のように。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.honeybread.directionthat"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
レイアウトのxml
以下を記述します。デフォルトではhelloWorldのTextViewですから、fragmentに入れ替えます。
<fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent"/>
MainActivityのJAVA
いよいよJAVAです。以下の手順です。今回は富士山を中央表示します。
①GoogleMap、LatLngのインスタンス作成
GoogleMap mMap; double mtFujiLatDouble = 35.360556; double mtFujiLngDouble = 138.727778; LatLng targetLatLng= new LatLng(mtFujiLatDouble ,mtFujiLngDouble );
targetLatLngに富士山山頂の緯度経度情報を入れました。
②OnMapReadyCallbackインタフェースを実装します。
implements OnMapReadyCallback
③SupportMapFragmentのインスタンス作成し、OnMapReadyCallbackをgetMapAsyncで設定します。
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this);
②onMapReady(GoogleMap googleMap)をオーバーライド。
@Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; mMap.moveCamera(CameraUpdateFactory.newLatLng(targetLatLng)); }
まとめると以下のコード
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback { GoogleMap mMap; double mtFujiLatDouble = 35.360556; double mtFujiLngDouble = 138.727778; LatLng targetLatLng= new LatLng(mtFujiLatDouble ,mtFujiLngDouble ); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; mMap.moveCamera(CameraUpdateFactory.newLatLng(targetLatLng)); } }
実行すると、、
大きすぎて富士山がどこなのかさっぱりわかりません。コードのどこかを変更してズームする必要があります。
googleMapをズームする
mMap.moveCamera(….)はターゲットにカメラ(マップ)の中央を移動させるという意味です。このあたりに何かすればよさそうです。googleMapに関するリファレンスを参照してみましょう。
このなかにZoom絡みの記述がありますので、そちらを利用して以下を追加します。
mMap.moveCamera(CameraUpdateFactory.zoomTo(18));
追加ですから、まずカメラを富士山に移動させ、次の行で18にズーム設定を行います。
さて、この18という数値、どこからきたのでしょう?ここで現在のマップの最大値を取得します。例えば
Log.d("Log0",""+mMap.getMaxZoomLevel());
のようにして、ズームを確認しました。18と指定してしまうのも良いのですが、次の書き方のほうが良いでしょう。
mMap.moveCamera(CameraUpdateFactory.zoomTo(mMap.getMaxZoomLevel()-3));
こうすれば最大ズーム値から3ズームアウトしたマップが表示されます。
実行すると、
良い感じになりました。
では、次にマップを回転させてみます。90度。と言いたいところです。しかしこの方法ではリファレンスを見ての通りこの辺りが限界です。AndroidStudioでCameraUpdateFactory.として候補を見るとnewCameraPositionというメソッドが用意されています。こちらを利用しましょう。
CameraUpdateFactoryの利用
角度設定の話の前にこちらを利用して中心地点とズームレベルを設定しなおします。
CameraPosition cameraPosition;
として、onMapReadyに以下を記述。
cameraPosition = new CameraPosition.Builder() .target(targetLatLng).zoom(mMap.getMaxZoomLevel()-3) .build();
そしてmMapに設定します。
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
同じ富士山の地図が表示されました。ズームレベルも同じです。
それでは、角度をつけます。bearingが用意されていますのでcameraPositionに追加します。
cameraPosition = new CameraPosition.Builder() .target(targetLatLng).zoom(mMap.getMaxZoomLevel()-3) .bearing(90) .build();
結果は
ここで注意していただきたいことはマップが90度回転ではなく、カメラが90度回転ということです。あくまでmoveCameraです。ですから地図が-90度回転したように見えるわけです。
googleMapサンプルコード
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback { GoogleMap mMap; double mtFujiLatDouble = 35.360556; double mtFujiLngDouble = 138.727778; LatLng targetLatLng= new LatLng(mtFujiLatDouble ,mtFujiLngDouble ); CameraPosition cameraPosition; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; cameraPosition = new CameraPosition.Builder() .target(targetLatLng).zoom(mMap.getMaxZoomLevel()-3) .bearing(90) .build(); mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); // mMap.moveCamera(CameraUpdateFactory.newLatLng(targetLatLng)); // mMap.moveCamera(CameraUpdateFactory.zoomTo(mMap.getMaxZoomLevel()-3)); } }