Polylines and Polygons to Represent Routes and Areas

This tutorial shows y'all how to add a Google map to your Android app, and use polylines and polygons to represent routes and areas on a map.

Follow the tutorial to build an Android app using the Maps SDK for Android. The recommended evolution surround is Android Studio.

Become the code

Clone or download the Google Maps Android API v2 Samples repository from GitHub.

View the Java version of the activeness:

                        // Copyright 2022 Google LLC // // Licensed under the Apache License, Version two.0 (the "License"); // you may non apply this file except in compliance with the License. // You may obtain a re-create of the License at // //      http://www.apache.org/licenses/LICENSE-2.0 // // Unless required past applicable police or agreed to in writing, software // distributed under the License is distributed on an "Equally IS" Basis, // WITHOUT WARRANTIES OR Conditions OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations nether the License.  package com.example.polygons;  import android.os.Package; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CustomCap; import com.google.android.gms.maps.model.Dash; import com.google.android.gms.maps.model.Dot; import com.google.android.gms.maps.model.Gap; import com.google.android.gms.maps.model.JointType; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.PatternItem; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.PolygonOptions; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; import com.google.android.gms.maps.model.RoundCap; import coffee.util.Arrays; import java.util.List;   /**  * An activity that displays a Google map with polylines to represent paths or routes,  * and polygons to represent areas.  */ public grade PolyActivity extends AppCompatActivity         implements                 OnMapReadyCallback,                 GoogleMap.OnPolylineClickListener,                 GoogleMap.OnPolygonClickListener {      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);          // Think 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(R.id.map);         mapFragment.getMapAsync(this);     }      /**      * Manipulates the map when it's available.      * The API invokes this callback when the map is gear up to be used.      * This is where we can add markers or lines, add listeners or move the camera.      * In this tutorial, we add polylines and polygons to correspond routes and areas on the map.      */     @Override     public void onMapReady(GoogleMap googleMap) {          // Add polylines to the map.         // Polylines are useful to testify a route or some other connectedness between points.         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 information object with the polyline, used here to signal an arbitrary blazon.         polyline1.setTag("A");         // Style the polyline.         stylePolyline(polyline1);          Polyline polyline2 = googleMap.addPolyline(new PolylineOptions()                 .clickable(true)                 .add together(                         new LatLng(-29.501, 119.700),                         new LatLng(-27.456, 119.672),                         new LatLng(-25.971, 124.187),                         new LatLng(-28.081, 126.555),                         new LatLng(-28.848, 124.229),                         new LatLng(-28.215, 123.938)));         polyline2.setTag("B");         stylePolyline(polyline2);          // Add together polygons to indicate areas on the map.         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 betoken an arbitrary type.         polygon1.setTag("alpha");         // Style the polygon.         stylePolygon(polygon1);          Polygon polygon2 = googleMap.addPolygon(new PolygonOptions()                 .clickable(true)                 .add(                         new LatLng(-31.673, 128.892),                         new LatLng(-31.952, 115.857),                         new LatLng(-17.785, 122.258),                         new LatLng(-12.4258, 130.7932)));         polygon2.setTag("beta");         stylePolygon(polygon2);          // Position the map's camera near Alice Springs in the center of Australia,         // and gear up the zoom cistron so well-nigh of Australia shows on the screen.         googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-23.684, 133.903), four));          // Prepare listeners for click events.         googleMap.setOnPolylineClickListener(this);         googleMap.setOnPolygonClickListener(this);     }      individual static final int COLOR_BLACK_ARGB = 0xff000000;     private static final int POLYLINE_STROKE_WIDTH_PX = 12;      /**      * Styles the polyline, based on type.      * @param polyline The polyline object that needs styling.      */     private void stylePolyline(Polyline polyline) {         Cord type = "";         // Go the information object stored with the polyline.         if (polyline.getTag() != null) {             type = polyline.getTag().toString();         }          switch (type) {             // If no blazon is given, allow the API to use the default.             case "A":                 // Use a custom bitmap equally 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);     }      individual static final int PATTERN_GAP_LENGTH_PX = 20;     private static terminal 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);      /**      * Listens for clicks on a polyline.      * @param polyline The polyline object that the user has clicked.      */     @Override     public void onPolylineClick(Polyline polyline) {         // Flip from solid stroke to dotted stroke pattern.         if ((polyline.getPattern() == nil) || (!polyline.getPattern().contains(DOT))) {             polyline.setPattern(PATTERN_POLYLINE_DOTTED);         } else {             // The default pattern is a solid stroke.             polyline.setPattern(zilch);         }          Toast.makeText(this, "Route type " + polyline.getTag().toString(),                 Toast.LENGTH_SHORT).bear witness();     }      /**      * Listens for clicks on a polygon.      * @param polygon The polygon object that the user has clicked.      */     @Override     public void onPolygonClick(Polygon polygon) {         // Flip the values of the blood-red, green, and blueish components of the polygon'south color.         int color = polygon.getStrokeColor() ^ 0x00ffffff;         polygon.setStrokeColor(colour);         color = polygon.getFillColor() ^ 0x00ffffff;         polygon.setFillColor(colour);          Toast.makeText(this, "Expanse type " + polygon.getTag().toString(), Toast.LENGTH_SHORT).show();     }      private static terminal int COLOR_WHITE_ARGB = 0xffffffff;     private static terminal int COLOR_DARK_GREEN_ARGB = 0xff388E3C;     individual static final int COLOR_LIGHT_GREEN_ARGB = 0xff81C784;     private static final int COLOR_DARK_ORANGE_ARGB = 0xffF57F17;     private static final int COLOR_LIGHT_ORANGE_ARGB = 0xffF9A825;      private static final int POLYGON_STROKE_WIDTH_PX = 8;     private static final int PATTERN_DASH_LENGTH_PX = 20;     individual static final PatternItem Dash = new Dash(PATTERN_DASH_LENGTH_PX);      // Create a stroke design of a gap followed past a nuance.     individual static final Listing<PatternItem> PATTERN_POLYGON_ALPHA = Arrays.asList(GAP, Dash);      // Create a stroke blueprint of a dot followed by a gap, a nuance, and another gap.     private static final List<PatternItem> PATTERN_POLYGON_BETA =         Arrays.asList(DOT, GAP, DASH, GAP);      /**      * Styles the polygon, based on blazon.      * @param polygon The polygon object that needs styling.      */     private void stylePolygon(Polygon polygon) {         String type = "";         // Get the data object stored with the polygon.         if (polygon.getTag() != zero) {             type = polygon.getTag().toString();         }          List<PatternItem> pattern = nada;         int strokeColor = COLOR_BLACK_ARGB;         int fillColor = COLOR_WHITE_ARGB;          switch (blazon) {             // If no type is given, let the API to use the default.             case "alpha":                 // Utilize a stroke design to return a dashed line, and define colors.                 pattern = PATTERN_POLYGON_ALPHA;                 strokeColor = COLOR_DARK_GREEN_ARGB;                 fillColor = COLOR_LIGHT_GREEN_ARGB;                 suspension;             case "beta":                 // Utilise a stroke pattern to return a line of dots and dashes, and define colors.                 pattern = PATTERN_POLYGON_BETA;                 strokeColor = COLOR_DARK_ORANGE_ARGB;                 fillColor = COLOR_LIGHT_ORANGE_ARGB;                 break;         }          polygon.setStrokePattern(design);         polygon.setStrokeWidth(POLYGON_STROKE_WIDTH_PX);         polygon.setStrokeColor(strokeColor);         polygon.setFillColor(fillColor);     } }                      

