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

このチュートリアルでは、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 はプロジェクトの gradle.properties ファイルからこの文字列値に API キーをコピーします。

    <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> 要素を追加します。この要素は SupportMapFragment を定義して、マップのコンテナとして機能し、GoogleMap オブジェクトへのアクセス権を付与します。このチュートリアルでは、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() メソッドをオーバーライドします。API は、GoogleMap オブジェクトが利用可能になった際にこのコールバックを呼び出すため、マップにオブジェクトを追加し、それをアプリに合わせて詳細にカスタマイズすることができます。

    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);
    }
    

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

次のステップ

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