ルートとエリアを表すポリラインとポリゴン

このチュートリアルでは、Google マップを Android アプリに追加し、マップ上のルートやエリアを表すポリラインやポリゴンを使用する方法を紹介します。

Maps SDK for Android を使用して Android アプリを作成するには、このチュートリアルを参考にしてください。推奨される開発環境は Android Studio です。

コードを取得する

GitHub から、Google Maps Android API v2 サンプル リポジトリをダウンロードするかクローンを作成します。

開発プロジェクトを設定する

次のステップに従って、Android Studio でチュートリアル プロジェクトを作成します。

  1. Android Studio をダウンロードしてインストールします。
  2. Android Studio に Google Play 開発者サービス パッケージを追加します。
  3. Google Maps Android API v2 のサンプル リポジトリをダウンロードするかクローンを作成します(このチュートリアルの閲覧を開始した時点で行っていない場合)。
  4. 次の手順でチュートリアル プロジェクトをインポートします。

    • Android Studio で、[File] > [New] > [Import Project] を選択します。
    • ダウンロードした Google Maps Android API v2 のサンプル リポジトリの保存先に移動します。
    • 次の場所で Polygons プロジェクトを見つけます。
      PATH-TO-SAVED-REPO/android-samples/tutorials/Polygons
    • プロジェクト ディレクトリを選択して、[OK] をクリックします。Android Studio で、Gradle ビルドツールを使用してプロジェクトが作成されます。

API キーを取得して必要な API を有効にする

このチュートリアルを完了するには、Maps SDK for Android の使用が許可されている Google API キーが必要です。

キーを取得して API を有効にするには、下のボタンをクリックしてください。

使ってみる

詳細については、API キーの取得に関する詳しいガイドをご覧ください。

アプリに API キーを追加する

  1. プロジェクトの gradle.properties ファイルを編集します。
  2. API キーを GOOGLE_MAPS_API_KEY プロパティの値に貼り付けます。アプリを作成すると、下記のように、Gradle で API キーがアプリの Android マニフェストにコピーされます。

    GOOGLE_MAPS_API_KEY=PASTE-YOUR-API-KEY-HERE
    

アプリを作成して実行する

  1. Android デバイスをコンピュータに接続します。手順に沿って、Android デバイスでデベロッパー オプションを有効にし、デバイスを検出するようにシステムを設定します(または、Android Virtual Device(AVD)Manager を使用して仮想デバイスを設定することもできます。エミュレータを指定する際は、Google API を含むイメージを選択する必要があります。詳しくは、スタートガイドをご覧ください)。
  2. Android Studio で [Run] メニュー オプション(またはプレイボタン アイコン)をクリックします。 表示される指示に沿ってデバイスを選択します。

Android Studio で Gradle が起動してアプリが作成され、そのアプリがデバイスまたはエミュレータ上で実行されます。

このページの画像のように、オーストラリアに 2 つのポリゴンがオーバーレイされた地図が表示されます。

トラブルシューティング:

  • 地図が表示されない場合は、上記の手順どおりに API キーを取得してアプリに追加しているかご確認ください。Android Studio の Android Monitor のログでも、API キーに関するエラー メッセージを確認してください。
  • ログを表示してアプリをデバッグするには、Android Studio デバッグツールを使用します。

コードを理解する

このパートでは、Polygons アプリの最も重要な部分について説明します。同様のアプリを作成する方法について理解を深めていただけます。

Android マニフェストを確認する

アプリの AndroidManifest.xml ファイルには次の要素が含まれています。

  • meta-data 要素を追加すると、アプリのコンパイルに使用された Google Play 開発者サービスのバージョンが埋め込まれます。

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    
  • API キーを指定する meta-data 要素を追加します。このチュートリアルのサンプルでは、API キーの値が文字列 google_maps_key にマッピングされています。 アプリを作成すると、Gradle で API キーがプロジェクトの gradle.properties ファイルからこの文字列値にコピーされます。

    <meta-data
      android:name="com.google.android.geo.API_KEY"
      android:value="@string/google_maps_key" />
    

    API キーがどのように文字列値にマッピングされているかを確認するには、アプリの build.gradle をご覧ください。これには、文字列 google_maps_key を Gradle のプロパティ GOOGLE_MAPS_API_KEY にマッピングする次の行が含まれています。

    resValue "string", "google_maps_key",
            (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "")
    

マニフェストの詳細な例を以下に示します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.polygons">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <!--
             The API key for Google Maps-based APIs.
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name="com.example.polygons.PolyActivity"
            android:label="@string/title_activity_maps">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