View the Kotlin version of the action:

                        // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // yous may not use this file except in compliance with the License. // You may obtain a copy of the License at // //      http://world wide web.apache.org/licenses/LICENSE-ii.0 // // Unless required by applicative law or agreed to in writing, software // distributed nether the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // Meet the License for the specific language governing permissions and // limitations under the License. package com.example.polygons  import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.GoogleMap.OnPolygonClickListener import com.google.android.gms.maps.GoogleMap.OnPolylineClickListener import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.CustomCap import com.google.android.gms.maps.model.Nuance import com.google.android.gms.maps.model.Dot import com.google.android.gms.maps.model.Gap import com.google.android.gms.maps.model.JointType import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.PatternItem import com.google.android.gms.maps.model.Polygon import com.google.android.gms.maps.model.PolygonOptions import com.google.android.gms.maps.model.Polyline import com.google.android.gms.maps.model.PolylineOptions import com.google.android.gms.maps.model.RoundCap  /**  * An action that displays a Google map with polylines to represent paths or routes,  * and polygons to represent areas.  */ class PolyActivity : AppCompatActivity(), OnMapReadyCallback, OnPolylineClickListener, OnPolygonClickListener {      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)          // Recall the content view that renders the map.         setContentView(R.layout.activity_maps)          // Become the SupportMapFragment and asking notification when the map is ready to be used.         val mapFragment = supportFragmentManager             .findFragmentById(R.id.map) as SupportMapFragment?         mapFragment?.getMapAsync(this)     }      /**      * Manipulates the map when it'southward available.      * The API invokes this callback when the map is ready to be used.      * This is where we tin can add markers or lines, add listeners or move the camera.      * In this tutorial, nosotros add polylines and polygons to represent routes and areas on the map.      */     override fun onMapReady(googleMap: GoogleMap) {          // Add polylines to the map.         // Polylines are useful to show a route or some other connection betwixt points.         val polyline1 = googleMap.addPolyline(PolylineOptions()             .clickable(true)             .add(                 LatLng(-35.016, 143.321),                 LatLng(-34.747, 145.592),                 LatLng(-34.364, 147.891),                 LatLng(-33.501, 150.217),                 LatLng(-32.306, 149.248),                 LatLng(-32.491, 147.309)))         // Store a information object with the polyline, used here to betoken an arbitrary type.         polyline1.tag = "A"         // Mode the polyline.         stylePolyline(polyline1)          val polyline2 = googleMap.addPolyline(PolylineOptions()             .clickable(true)             .add together(                 LatLng(-29.501, 119.700),                 LatLng(-27.456, 119.672),                 LatLng(-25.971, 124.187),                 LatLng(-28.081, 126.555),                 LatLng(-28.848, 124.229),                 LatLng(-28.215, 123.938)))         polyline2.tag = "B"         stylePolyline(polyline2)          // Add polygons to indicate areas on the map.         val polygon1 = googleMap.addPolygon(PolygonOptions()             .clickable(truthful)             .add together(                 LatLng(-27.457, 153.040),                 LatLng(-33.852, 151.211),                 LatLng(-37.813, 144.962),                 LatLng(-34.928, 138.599)))         // Store a data object with the polygon, used here to indicate an arbitrary blazon.         polygon1.tag = "alpha"         // Manner the polygon.         stylePolygon(polygon1)          val polygon2 = googleMap.addPolygon(PolygonOptions()             .clickable(truthful)             .add(                 LatLng(-31.673, 128.892),                 LatLng(-31.952, 115.857),                 LatLng(-17.785, 122.258),                 LatLng(-12.4258, 130.7932)))         polygon2.tag = "beta"         stylePolygon(polygon2)          // Position the map's camera near Alice Springs in the middle of Australia,         // and set the zoom factor then near of Australia shows on the screen.         googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(-23.684, 133.903), 4f))          // Set listeners for click events.         googleMap.setOnPolylineClickListener(this)         googleMap.setOnPolygonClickListener(this)     }      private val COLOR_BLACK_ARGB = -0x1000000     private val POLYLINE_STROKE_WIDTH_PX = 12      /**      * Styles the polyline, based on type.      * @param polyline The polyline object that needs styling.      */     private fun stylePolyline(polyline: Polyline) {         // Become the information object stored with the polyline.         val type = polyline.tag?.toString() ?: ""         when (type) {             "A" -> {                 // Utilize a custom bitmap as the cap at the start of the line.                 polyline.startCap = CustomCap(                     BitmapDescriptorFactory.fromResource(R.drawable.ic_arrow), 10f)             }             "B" -> {                // Apply a round cap at the commencement of the line.                 polyline.startCap = RoundCap()             }         }         polyline.endCap = RoundCap()         polyline.width = POLYLINE_STROKE_WIDTH_PX.toFloat()         polyline.colour = COLOR_BLACK_ARGB         polyline.jointType = JointType.Circular     }      individual val PATTERN_GAP_LENGTH_PX = twenty     individual val DOT: PatternItem = Dot()     private val GAP: PatternItem = Gap(PATTERN_GAP_LENGTH_PX.toFloat())      // Create a stroke pattern of a gap followed by a dot.     private val PATTERN_POLYLINE_DOTTED = listOf(GAP, DOT)      /**      * Listens for clicks on a polyline.      * @param polyline The polyline object that the user has clicked.      */     override fun onPolylineClick(polyline: Polyline) {         // Flip from solid stroke to dotted stroke design.         if (polyline.blueprint == nil || !polyline.pattern!!.contains(DOT)) {             polyline.pattern = PATTERN_POLYLINE_DOTTED         } else {             // The default pattern is a solid stroke.             polyline.pattern = nil         }         Toast.makeText(this, "Route type " + polyline.tag.toString(),             Toast.LENGTH_SHORT).show()     }      /**      * Listens for clicks on a polygon.      * @param polygon The polygon object that the user has clicked.      */     override fun onPolygonClick(polygon: Polygon) {         // Flip the values of the red, green, and blue components of the polygon'south colour.         var colour = polygon.strokeColor xor 0x00ffffff         polygon.strokeColor = color         color = polygon.fillColor xor 0x00ffffff         polygon.fillColor = color         Toast.makeText(this, "Area type ${polygon.tag?.toString()}", Toast.LENGTH_SHORT).show()     }      private val COLOR_WHITE_ARGB = -0x1     individual val COLOR_DARK_GREEN_ARGB = -0xc771c4     private val COLOR_LIGHT_GREEN_ARGB = -0x7e387c     private val COLOR_DARK_ORANGE_ARGB = -0xa80e9     private val COLOR_LIGHT_ORANGE_ARGB = -0x657db     private val POLYGON_STROKE_WIDTH_PX = eight     private val PATTERN_DASH_LENGTH_PX = 20      private val DASH: PatternItem = Dash(PATTERN_DASH_LENGTH_PX.toFloat())      // Create a stroke blueprint of a gap followed by a dash.     private val PATTERN_POLYGON_ALPHA = listOf(GAP, DASH)      // Create a stroke pattern of a dot followed by a gap, a nuance, and another gap.     private val PATTERN_POLYGON_BETA = listOf(DOT, GAP, Nuance, GAP)      /**      * Styles the polygon, based on type.      * @param polygon The polygon object that needs styling.      */     private fun stylePolygon(polygon: Polygon) {         // Get the information object stored with the polygon.         val type = polygon.tag?.toString() ?: ""         var blueprint: List<PatternItem>? = zero         var strokeColor = COLOR_BLACK_ARGB         var fillColor = COLOR_WHITE_ARGB         when (type) {             "alpha" -> {                 // Apply a stroke blueprint to render a dashed line, and define colors.                 pattern = PATTERN_POLYGON_ALPHA                 strokeColor = COLOR_DARK_GREEN_ARGB                 fillColor = COLOR_LIGHT_GREEN_ARGB             }             "beta" -> {                 // Apply a stroke design to render a line of dots and dashes, and define colors.                 pattern = PATTERN_POLYGON_BETA                 strokeColor = COLOR_DARK_ORANGE_ARGB                 fillColor = COLOR_LIGHT_ORANGE_ARGB             }         }         polygon.strokePattern = pattern         polygon.strokeWidth = POLYGON_STROKE_WIDTH_PX.toFloat()         polygon.strokeColor = strokeColor         polygon.fillColor = fillColor     } }                      

