MapView で Google Map を表示
〜 Android Studio の使い方 17 〜
2023-11-11 作成 福島
TOP > androidstudio > mapview

使用ツール

    Android Studio Giraffe | 2022.3.1 Patch 2  


Android Studio Giraffe では、プロジェクトを新規作成するときに「Google Map テンプレート」を選択することができなくなりました。
(もしも同等のプロジェクトを作成したいなら  app  >  File  -  New  -  Fragment  -  Gallery...  から  Google Maps Fragment  を選択します)

「Google Map テンプレート」は Fragment による実装でしたが、ここでは MapView で実装します。
MapView を使用することにより、ほかの View との重ね合わせを直感的に配置できます。


0. 事前準備 (Web ページ Google Maps Platform で作業)

Google Map を表示するには「Google Maps API」を使用しますが、
それには API キー (長い文字列) の発行を受け、そのキーをプログラムに埋め込まなければなりません。
API キーはアカウント毎ではなく、プロジェクト毎の発行です。

API キーは有料 (発行前にクレジットカードの登録が必要) ですが無料期間が 90 日あり、これを過ぎると 30 日間の猶予の後に API キーが無効になります。
キーが無効になるとサービスが受けられなくなるだけで、料金の発生はありません。

Google Cloud の無料プログラム」によると、条件は以下なので、無料トライアルは 1 回だけ受けられる、ということになります。

以下抜粋
このとき、さらに Google Maps API を使うには、以下の方法があります。
「料金」は「お客様のニーズに合わせた柔軟な料金設定」によると、「1 か月あたり 28,500 回まで無料の地図読み込み」とあるので、開発目的なら無料という算段になります。
(負荷テストとかは、やっちゃだめですよ)


API キーの取得

0-1. Gmail アカウント (= Google アカウント) の作成
Google アカウントは Gmail アカウントを作成すると、それに付随して作成される。
すでに Gmail アカウントがあるなら、作成の必要はない。
0-2. Google Cloud へログイン
Google Maps Platform をブラウザでアクセスし、「使ってみる」から Gmail アカウントでログインすると、Google Cloud が使えるようになる。
0-3. プロジェクトを作成
Google Cloud の「≡」(ナビゲーションメニュー) にある「Google Maps Platform」からプロジェクトを一つ作成する。
プロジェクトを作成すると、自動的に API キーが発行される。
(API キーを発行するような操作は特に必要ない)
0-4. API キーの表示
作成したプロジェクトを選択し「≡」の「Google Maps Platform」から「鍵と認証情報」を選択する。

中央ペインの「API キー」の下にある「鍵を表示します」をクリックして API キーを表示する。

ここで表示した API キーの文字列をコピーし、後述の MAPS_API_KEY= として設置する。(下記 3-1)


1. Android Studio で通常のプロジェクトを作成する。

ここでは MapView を利用して Google Map を表示するので、画面の存在するプロジェクトを作成する。
「Empty Activity」「Empty Views Activity」等のプロジェクトが対象。
「No Activity」でも構わないが、Default Activity の追加が必要になるので、ここでは割愛する。(選択しない)


2. アクティビティに MapView を配置する。

要素名内容備考
アクティビティAndroid > app > res > layout > activity_main.xml-
部品種類MapView-
idmapViewプログラムから R.id.mapView として参照される。
MapView を設置すると「No speakable text present」の警告が表示される。無視の設定をするか、contentDescription を設定すると警告が消える。


3. API キーの設置

3-1. local.properties を開き、API キー (上記 0-4 で取得) を設置する。
 Android  >  Gradle Scripts  >  local.properties  を編集する。
MAPS_API_KEY= の右辺に記述する。(行そのものがないので、1 行追加)
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=/home/who/Android/Sdk
MAPS_API_KEY=AbCdEfGhIjKlMnOpQrStUvWxYz-0123456789aZ
MAPS_API_KEY は下記 AndroidManifest.xml から value="${MAPS_API_KEY}" として参照する。
ここではサンプルのため、でたらめな文字列にしている。


4. 設定ファイルの調整

4-1. Manifest の追加
 Android  >  app  >  manifests  >  AndroidManifest.xml  を編集する。
<application></application> の中に <meta-data> を挿入する。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        ~省略~
        tools:targetApi="31">
        
<meta-data android:name="com.google.android.geo.API_KEY" android:value="${MAPS_API_KEY}" />
<activity ~省略~ </activity> </application> </manifest>
4-2. プラグインの追加 (1)
 Android  >  Gradle Scripts  >  build.gradle.kts (Project)  を編集する。
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id("com.android.application") version "8.1.2" apply false