地図を追加する

Maps SDK for Android を使用して地図を表示します。

  1. アクティビティのレイアウト ファイル(activity_maps.xml)に <fragment> 要素を追加します。この要素では、地図のコンテナとして機能し、GoogleMap オブジェクトへのアクセス権を付与するよう SupportMapFragment を定義します。このチュートリアルでは、Android フレームワークの以前のバージョンとの下位互換性を確保するため、地図フラグメントの Android サポート ライブラリ バージョンを使用します。

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.polygons.PolyActivity" />
    
    
  2. アクティビティの onCreate() メソッドで、レイアウト ファイルをコンテンツ ビューとして設定します。FragmentManager.findFragmentById() を呼び出して、地図フラグメントに対するハンドルを取得します。次に、getMapAsync() を使用して、地図コールバックを登録します。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // Retrieve the content view that renders the map.
        setContentView(R.layout.activity_maps);
    
        // Get the SupportMapFragment and request notification when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(map);
        mapFragment.getMapAsync(this);
    }
    
  3. OnMapReadyCallback インターフェースを実装し、onMapReady() メソッドをオーバーライドします。GoogleMap オブジェクトが利用可能な場合は、API でこのコールバックが呼び出されるため、地図にオブジェクトを追加して、アプリに合わせて詳細にカスタマイズすることができます。

    public class PolyActivity extends AppCompatActivity
            implements
                    OnMapReadyCallback,
                    GoogleMap.OnPolylineClickListener,
                    GoogleMap.OnPolygonClickListener {
    
        // More code goes here, including the onCreate() method described above.
    
        @Override
        public void onMapReady(GoogleMap googleMap) {
    
            // Add polylines and polygons to the map. This section shows just
            // a single polyline. Read the rest of the tutorial to learn more.
            Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
                    .clickable(true)
                    .add(
                            new LatLng(-35.016, 143.321),
                            new LatLng(-34.747, 145.592),
                            new LatLng(-34.364, 147.891),
                            new LatLng(-33.501, 150.217),
                            new LatLng(-32.306, 149.248),
                            new LatLng(-32.491, 147.309)));
    
            // Position the map's camera near Alice Springs in the center of Australia,
            // and set the zoom factor so most of Australia shows on the screen.
            googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-23.684, 133.903), 4));
    
            // Set listeners for click events.
            googleMap.setOnPolylineClickListener(this);
            googleMap.setOnPolygonClickListener(this);
        }
    }
    

ポリラインを追加して地図にラインを引く

Polyline は、一連の線分のつながりです。ポリラインは、地図上の場所間のルートや経路などのつながりを表すのに役立ちます。

  1. PolylineOptions オブジェクトを作成して地点を追加します。 それぞれの地点は地図上の場所を表し、緯度と経度の値を含む LatLng オブジェクトで定義されます。以下のコードサンプルでは、6 つの地点をつなぐポリラインが作成されます。

  2. GoogleMap.addPolyline() を呼び出して、地図にポリラインを追加します。

    Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
            .clickable(true)
            .add(
                    new LatLng(-35.016, 143.321),
                    new LatLng(-34.747, 145.592),
                    new LatLng(-34.364, 147.891),
                    new LatLng(-33.501, 150.217),
                    new LatLng(-32.306, 149.248),
                    new LatLng(-32.491, 147.309)));
    

ポリラインでクリック イベントを処理する場合は、ポリラインの clickable オプションを true に設定します。イベントの詳細については、このチュートリアルの後半で説明します。

ポリラインを含む任意のデータを保存する

ポリラインやその他のジオメトリ オブジェクトを含む任意のデータ オブジェクトを保存できます。

  1. Polyline.setTag() を呼び出して、ポリラインを含むデータ オブジェクトを保存します。以下のコードでは、ポリラインのタイプを示す任意のタグ(A)を定義しています。

    Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
            .clickable(true)
            .add(
                    new LatLng(-35.016, 143.321),
                    new LatLng(-34.747, 145.592),
                    new LatLng(-34.364, 147.891),
                    new LatLng(-33.501, 150.217),
                    new LatLng(-32.306, 149.248),
                    new LatLng(-32.491, 147.309)));
    // Store a data object with the polyline, used here to indicate an arbitrary type.
    polyline1.setTag("A");
    
  2. 次のセクションに示すように、Polyline.getTag() を使用してデータを取得します。

ポリラインにカスタム スタイルを追加する