Gear up your evolution project

Follow these steps to create the tutorial project in Android Studio.

  1. Download and install Android Studio.
  2. Add together the Google Play services package to Android Studio.
  3. Clone or download the Google Maps Android API v2 Samples repository if you lot didn't do that when you lot started reading this tutorial.
  4. Import the tutorial project:

    • In Android Studio, select File > New > Import Projection.
    • Go to the location where you saved the Google Maps Android API v2 Samples repository after downloading it.
    • Find the Polygons project at this location:
      PATH-TO-SAVED-REPO/android-samples/tutorials/java/Polygons (Coffee) or
      PATH-TO-SAVED-REPO/android-samples/tutorials/kotlin/Polygons (Kotlin)
    • Select the projection directory, then click Open. Android Studio now builds your project, using the Gradle build tool.

Enable the necessary APIs and get an API key

To complete this tutorial, you lot need a Google Cloud project with the necessary APIs enabled and an API key that's authorized to use the Maps SDK for Android. For more details, see:

  • Set up your Google Cloud projection
  • Use an API key

Add the API key to your app

  1. Open your project'south local.properties file.
  2. Add the following string and and then replace YOUR_API_KEY with the value of your API key:

                            MAPS_API_KEY=YOUR_API_KEY                                                                                                    

    When you lot build your app, the Secrets Gradle Plugin for Android will re-create the API key and brand it bachelor as a build variable in the Android manifest, as explained below.