id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") version "2.0.1" apply false
}
4-3. プラグインの追加 (2)
 Android  >  Gradle Scripts  >  build.gradle.kts (Module :app)  を編集する。
plugins {
    id("com.android.application")


id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
} ~省略~
4-4. ビルド情報の反映。
メニュー   File    Sync Project with Gradle Files   Ctrl+Shift+O   を選択する。


5. 地図の表示

5-1. MainActivity.java にコードを記述する。
フラグメント xxx_Fragment.java に記述する場合は  onCreate(··· ではなく  onCreateView(··· に記述する。
参考はここ
public class MainActivity extends AppCompatActivity {


private MapView mMapView;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
// MapView に GoogleMap を表示する mMapView = findViewById(R.id.mapView); mMapView.onCreate(savedInstanceState); // GoogleMap のコールバックメソッドを用意する OnMapReadyCallback onMapReadyCallback = new OnMapReadyCallback() { @Override public void onMapReady(@NonNull GoogleMap googleMap) { // ジェスチャーによる地図の回転を許可する UiSettings uiSettings = googleMap.getUiSettings(); uiSettings.setRotateGesturesEnabled(true); // 東京タワーの緯度・経度 LatLng tokyoTower = new LatLng(35.65867633445335, 139.74545436106237); // 東京タワーのマーカーを設置する MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(tokyoTower); markerOptions.title("東京タワー"); googleMap.addMarker(markerOptions); // 東京タワーを中心にして地図を表示する googleMap.moveCamera(CameraUpdateFactory.newLatLng(tokyoTower)); googleMap.moveCamera(CameraUpdateFactory.zoomTo(8.0f)); // ジェスチャーによる地図の移動開始リスナを用意する googleMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() { @Override public void onCameraMoveStarted(int i) { // カメラ移動の開始要因を求める String reason = ""; switch(i) { case GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE: reason = "GESTURE"; break; case GoogleMap.OnCameraMoveStartedListener.REASON_API_ANIMATION: reason = "API_ANIMATION"; break; case GoogleMap.OnCameraMoveStartedListener.REASON_DEVELOPER_ANIMATION: reason = "DEVELOPER_ANIMATION"; break; } Toast.makeText(MainActivity.this, "CameraMove Started: " + reason, Toast.LENGTH_SHORT).show(); } }); // ジェスチャーによる地図の移動中リスナを用意する googleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() { @Override public void onCameraMove() { // カメラ位置を求める CameraPosition cameraPosition = googleMap.getCameraPosition(); LatLng latLng = cameraPosition.target; float zoom = cameraPosition.zoom; float bearing = cameraPosition.bearing; String state = String.format("%7.3f %7.3f %7.3f %7.3f°", latLng.latitude, latLng.longitude, zoom, bearing); Log.d("CameraMove", state); //トーストだとイベント発生が多すぎて追従できない } }); // ジェスチャーによる地図の移動終了リスナを用意する googleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() { @Override public void onCameraIdle() { // カメラ位置を求める CameraPosition cameraPosition = googleMap.getCameraPosition(); LatLng latLng = cameraPosition.target; float zoom = cameraPosition.zoom; float bearing = cameraPosition.bearing; String state = String.format("%7.3f %7.3f %7.3f %7.3f°", latLng.latitude, latLng.longitude, zoom, bearing); Toast.makeText(MainActivity.this, "CameraMove in Idle:\n"+state, Toast.LENGTH_SHORT).show();
// ここはお好みで追加する LatLngBounds bounds = googleMap.getProjection().getVisibleRegion().latLngBounds; Log.d("LatLngBounds", String.format("%7.3f,%7.3f - %7.3f,%7.3f", bounds.northeast.latitude, bounds.northeast.longitude, bounds.southwest.latitude, bounds.southwest.longitude));
} }); } }; // GoogleMap のコールバックメソッドを登録する mMapView.getMapAsync(onMapReadyCallback);
}
@Override protected void onResume() { super.onResume(); mMapView.onResume(); } @Override protected void onStart() { super.onStart(); mMapView.onStart(); } @Override protected void onStop() { super.onStop(); mMapView.onStop(); } @Override protected void onPause() { mMapView.onPause(); super.onPause(); } @Override protected void onDestroy() { mMapView.onDestroy(); super.onDestroy(); } @Override public void onLowMemory() { super.onLowMemory(); mMapView.onLowMemory(); }
}