PolylineOptions オブジェクトで、さまざまなスタイルのプロパティを指定できます。スタイルのオプションには、ストロークの色と幅およびパターンのほか、ジョイントのタイプや、始点と終点のキャップなどがあります。特定のプロパティを指定しない場合は、API でそのプロパティのデフォルトの値が使用されます。

次のコードでは、ラインの終点にはラウンド キャップが適用され、始点のキャップはポリラインのタイプに応じて適用されます。この場合、タイプはポリラインのデータ オブジェクトに保存されている任意のプロパティとなります。サンプルでは、ストロークの幅と色や、ジョイント タイプも指定されています。

private static final int COLOR_BLACK_ARGB = 0xff000000;
private static final int POLYLINE_STROKE_WIDTH_PX = 12;

private void stylePolyline(Polyline polyline) {
    String type = "";
    // Get the data object stored with the polyline.
    if (polyline.getTag() != null) {
        type = polyline.getTag().toString();
    }

    switch (type) {
        // If no type is given, allow the API to use the default.
        case "A":
            // Use a custom bitmap as the cap at the start of the line.
            polyline.setStartCap(
                    new CustomCap(
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_arrow), 10));
            break;
        case "B":
            // Use a round cap at the start of the line.
            polyline.setStartCap(new RoundCap());
            break;
    }

    polyline.setEndCap(new RoundCap());
    polyline.setWidth(POLYLINE_STROKE_WIDTH_PX);
    polyline.setColor(COLOR_BLACK_ARGB);
    polyline.setJointType(JointType.ROUND);
}

上記のコードでは、タイプ A のポリラインの始点のキャップにカスタム ビットマップを指定しているほか、リファレンスのストロークの幅を 10 ピクセルに指定しています。API では、ビットマップがリファレンスのストロークの幅に基づいてスケーリングされます。リファレンスのストロークの幅を指定する際は、ビットマップ画像の作成時に使用した幅、つまり元の画像サイズでの幅を指定します。ヒント: 画像エディタで表示倍率を 100% に設定してビットマップ画像を開き、画像に適したライン ストロークの幅を検討します。

詳しくは、ラインキャップと、シェイプのカスタマイズに関するその他のオプションをご覧ください。

ポリラインでのクリック イベントを処理する

  1. Polyline.setClickable() を呼び出して、ポリラインをクリック可能にします(デフォルトでは、ポリラインはクリックできないため、ユーザーがポリラインをタップしてもアプリには通知されません)。

  2. OnPolylineClickListener インターフェースを実装し、GoogleMap.setOnPolylineClickListener() を呼び出して、地図にリスナーを設定します。

    public class PolyActivity extends AppCompatActivity
            implements
                    OnMapReadyCallback,
                    GoogleMap.OnPolylineClickListener,
                    GoogleMap.OnPolygonClickListener {
    
        @Override
        public void onMapReady(GoogleMap googleMap) {
            // Add a polyline to the map.
            Polyline polyline1 = googleMap.addPolyline((new PolylineOptions())
                    .clickable(true)
                    .add(new LatLng(-35.016, 143.321),
                            new LatLng(-34.747, 145.592),
                            new LatLng(-34.364, 147.891),
                            new LatLng(-33.501, 150.217),
                            new LatLng(-32.306, 149.248),
                            new LatLng(-32.491, 147.309)));
    
            // Set listeners for click events.
            googleMap.setOnPolylineClickListener(this);
            googleMap.setOnPolygonClickListener(this);
        }
    }
    
  3. onPolylineClick() コールバック メソッドをオーバーライドします。次の例では、ユーザーがポリラインをクリックするたびに、ラインのストローク パターンを実線または点線に切り替えます。

    private static final PatternItem DOT = new Dot();
    private static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);
    //
    // Create a stroke pattern of a gap followed by a dot.
    private static final List<PatternItem> PATTERN_POLYLINE_DOTTED = Arrays.asList(GAP, DOT);
    
    @Override
    public void onPolylineClick(Polyline polyline) {
        // Flip from solid stroke to dotted stroke pattern.
        if ((polyline.getPattern() == null) || (!polyline.getPattern().contains(DOT))) {
            polyline.setPattern(PATTERN_POLYLINE_DOTTED);
        } else {
            // The default pattern is a solid stroke.
            polyline.setPattern(null);
        }
    
        Toast.makeText(this, "Route type " + polyline.getTag().toString(),
                Toast.LENGTH_SHORT).show();
    }
    

エリアを表すポリゴンを地図に追加する