Build and run your app

To build and run the app:

  1. Connect an Android device to your computer. Follow the instructions to enable developer options on your Android device and configure your system to detect the device.

    Alternatively, you tin use the Android Virtual Device (AVD) Managing director to configure a virtual device. When choosing an emulator, make sure you pick an image that includes the Google APIs. For more than details, encounter Set Up an Android Studio Project .

  2. In Android Studio, click the Run menu option (or the play button icon). Cull a device equally prompted.

Android Studio invokes Gradle to build the app, and and so runs the app on the device or on the emulator.

You should meet a map with ii polygons overlaid on summit of Australia, similar to the image on this page.

Troubleshooting:

  • If y'all don't run across a map, check that you've obtained an API key and added it to the app, every bit described above. Check the log in Android Studio'south Android Monitor for error messages near the API key.
  • Use the Android Studio debugging tools to view logs and debug the app.

Sympathize the code

This part of the tutorial explains the most significant parts of the Polygons app, to help you empathise how to build a similar app.

Bank check your Android manifest

Note the following elements in your app's AndroidManifest.xml file:

  • Add together a meta-information chemical element to embed the version of Google Play services that the app was compiled with.

                            <meta-data     android:proper noun="com.google.android.gms.version"     android:value="@integer/google_play_services_version" />                                              
  • Add a meta-data element specifying your API key. The sample accompanying this tutorial maps the value for the API fundamental to a build variable matching the name of the key y'all defined earlier, MAPS_API_KEY. When you build your app, the Secrets Gradle Plugin for Android volition brand the keys in your local.backdrop file available as manifest build variables.

                            <meta-data   android:name="com.google.android.geo.API_KEY"   android:value="${MAPS_API_KEY}" />                                              

    In your build.gradle file, the following line passes your API fundamental to your Android manifest.

                                                      id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'                                              

Below is a consummate example of a manifest:

                    <?xml version="1.0" encoding="utf-8"?> <!--  Copyright 2022 Google LLC   Licensed under the Apache License, Version ii.0 (the "License");  you may not use this file except in compliance with the License.  You may obtain a copy of the License at        http://world wide web.apache.org/licenses/LICENSE-2.0   Unless required past applicable constabulary or agreed to in writing, software  distributed under the License is distributed on an "AS IS" Ground,  WITHOUT WARRANTIES OR CONDITIONS OF Any KIND, either express or implied.  See the License for the specific language governing permissions and  limitations under the License. -->  <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="@way/AppTheme">          <meta-information             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="${MAPS_API_KEY}" />          <activity             android:proper name="com.example.polygons.PolyActivity"             android:exported="true"             android:label="@string/title_activity_maps">             <intent-filter>                 <activity android:name="android.intent.action.Primary" />                 <category android:proper name="android.intent.category.LAUNCHER" />             </intent-filter>         </activity>     </application> </manifest>                  

Add a map

Display a map, using the Maps SDK for Android.

  1. Add a <fragment> element to your activity's layout file, activity_maps.xml. This element defines a SupportMapFragment to act as a container for the map and to provide admission to the GoogleMap object. The tutorial uses the Android back up library version of the map fragment, to ensure backward compatibility with earlier versions of the Android framework.

    <!--  Copyright 2022 Google LLC   Licensed nether the Apache License, Version 2.0 (the "License");  you may non use this file except in compliance with the License.  Y'all may obtain a copy of the License at        http://www.apache.org/licenses/LICENSE-2.0   Unless required by applicative law or agreed to in writing, software  distributed under the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR Weather OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and  limitations under the License. -->  <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.instance.polygons.PolyActivity" />                      
  2. In your activity'south onCreate() method, set the layout file as the content view. Get a handle to the map fragment by calling FragmentManager.findFragmentById(). Then use getMapAsync() to register for the map callback:

    Coffee

    @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);      // Remember the content view that renders the map.     setContentView(R.layout.activity_maps);      // Become the SupportMapFragment and asking notification when the map is fix to exist used.     SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()             .findFragmentById(R.id.map);     mapFragment.getMapAsync(this); }                          

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {     super.onCreate(savedInstanceState)      // Retrieve the content view that renders the map.     setContentView(R.layout.activity_maps)      // Go the SupportMapFragment and request notification when the map is ready to be used.     val mapFragment = supportFragmentManager         .findFragmentById(R.id.map) as SupportMapFragment?     mapFragment?.getMapAsync(this) }                          
  3. Implement the OnMapReadyCallback interface and override the onMapReady() method. The API invokes this callback when the GoogleMap object is available, so you can add objects to the map and further customize it for your app:

    Java

    public class PolyActivity extends AppCompatActivity         implements                 OnMapReadyCallback,                 GoogleMap.OnPolylineClickListener,                 GoogleMap.OnPolygonClickListener {      @Override     protected void onCreate(Parcel savedInstanceState) {         super.onCreate(savedInstanceState);          // Recollect the content view that renders the map.         setContentView(R.layout.activity_maps);          // Get the SupportMapFragment and request notification when the map is prepare to be used.         SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()                 .findFragmentById(R.id.map);         mapFragment.getMapAsync(this);     }      /**      * Manipulates the map when it's bachelor.      * The API invokes this callback when the map is fix to be used.      * This is where nosotros tin can add markers or lines, add listeners or motility the camera.      * In this tutorial, we add polylines and polygons to represent routes and areas on the map.      */     @Override     public void onMapReady(GoogleMap googleMap) {          // Add polylines to the map.         // Polylines are useful to testify a route or another connection betwixt points.         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 eye of Australia,         // and set the zoom factor so almost of Commonwealth of australia shows on the screen.         googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-23.684, 133.903), 4));          // Set up listeners for click events.         googleMap.setOnPolylineClickListener(this);         googleMap.setOnPolygonClickListener(this);     }                          

    Kotlin

    class PolyActivity : AppCompatActivity(), OnMapReadyCallback, OnPolylineClickListener, OnPolygonClickListener {      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)          // Recall 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.         val mapFragment = supportFragmentManager             .findFragmentById(R.id.map) equally SupportMapFragment?         mapFragment?.getMapAsync(this)     }      /**      * Manipulates the map when it's bachelor.      * The API invokes this callback when the map is set up to exist used.      * This is where we can add markers or lines, add listeners or move the camera.      * In this tutorial, we add polylines and polygons to represent routes and areas on the map.      */     override fun onMapReady(googleMap: GoogleMap) {          // Add polylines to the map.         // Polylines are useful to show a route or some other connection betwixt points.         val polyline1 = googleMap.addPolyline(PolylineOptions()             .clickable(true)             .add(                 LatLng(-35.016, 143.321),                 LatLng(-34.747, 145.592),                 LatLng(-34.364, 147.891),                 LatLng(-33.501, 150.217),                 LatLng(-32.306, 149.248),                 LatLng(-32.491, 147.309)))          // Position the map'south photographic camera about Alice Springs in the center of Australia,         // and set the zoom factor and then most of Australia shows on the screen.         googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(-23.684, 133.903), 4f))          // Fix listeners for click events.         googleMap.setOnPolylineClickListener(this)         googleMap.setOnPolygonClickListener(this)     }                          

Add a polyline to describe a line on the map

A Polyline is a serial of connected line segments. Polylines are useful to represent routes, paths, or other connections between locations on the map.

  1. Create a PolylineOptions object and add points to it. Each bespeak represents a location on the map, which you lot ascertain with a LatLng object containing latitude and longitude values. The code sample below creates a polyline with 6 points.

  2. Call GoogleMap.addPolyline() to add the polyline to the map.

    Java

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

    Kotlin

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

Gear up the polyline'due south clickable choice to true if you desire to handle click events on the polyline. In that location'southward more than well-nigh effect handling later in this tutorial.

Store arbitrary data with a polyline

You tin can shop arbitrary data objects with polylines and other geometry objects.

  1. Call Polyline.setTag() to shop a data object with the polyline. The code below defines an capricious tag (A) indicating a blazon of polyline.

    Coffee

    Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()     .clickable(truthful)     .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 information object with the polyline, used here to bespeak an arbitrary blazon. polyline1.setTag("A");                          

    Kotlin

    val polyline1 = googleMap.addPolyline(PolylineOptions() .clickable(true) .add(     LatLng(-35.016, 143.321),     LatLng(-34.747, 145.592),     LatLng(-34.364, 147.891),     LatLng(-33.501, 150.217),     LatLng(-32.306, 149.248),     LatLng(-32.491, 147.309))) // Store a data object with the polyline, used here to bespeak an arbitrary blazon. polyline1.tag = "A                          
  2. Remember the data using Polyline.getTag(), every bit the next section shows.

Add custom styling to your polyline

You can specify diverse styling properties in the PolylineOptions object. Styling options include the stroke colour, stroke width, stroke pattern, joint types, and start and terminate caps. If you don't specify a item belongings, the API uses a default for that belongings.

The following code applies a circular cap to the terminate of the line, and a different start cap depending on the polyline's blazon, where the type is an arbitrary property stored in the data object for the polyline. The sample likewise specifies a stroke width, stroke color, and joint type:

Java

private static final int COLOR_BLACK_ARGB = 0xff000000; private static final int POLYLINE_STROKE_WIDTH_PX = 12;  /**  * Styles the polyline, based on blazon.  * @param polyline The polyline object that needs styling.  */ private void stylePolyline(Polyline polyline) {     String blazon = "";     // Become the information object stored with the polyline.     if (polyline.getTag() != null) {         type = polyline.getTag().toString();     }      switch (type) {         // If no blazon is given, allow the API to use the default.         example "A":             // Apply a custom bitmap as the cap at the start of the line.             polyline.setStartCap(                     new CustomCap(                             BitmapDescriptorFactory.fromResource(R.drawable.ic_arrow), ten));             interruption;         case "B":             // Utilise a round cap at the start of the line.             polyline.setStartCap(new RoundCap());             interruption;     }      polyline.setEndCap(new RoundCap());     polyline.setWidth(POLYLINE_STROKE_WIDTH_PX);     polyline.setColor(COLOR_BLACK_ARGB);     polyline.setJointType(JointType.ROUND); }                      

Kotlin

private val COLOR_BLACK_ARGB = -0x1000000 private val POLYLINE_STROKE_WIDTH_PX = 12  /**  * Styles the polyline, based on blazon.  * @param polyline The polyline object that needs styling.  */ individual fun stylePolyline(polyline: Polyline) {     // Go the data object stored with the polyline.     val type = polyline.tag?.toString() ?: ""     when (type) {         "A" -> {             // Use a custom bitmap as the cap at the start of the line.             polyline.startCap = CustomCap(                 BitmapDescriptorFactory.fromResource(R.drawable.ic_arrow), 10f)         }         "B" -> {            // Use a round cap at the start of the line.             polyline.startCap = RoundCap()         }     }     polyline.endCap = RoundCap()     polyline.width = POLYLINE_STROKE_WIDTH_PX.toFloat()     polyline.color = COLOR_BLACK_ARGB     polyline.jointType = JointType.ROUND }                      

The higher up code specifies a custom bitmap for the offset cap of the type A polyline, and specifies a reference stroke width of 10 pixels. The API scales the bitmap based on the reference stroke width. When specifying the reference stroke width, supply the width that you lot used when designing the bitmap prototype, at the original dimension of the image. Hint: Open your bitmap epitome at 100% zoom in an image editor, and plot the desired width of the line stroke relative to the image.

Read more near line caps and other options for customizing shapes.

Handle click events on the polyline

  1. Make the polyline clickable by calling Polyline.setClickable(). (By default, polylines are not clickable and your app will not receive a notification when the user taps a polyline.)

  2. Implement the OnPolylineClickListener interface and telephone call GoogleMap.setOnPolylineClickListener() to set the listener on the map:

    Java

    public form PolyActivity extends AppCompatActivity         implements                 OnMapReadyCallback,                 GoogleMap.OnPolylineClickListener,                 GoogleMap.OnPolygonClickListener {      @Override     protected void onCreate(Packet savedInstanceState) {         super.onCreate(savedInstanceState);          // Retrieve the content view that renders the map.         setContentView(R.layout.activity_maps);          // Go the SupportMapFragment and request notification when the map is ready to be used.         SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()                 .findFragmentById(R.id.map);         mapFragment.getMapAsync(this);     }      /**      * Manipulates the map when it's available.      * The API invokes this callback when the map is ready to be used.      * This is where we can add markers or lines, add listeners or motion the camera.      * In this tutorial, we add polylines and polygons to stand for routes and areas on the map.      */     @Override     public void onMapReady(GoogleMap googleMap) {          // Add together polylines to the map.         // Polylines are useful to show a route or some other connection between points.         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 almost 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), four));          // Set listeners for click events.         googleMap.setOnPolylineClickListener(this);         googleMap.setOnPolygonClickListener(this);     }                          

    Kotlin

    form PolyActivity : AppCompatActivity(), OnMapReadyCallback, OnPolylineClickListener, OnPolygonClickListener {      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)          // Retrieve the content view that renders the map.         setContentView(R.layout.activity_maps)          // Get the SupportMapFragment and asking notification when the map is fix to exist used.         val mapFragment = supportFragmentManager             .findFragmentById(R.id.map) as SupportMapFragment?         mapFragment?.getMapAsync(this)     }      /**      * Manipulates the map when it's available.      * The API invokes this callback when the map is set to be used.      * This is where we can add markers or lines, add together listeners or move the camera.      * In this tutorial, nosotros add polylines and polygons to represent routes and areas on the map.      */     override fun onMapReady(googleMap: GoogleMap) {          // Add polylines to the map.         // Polylines are useful to show a route or some other connection betwixt points.         val polyline1 = googleMap.addPolyline(PolylineOptions()             .clickable(true)             .add(                 LatLng(-35.016, 143.321),                 LatLng(-34.747, 145.592),                 LatLng(-34.364, 147.891),                 LatLng(-33.501, 150.217),                 LatLng(-32.306, 149.248),                 LatLng(-32.491, 147.309)))          // Position the map's camera near Alice Springs in the center of Commonwealth of australia,         // and set the zoom factor and so nigh of Australia shows on the screen.         googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(-23.684, 133.903), 4f))          // Set listeners for click events.         googleMap.setOnPolylineClickListener(this)         googleMap.setOnPolygonClickListener(this)     }                          
  3. Override the onPolylineClick() callback method. The following example alternates the stroke pattern of the line between solid and dotted, each time the user clicks the polyline:

    Java

    private static last int PATTERN_GAP_LENGTH_PX = xx; private static final PatternItem DOT = new Dot(); private static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);  // Create a stroke blueprint of a gap followed past a dot. private static final Listing<PatternItem> PATTERN_POLYLINE_DOTTED = Arrays.asList(GAP, DOT);  /**  * Listens for clicks on a polyline.  * @param polyline The polyline object that the user has clicked.  */ @Override public void onPolylineClick(Polyline polyline) {     // Flip from solid stroke to dotted stroke pattern.     if ((polyline.getPattern() == nil) || (!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).prove(); }                          

    Kotlin

    individual val PATTERN_GAP_LENGTH_PX = twenty private val DOT: PatternItem = Dot() private val GAP: PatternItem = Gap(PATTERN_GAP_LENGTH_PX.toFloat())  // Create a stroke pattern of a gap followed past a dot. individual val PATTERN_POLYLINE_DOTTED = listOf(GAP, DOT)  /**  * Listens for clicks on a polyline.  * @param polyline The polyline object that the user has clicked.  */ override fun onPolylineClick(polyline: Polyline) {     // Flip from solid stroke to dotted stroke pattern.     if (polyline.pattern == null || !polyline.pattern!!.contains(DOT)) {         polyline.pattern = PATTERN_POLYLINE_DOTTED     } else {         // The default pattern is a solid stroke.         polyline.pattern = naught     }     Toast.makeText(this, "Route type " + polyline.tag.toString(),         Toast.LENGTH_SHORT).show() }                          

Add polygons to represent areas on the map

A Polygon is a shape consisting of a series of coordinates in an ordered sequence, similar to a Polyline. The difference is that polygon defines a airtight expanse with a fillable interior, while a polyline is open ended.

  1. Create a PolygonOptions object and add points to it. Each point represents a location on the map, which you ascertain with a LatLng object containing latitude and longitude values. The code sample below creates a polygon with 4 points.

  2. Make the polygon clickable by calling Polygon.setClickable(). (By default, polygons are not clickable and your app will not receive a notification when the user taps a polygon.) Handling polygon click events is similar to treatment the events on polylines, described before in this tutorial.

  3. Phone call GoogleMap.addPolygon() to add the polygon to the map.

  4. Call Polygon.setTag() to store a data object with the polygon. The code beneath defines an arbitrary type (alpha) for the polygon.

    Java

    // Add polygons to indicate areas on the map. 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 bespeak an arbitrary type. polygon1.setTag("alpha");                          

    Kotlin

    // Add polygons to point areas on the map. val polygon1 = googleMap.addPolygon(PolygonOptions()     .clickable(truthful)     .add(         LatLng(-27.457, 153.040),         LatLng(-33.852, 151.211),         LatLng(-37.813, 144.962),         LatLng(-34.928, 138.599))) // Shop a data object with the polygon, used here to indicate an arbitrary type. polygon1.tag = "alpha" // Style the polygon.                          

Add custom styling to your polygon

Y'all tin can specify a number of styling properties in the PolygonOptions object. Styling options include the stroke color, stroke width, stroke design, stroke joint types, and fill color. If you don't specify a item property, the API uses a default for that property.

The following code applies specific colors and stroke patterns depending on the polygon'due south type, where the blazon is an capricious property stored in the data object for the polygon:

Java

individual static terminal int COLOR_WHITE_ARGB = 0xffffffff; individual static final int COLOR_DARK_GREEN_ARGB = 0xff388E3C; private static final int COLOR_LIGHT_GREEN_ARGB = 0xff81C784; private static final int COLOR_DARK_ORANGE_ARGB = 0xffF57F17; private static concluding int COLOR_LIGHT_ORANGE_ARGB = 0xffF9A825;  individual static last int POLYGON_STROKE_WIDTH_PX = 8; private static terminal int PATTERN_DASH_LENGTH_PX = twenty; private static concluding PatternItem Dash = new Dash(PATTERN_DASH_LENGTH_PX);  // Create a stroke blueprint 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 nuance, and another gap. private static final List<PatternItem> PATTERN_POLYGON_BETA =     Arrays.asList(DOT, GAP, Dash, GAP);  /**  * Styles the polygon, based on type.  * @param polygon The polygon object that needs styling.  */ individual void stylePolygon(Polygon polygon) {     String type = "";     // Become the data object stored with the polygon.     if (polygon.getTag() != null) {         type = polygon.getTag().toString();     }      List<PatternItem> pattern = cipher;     int strokeColor = COLOR_BLACK_ARGB;     int fillColor = COLOR_WHITE_ARGB;      switch (blazon) {         // If no type is given, allow the API to apply the default.         case "blastoff":             // Apply a stroke blueprint to return a dashed line, and define colors.             pattern = PATTERN_POLYGON_ALPHA;             strokeColor = COLOR_DARK_GREEN_ARGB;             fillColor = COLOR_LIGHT_GREEN_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_DARK_ORANGE_ARGB;             fillColor = COLOR_LIGHT_ORANGE_ARGB;             break;     }      polygon.setStrokePattern(pattern);     polygon.setStrokeWidth(POLYGON_STROKE_WIDTH_PX);     polygon.setStrokeColor(strokeColor);     polygon.setFillColor(fillColor); }                      

Kotlin

private val COLOR_WHITE_ARGB = -0x1 private val COLOR_DARK_GREEN_ARGB = -0xc771c4 private val COLOR_LIGHT_GREEN_ARGB = -0x7e387c private val COLOR_DARK_ORANGE_ARGB = -0xa80e9 private val COLOR_LIGHT_ORANGE_ARGB = -0x657db private val POLYGON_STROKE_WIDTH_PX = 8 private val PATTERN_DASH_LENGTH_PX = 20  private val Dash: PatternItem = Nuance(PATTERN_DASH_LENGTH_PX.toFloat())  // Create a stroke pattern of a gap followed by a dash. individual val PATTERN_POLYGON_ALPHA = listOf(GAP, Dash)  // Create a stroke blueprint of a dot followed by a gap, a dash, and some other gap. private val PATTERN_POLYGON_BETA = listOf(DOT, GAP, Dash, GAP)  /**  * Styles the polygon, based on type.  * @param polygon The polygon object that needs styling.  */ individual fun stylePolygon(polygon: Polygon) {     // Get the data object stored with the polygon.     val blazon = polygon.tag?.toString() ?: ""     var pattern: List<PatternItem>? = cypher     var strokeColor = COLOR_BLACK_ARGB     var fillColor = COLOR_WHITE_ARGB     when (type) {         "alpha" -> {             // Apply a stroke pattern to render a dashed line, and define colors.             design = PATTERN_POLYGON_ALPHA             strokeColor = COLOR_DARK_GREEN_ARGB             fillColor = COLOR_LIGHT_GREEN_ARGB         }         "beta" -> {             // Employ a stroke pattern to render a line of dots and dashes, and define colors.             design = PATTERN_POLYGON_BETA             strokeColor = COLOR_DARK_ORANGE_ARGB             fillColor = COLOR_LIGHT_ORANGE_ARGB         }     }     polygon.strokePattern = blueprint     polygon.strokeWidth = POLYGON_STROKE_WIDTH_PX.toFloat()     polygon.strokeColor = strokeColor     polygon.fillColor = fillColor }                      

Read more about stroke patterns and other options for customizing shapes.

Next steps

Learn well-nigh the Circle object. Circles are similar to polygons just accept properties that reverberate the shape of a circle.