Polygon は、Polyline と同様に、指定されたシーケンスの一連の座標で構成されるシェイプです。違っているのは、ポリゴンが塗りつぶし可能な閉じたエリアを定義するのに対し、ポリラインは端が開いている点です。

  1. PolygonOptions オブジェクトを作成して地点を追加します。 それぞれの地点は地図上の場所を表し、緯度と経度の値を含む LatLng オブジェクトで定義されます。以下のコードサンプルでは、4 つの地点をつなぐポリゴンが作成されます。

  2. Polygon.setClickable() を呼び出して、ポリゴンをクリック可能にします(デフォルトでは、ポリゴンはクリックできず、ユーザーがポリゴンをタップしてもアプリには通知されません)。ポリゴンでのクリック イベントの処理は、このチュートリアルの前半で説明したポリラインでのイベントの処理と同様に行います。

  3. GoogleMap.addPolygon() を呼び出して、マップにポリゴンを追加します。

  4. Polygon.setTag() を呼び出して、ポリゴンを含むデータ オブジェクトを保存します。以下のコードでは、ポリゴンの任意のタイプ(alpha)を定義しています。

    Polygon polygon1 = googleMap.addPolygon(new PolygonOptions()
            .clickable(true)
            .add(
                    new LatLng(-27.457, 153.040),
                    new LatLng(-33.852, 151.211),
                    new LatLng(-37.813, 144.962),
                    new LatLng(-34.928, 138.599)));
    // Store a data object with the polygon, used here to indicate an arbitrary type.
    polygon1.setTag("alpha");
    

ポリゴンにカスタム スタイルを追加する

PolygonOptions オブジェクトではさまざまなスタイルのプロパティを指定できます。スタイルのオプションには、ストロークの色と幅およびパターンのほか、ストローク ジョイントのタイプや、塗りつぶしの色などがあります。特定のプロパティを指定しない場合は、API でそのプロパティのデフォルトの値が使用されます。

次のコードでは、ポリゴンのタイプに応じて特定の色とストローク パターンが適用されます。この場合、タイプはポリゴンのデータ オブジェクトに保存されている任意のプロパティとなります。

private static final int COLOR_BLACK_ARGB = 0xff000000;
private static final int COLOR_WHITE_ARGB = 0xffffffff;
private static final int COLOR_GREEN_ARGB = 0xff388E3C;
private static final int COLOR_PURPLE_ARGB = 0xff81C784;
private static final int COLOR_ORANGE_ARGB = 0xffF57F17;
private static final int COLOR_BLUE_ARGB = 0xffF9A825;

private static final int POLYGON_STROKE_WIDTH_PX = 8;
private static final int PATTERN_DASH_LENGTH_PX = 20;
private static final int PATTERN_GAP_LENGTH_PX = 20;
private static final PatternItem DOT = new Dot();
private static final PatternItem DASH = new Dash(PATTERN_DASH_LENGTH_PX);
private static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);

// Create a stroke pattern of a gap followed by a dash.
private static final List<PatternItem> PATTERN_POLYGON_ALPHA = Arrays.asList(GAP, DASH);

// Create a stroke pattern of a dot followed by a gap, a dash, and another gap.
private static final List<PatternItem> PATTERN_POLYGON_BETA =
        Arrays.asList(DOT, GAP, DASH, GAP);

private void stylePolygon(Polygon polygon) {
    String type = "";
    // Get the data object stored with the polygon.
    if (polygon.getTag() != null) {
        type = polygon.getTag().toString();
    }

    List<PatternItem> pattern = null;
    int strokeColor = COLOR_BLACK_ARGB;
    int fillColor = COLOR_WHITE_ARGB;

    switch (type) {
        // If no type is given, allow the API to use the default.
        case "alpha":
            // Apply a stroke pattern to render a dashed line, and define colors.
            pattern = PATTERN_POLYGON_ALPHA;
            strokeColor = COLOR_GREEN_ARGB;
            fillColor = COLOR_PURPLE_ARGB;
            break;
        case "beta":
            // Apply a stroke pattern to render a line of dots and dashes, and define colors.
            pattern = PATTERN_POLYGON_BETA;
            strokeColor = COLOR_ORANGE_ARGB;
            fillColor = COLOR_BLUE_ARGB;
            break;
    }

    polygon.setStrokePattern(pattern);
    polygon.setStrokeWidth(POLYGON_STROKE_WIDTH_PX);
    polygon.setStrokeColor(strokeColor);
    polygon.setFillColor(fillColor);
}

詳しくは、ストローク パターンと、シェイプのカスタマイズに関するその他のオプションをご覧ください。

次のステップ

オブジェクトについて学びます。円はポリゴンに似ていますが、円の形状を定義するプロパティを持ちます。