diff --git a/ApiDemos/java/app/build.gradle.kts b/ApiDemos/java/app/build.gradle.kts
index 2230fae8..ccb62802 100644
--- a/ApiDemos/java/app/build.gradle.kts
+++ b/ApiDemos/java/app/build.gradle.kts
@@ -58,8 +58,9 @@ dependencies {
implementation(libs.appcompat)
implementation(libs.recyclerview)
implementation(libs.volley)
- implementation(platform(libs.kotlinBom))
implementation(libs.playServicesMaps)
+ implementation(libs.material)
+ implementation(libs.activity)
// Tests
testImplementation(libs.junit)
diff --git a/ApiDemos/java/app/src/main/AndroidManifest.xml b/ApiDemos/java/app/src/main/AndroidManifest.xml
index 1f982433..229771d1 100644
--- a/ApiDemos/java/app/src/main/AndroidManifest.xml
+++ b/ApiDemos/java/app/src/main/AndroidManifest.xml
@@ -92,10 +92,12 @@ limitations under the License.
android:label="@string/circle_demo_label" />
selectedPlaceIds = new HashSet<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ EdgeToEdge.enable(this);
setContentView(R.layout.data_driven_boundaries_demo);
+ // [START_EXCLUDE silent]
+ if (getString(R.string.map_id).equals("DEMO_MAP_ID")) {
+ // This demo will not work if the map id is not set.
+ Toast.makeText(this, "Map ID is not set. See README for instructions.", Toast.LENGTH_LONG).show();
+ }
+ // [END_EXCLUDE]
+
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
if (mapFragment != null) {
mapFragment.getMapAsync(this);
}
- findViewById(R.id.button_hawaii).setOnClickListener(view -> centerMapOnLocation(HANA_HAWAII, 13.5f));
+ findViewById(R.id.button_hawaii).setOnClickListener(view -> centerMapOnLocation(HANA_HAWAII, 11f));
findViewById(R.id.button_us).setOnClickListener(view -> centerMapOnLocation(CENTER_US, 1f));
+
+ applyInsets(findViewById(R.id.map_container));
+
+ // [START_EXCLUDE silent]
+ setupBoundarySelectorButton();
+ // [END_EXCLUDE]
}
+ // [START_EXCLUDE silent]
+ private void setupBoundarySelectorButton() {
+ MaterialButton stylingTypeButton = findViewById(R.id.button_feature_type);
+ stylingTypeButton.setOnClickListener(v -> {
+ PopupMenu popupMenu = new PopupMenu(this, v);
+ MenuInflater inflater = popupMenu.getMenuInflater();
+ inflater.inflate(R.menu.boundary_types_menu, popupMenu.getMenu());
+
+ popupMenu.setOnMenuItemClickListener(this);
+
+ popupMenu.getMenu().findItem(R.id.boundary_type_locality).setChecked(localityEnabled);
+ popupMenu.getMenu().findItem(R.id.boundary_type_administrative_area_level_1).setChecked(adminAreaEnabled);
+ popupMenu.getMenu().findItem(R.id.boundary_type_country).setChecked(countryEnabled);
+ popupMenu.show();
+ });
+ }
+ // [END_EXCLUDE]
+
private void centerMapOnLocation(LatLng location, float zoomLevel) {
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, zoomLevel));
}
- @RequiresApi(Build.VERSION_CODES.O)
@Override
- public void onMapReady(GoogleMap googleMap) {
+ public void onMapReady(@NonNull GoogleMap googleMap) {
this.map = googleMap;
MapCapabilities capabilities = map.getMapCapabilities();
Log.d(TAG, "Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable());
- // Get the LOCALITY feature layer.
+ if (!capabilities.isDataDrivenStylingAvailable()) {
+ Toast.makeText(
+ this,
+ "Data-driven Styling is not available. See README.md for instructions.",
+ Toast.LENGTH_LONG
+ ).show();
+ }
+
+ // Gets the LOCALITY feature layer.
localityLayer = googleMap.getFeatureLayer(
new FeatureLayerOptions.Builder()
.featureType(FeatureType.LOCALITY)
.build()
);
- // Apply style factory function to LOCALITY layer.
- styleLocalityLayer();
-
- // Get the ADMINISTRATIVE_AREA_LEVEL_1 feature layer.
+ // Gets the ADMINISTRATIVE_AREA_LEVEL_1 feature layer.
areaLevel1Layer = googleMap.getFeatureLayer(
new FeatureLayerOptions.Builder()
.featureType(FeatureType.ADMINISTRATIVE_AREA_LEVEL_1)
.build()
);
- // Apply style factory function to ADMINISTRATIVE_AREA_LEVEL_1 layer.
- styleAreaLevel1Layer();
-
- // Get the COUNTRY feature layer.
+ // Gets the COUNTRY feature layer.
countryLayer = googleMap.getFeatureLayer(
new FeatureLayerOptions.Builder()
.featureType(FeatureType.COUNTRY)
.build()
);
-
- // Register the click event handler for the Country layer.
countryLayer.addOnFeatureClickListener(this);
- // Apply default style to all countries on load to enable clicking.
- styleCountryLayer();
+ centerMapOnLocation(HANA_HAWAII, 11f);
+
+ // Apply the current set of styles.
+ updateStyles();
}
- private void styleLocalityLayer() {
- // Create the style factory function.
- FeatureLayer.StyleFactory styleFactory = feature -> {
+ /**
+ * Updates the styles of the locality, area level 1, and country layers based on the current
+ * state of the `localityEnabled`, `adminAreaEnabled`, and `countryEnabled` flags.
+ *
+ * For each layer, if the corresponding flag is true, the layer's features will be styled using
+ * the layer specific style factory function.
+ */
+ private void updateStyles() {
+ if (localityLayer != null && areaLevel1Layer != null && countryLayer != null) {
+ localityLayer.setFeatureStyle(localityEnabled ? localityStyleFactory : null);
+ areaLevel1Layer.setFeatureStyle(adminAreaEnabled ? areaLevel1StyleFactory : null);
+ if (countryEnabled) {
+ countryLayer.setFeatureStyle(countryStyleFactory);
+ } else {
+ countryLayer.setFeatureStyle(null);
+ }
+ }
+ }
+
+ /**
+ * Creates a StyleFactory for a FeatureLayer that styles Hana, HI on its Place ID.
+ *
+ * This method defines a style factory that checks if a given feature is a {@link PlaceFeature}.
+ * and if that feature matches "ChIJ0zQtYiWsVHkRk8lRoB1RNPo" (Hana, HI) applies a specific style.
+ * Otherwise, it returns null, indicating no specific styling is applied.
+ *
+ * @return A {@link FeatureLayer.StyleFactory} instance that can be used to style features in a FeatureLayer.
+ * The factory returns a {@link FeatureStyle} for Hana, HI, and null for other features.
+ */
+ private static FeatureLayer.StyleFactory getLocalityStyleFactory() {
+ int purple = 0x810FCB;
+ // Define a style with purple fill at 50% opacity and
+ // solid purple border.
+ int fillColor = setAlphaValueOnColor(purple, 0.5f);
+ int strokeColor = setAlphaValueOnColor(purple, 1f);
+
+ return feature -> {
// Check if the feature is an instance of PlaceFeature,
// which contains a place ID.
if (feature instanceof PlaceFeature placeFeature) {
@@ -129,24 +219,26 @@ public class DataDrivenBoundariesActivity extends AppCompatActivity implements O
// Use FeatureStyle.Builder to configure the FeatureStyle object
// returned by the style factory function.
return new FeatureStyle.Builder()
- // Define a style with purple fill at 50% opacity and
- // solid purple border.
- .fillColor(0x80810FCB)
- .strokeColor(0xFF810FCB)
+ .fillColor(fillColor)
+ .strokeColor(strokeColor)
.build();
}
}
return null;
};
-
- // Apply the style factory function to the feature layer.
- if (localityLayer != null) {
- localityLayer.setFeatureStyle(styleFactory);
- }
}
- private void styleAreaLevel1Layer() {
- FeatureLayer.StyleFactory styleFactory = feature -> {
+ /**
+ * Creates a StyleFactory for area level 1 features (e.g., states, provinces).
+ *
+ * This factory provides a semi-transparent fill color for each area level 1 feature.
+ *
+ * @return A StyleFactory that can be used to style area level 1 features on a map.
+ */
+ private static FeatureLayer.StyleFactory getAreaLevel1StyleFactory() {
+ int alpha = (int) (255 * 0.25);
+
+ return feature -> {
if (feature instanceof PlaceFeature placeFeature) {
// Return a hueColor in the range [-299,299]. If the value is
@@ -157,64 +249,61 @@ public class DataDrivenBoundariesActivity extends AppCompatActivity implements O
}
return new FeatureStyle.Builder()
// Set the fill color for the state based on the hashed hue color.
- .fillColor(Color.HSVToColor(150, new float[]{hueColor, 1f, 1f}))
+ .fillColor(Color.HSVToColor(alpha, new float[]{hueColor, 1f, 1f}))
.build();
}
return null;
};
-
- // Apply the style factory function to the feature layer.
- if (areaLevel1Layer != null) {
- areaLevel1Layer.setFeatureStyle(styleFactory);
- }
}
- // Set default fill and border for all countries to ensure that they respond
- // to click events.
- @RequiresApi(Build.VERSION_CODES.O)
- private void styleCountryLayer() {
- FeatureLayer.StyleFactory styleFactory = feature -> new FeatureStyle.Builder()
- // Set the fill color for the country as white with a 10% opacity.
- // This requires minApi 26
- .fillColor(Color.argb(0.1f, 0f, 0f, 0f))
- // Set border color to solid black.
- .strokeColor(Color.BLACK)
- .build();
-
- // Apply the style factory function to the country feature layer.
- if (countryLayer != null) {
- countryLayer.setFeatureStyle(styleFactory);
- }
+ /**
+ * Creates a StyleFactory for styling country features on a FeatureLayer highlighting selected
+ * countries. Selection is determined via the selectedPlaceIds set.
+ *
+ * *Note:* If the set of selected countries changes, this function must be called to update the
+ * styling.
+ *
+ * @return A FeatureLayer.StyleFactory that can be used to style country features.
+ */
+ private FeatureLayer.StyleFactory getCountryStyleFactory() {
+ int defaultFillColor = setAlphaValueOnColor(Color.BLACK, 0.1f);
+ int selectedFillColor = setAlphaValueOnColor(Color.RED, 0.33f);
+ return feature -> {
+ if (feature instanceof PlaceFeature) {
+ int fillColor = selectedPlaceIds.contains(((PlaceFeature) feature).getPlaceId()) ? selectedFillColor : defaultFillColor;
+ FeatureStyle.Builder build = new FeatureStyle.Builder();
+ return build.fillColor(fillColor).strokeColor(Color.BLACK).build();
+ }
+ return null;
+ };
}
- // Define the click event handler.
+ /**
+ * Called when a feature is clicked on the map. It is only applied to the country layer.
+ *
+ * Each time a country is clicked, its place ID is added to the selectedPlaceIds set or removed
+ * if it was already present. Each time the set is
+ *
+ */
@Override
- public void onFeatureClick(FeatureClickEvent event) {
+ public void onFeatureClick(@NonNull FeatureClickEvent event) {
// Get the list of features affected by the click using
// getPlaceIds() defined below.
- List selectedPlaceIds = getPlaceIds(event.getFeatures());
- if (!selectedPlaceIds.isEmpty()) {
- FeatureLayer.StyleFactory styleFactory = feature -> {
- // Use PlaceFeature to get the placeID of the country.
- if (feature instanceof PlaceFeature) {
- if (selectedPlaceIds.contains(((PlaceFeature) feature).getPlaceId())) {
- return new FeatureStyle.Builder()
- // Set the fill color to red.
- .fillColor(Color.RED)
- .build();
- }
- }
- return null;
- };
+ List newSelectedPlaceIds = getPlaceIds(event.getFeatures());
- // Apply the style factory function to the feature layer.
- if (countryLayer != null) {
- countryLayer.setFeatureStyle(styleFactory);
+ for (String placeId : newSelectedPlaceIds) {
+ if (selectedPlaceIds.contains(placeId)) {
+ selectedPlaceIds.remove(placeId);
+ } else {
+ selectedPlaceIds.add(placeId);
}
}
+
+ // Reset the feature styling
+ countryLayer.setFeatureStyle(countryStyleFactory);
}
- // Get a List of place IDs from the FeatureClickEvent object.
+ // Gets a List of place IDs from the FeatureClickEvent object.
private List getPlaceIds(List features) {
List placeIds = new ArrayList<>();
for (Feature feature : features) {
@@ -224,5 +313,59 @@ public class DataDrivenBoundariesActivity extends AppCompatActivity implements O
}
return placeIds;
}
+
+ private static int setAlphaValueOnColor(int color, float alpha) {
+ return (color & 0x00ffffff) | (round(alpha * 255) << 24);
+ }
+
+ /**
+ * Applies insets to the container view to properly handle window insets.
+ *
+ * @param container the container view to apply insets to
+ */
+ private static void applyInsets(View container) {
+ ViewCompat.setOnApplyWindowInsetsListener(container,
+ (view, insets) -> {
+ Insets innerPadding = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
+ view.setPadding(innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom);
+ return insets;
+ }
+ );
+ }
+
+ /**
+ * Handles the click events for menu items in the boundary type selection menu.
+ * This method is called when a user selects a boundary type (locality, administrative area, or country) from the menu.
+ * It toggles the checked state of the selected menu item and updates the corresponding boolean flags (localityEnabled, adminAreaEnabled, countryEnabled).
+ * Finally, it calls the {@link #updateStyles()} method to reflect the changes in the map's display.
+ *
+ * @param item The MenuItem that was clicked.
+ * @return True if the event was handled, false otherwise. In this case it always return true if one of the correct items was selected.
+ */ // [START_EXCLUDE silent]
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ Log.d(TAG, "onMenuItemClick: " + item.getItemId());
+ int id = item.getItemId();
+ boolean result = false;
+
+ if (id == R.id.boundary_type_locality) {
+ item.setChecked(!item.isChecked());
+ localityEnabled = item.isChecked();
+ result = true;
+ } else if (id == R.id.boundary_type_administrative_area_level_1) {
+ item.setChecked(!item.isChecked());
+ adminAreaEnabled = item.isChecked();
+ result = true;
+ } else if (id == R.id.boundary_type_country) {
+ item.setChecked(!item.isChecked());
+ countryEnabled = item.isChecked();
+ result = true;
+ }
+
+ updateStyles();
+
+ return result;
+ }
+ // [END_EXCLUDE]
}
// [END maps_android_data_driven_styling_boundaries]
\ No newline at end of file
diff --git a/ApiDemos/java/app/src/main/java/com/example/mapdemo/DataDrivenDatasetStylingActivity.java b/ApiDemos/java/app/src/main/java/com/example/mapdemo/DataDrivenDatasetStylingActivity.java
index f5f0f2c4..89c57194 100644
--- a/ApiDemos/java/app/src/main/java/com/example/mapdemo/DataDrivenDatasetStylingActivity.java
+++ b/ApiDemos/java/app/src/main/java/com/example/mapdemo/DataDrivenDatasetStylingActivity.java
@@ -16,12 +16,17 @@ package com.example.mapdemo;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
+import android.view.View;
import android.widget.Button;
import android.widget.Toast;
+import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.ColorUtils;
+import androidx.core.graphics.Insets;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
@@ -54,6 +59,7 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
String label,
String datasetId,
LatLng location,
+ float zoomLevel,
DataDrivenDatasetStylingActivity.DataSet.StylingCallback callback) {
public interface StylingCallback {
void styleDatasetLayer();
@@ -81,9 +87,9 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
* Note: We have use the secrets plugin to allow us to configure the Dataset IDs in our secrets.properties file.
*/
private final DataSet[] dataSets = new DataSet[] {
- new DataSet("Boulder", BuildConfig.BOULDER_DATASET_ID, new LatLng(40.0150, -105.2705), this::styleBoulderDatasetLayer),
- new DataSet("New York", BuildConfig.NEW_YORK_DATASET_ID, new LatLng(40.786244, -73.962684), this::styleNYCDatasetLayer),
- new DataSet("Kyoto", BuildConfig.KYOTO_DATASET_ID, new LatLng(35.005081, 135.764385), this::styleKyotoDatasetsLayer),
+ new DataSet("Boulder", BuildConfig.BOULDER_DATASET_ID, new LatLng(40.0150, -105.2705), 11f, this::styleBoulderDatasetLayer),
+ new DataSet("New York", BuildConfig.NEW_YORK_DATASET_ID, new LatLng(40.786244, -73.962684), 14f, this::styleNYCDatasetLayer),
+ new DataSet("Kyoto", BuildConfig.KYOTO_DATASET_ID, new LatLng(35.005081, 135.764385), 13.5f, this::styleKyotoDatasetsLayer),
};
private DataSet findDataSetByLabel(String label) {
@@ -95,7 +101,6 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
return null; // Return null if no match is found
}
- private static final float ZOOM_LEVEL = 13.5f;
private static final String TAG = DataDrivenDatasetStylingActivity.class.getName();
private static FeatureLayer datasetLayer = null;
private GoogleMap map;
@@ -104,8 +109,16 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ EdgeToEdge.enable(this);
setContentView(R.layout.data_driven_styling_demo);
+ // [START_EXCLUDE silent]
+ if (getString(R.string.map_id).equals("DEMO_MAP_ID")) {
+ // This demo will not work if the map id is not set.
+ Toast.makeText(this, "Map ID is not set. See README for instructions.", Toast.LENGTH_LONG).show();
+ }
+ // [END_EXCLUDE]
+
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
if (mapFragment != null) {
mapFragment.getMapAsync(this);
@@ -115,6 +128,18 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
for (int buttonId : buttonIds) {
findViewById(buttonId).setOnClickListener(view -> switchDataSet(((Button) view).getText().toString()));
}
+
+ applyInsets(findViewById(R.id.map_container));
+ }
+
+ private static void applyInsets(View container) {
+ ViewCompat.setOnApplyWindowInsetsListener(container,
+ (view, insets) -> {
+ Insets innerPadding = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
+ view.setPadding(innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom);
+ return insets;
+ }
+ );
}
/**
@@ -142,7 +167,7 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
.build()
);
dataSet.callback.styleDatasetLayer();
- centerMapOnLocation(dataSet.location());
+ centerMapOnLocation(dataSet.location(), dataSet.zoomLevel());
}
}
@@ -152,6 +177,13 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
MapCapabilities capabilities = map.getMapCapabilities();
Log.d(TAG, "Data-driven Styling is available: " + capabilities.isDataDrivenStylingAvailable());
+ if (!capabilities.isDataDrivenStylingAvailable()) {
+ Toast.makeText(
+ this,
+ "Data-driven Styling is not available. See README.md for instructions.",
+ Toast.LENGTH_LONG
+ ).show();
+ }
// Switch to the default dataset which must happen before adding the feature click listener
switchDataSet("Boulder");
@@ -270,8 +302,8 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
// Create the style factory function.
FeatureLayer.StyleFactory styleFactory = feature -> {
// Set default colors to yellow and point radius to 8.
- int fillColor = Color.GREEN;
- int strokeColor = Color.YELLOW;
+ int fillColor;
+ int strokeColor;
float pointRadius = 8F;
float strokeWidth = 3F;
@@ -323,8 +355,8 @@ public class DataDrivenDatasetStylingActivity extends AppCompatActivity implemen
}
- private void centerMapOnLocation(LatLng location) {
- map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, ZOOM_LEVEL));
+ private void centerMapOnLocation(LatLng location, float zoomLevel) {
+ map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, zoomLevel));
}
@Override
diff --git a/ApiDemos/java/app/src/main/res/drawable/baseline_arrow_drop_down_24.xml b/ApiDemos/java/app/src/main/res/drawable/baseline_arrow_drop_down_24.xml
new file mode 100644
index 00000000..e830b0ff
--- /dev/null
+++ b/ApiDemos/java/app/src/main/res/drawable/baseline_arrow_drop_down_24.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/ApiDemos/java/app/src/main/res/layout/data_driven_boundaries_demo.xml b/ApiDemos/java/app/src/main/res/layout/data_driven_boundaries_demo.xml
index 04780ce9..74797f61 100644
--- a/ApiDemos/java/app/src/main/res/layout/data_driven_boundaries_demo.xml
+++ b/ApiDemos/java/app/src/main/res/layout/data_driven_boundaries_demo.xml
@@ -14,18 +14,38 @@
limitations under the License.
-->
-
-
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
+ >
+
+
+
+ class="com.google.android.gms.maps.SupportMapFragment"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/top_bar" />
-
-
-
-
\ No newline at end of file
+
diff --git a/ApiDemos/java/app/src/main/res/layout/data_driven_styling_demo.xml b/ApiDemos/java/app/src/main/res/layout/data_driven_styling_demo.xml
index 4deccd15..26d7a546 100644
--- a/ApiDemos/java/app/src/main/res/layout/data_driven_styling_demo.xml
+++ b/ApiDemos/java/app/src/main/res/layout/data_driven_styling_demo.xml
@@ -14,46 +14,68 @@
limitations under the License.
-->
-
-
+
+
+
+ class="com.google.android.gms.maps.SupportMapFragment"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/top_bar" />
-
+ android:padding="16dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/top_bar">
-
+ android:layout_margin="4dp"
+ android:text="@string/boulder" />
-
+ android:layout_margin="4dp"
+ android:text="@string/new_york" />
-
+ android:layout_margin="4dp"
+ android:text="@string/kyoto" />
+
-
-
\ No newline at end of file
+
diff --git a/ApiDemos/java/app/src/main/res/menu/boundary_types_menu.xml b/ApiDemos/java/app/src/main/res/menu/boundary_types_menu.xml
new file mode 100644
index 00000000..32df38f7
--- /dev/null
+++ b/ApiDemos/java/app/src/main/res/menu/boundary_types_menu.xml
@@ -0,0 +1,46 @@
+
+
+
diff --git a/ApiDemos/java/app/src/main/res/values/strings.xml b/ApiDemos/java/app/src/main/res/values/strings.xml
index a3417ad7..97febe45 100755
--- a/ApiDemos/java/app/src/main/res/values/strings.xml
+++ b/ApiDemos/java/app/src/main/res/values/strings.xml
@@ -301,4 +301,17 @@
Data Driven Boundaries DemoDemonstrates how to use Data Driven styling for boundaries.
+
+
+ Kyoto
+ New York
+ Boulder
+
+
+ Hawaii
+ US
+ Locality
+ Administrative Area Level 1
+ Country
+ Boundary
diff --git a/ApiDemos/java/app/src/main/res/values/styles.xml b/ApiDemos/java/app/src/main/res/values/styles.xml
index d1062b3d..fa66395b 100644
--- a/ApiDemos/java/app/src/main/res/values/styles.xml
+++ b/ApiDemos/java/app/src/main/res/values/styles.xml
@@ -23,4 +23,9 @@
@color/colorPrimaryDark@color/colorAccent
+
+
+
diff --git a/ApiDemos/java/gradle/libs.versions.toml b/ApiDemos/java/gradle/libs.versions.toml
index 06c84411..2ae50057 100644
--- a/ApiDemos/java/gradle/libs.versions.toml
+++ b/ApiDemos/java/gradle/libs.versions.toml
@@ -1,20 +1,21 @@
[versions]
+activity = "1.10.0"
+androidxJunit = "1.2.1"
appcompat = "1.7.0"
+espresso = "3.6.1"
+junit = "4.13.2"
+material = "1.12.0"
+playServicesMaps = "19.0.0"
recyclerview = "1.4.0"
volley = "1.2.1"
-kotlinBom = "2.0.21"
-playServicesMaps = "19.0.0"
-junit = "4.13.2"
-androidxJunit = "1.2.1"
-espresso = "3.6.1"
-
[libraries]
-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
-volley = { group = "com.android.volley", name = "volley", version.ref = "volley" }
-kotlinBom = { group = "org.jetbrains.kotlin", name = "kotlin-bom", version.ref = "kotlinBom" }
-playServicesMaps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
-junit = { group = "junit", name = "junit", version.ref = "junit" }
+activity = { module = "androidx.activity:activity", version.ref = "activity" }
androidxJunit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxJunit" }
-espressoCore = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
\ No newline at end of file
+appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+espressoCore = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+playServicesMaps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
+recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
+volley = { group = "com.android.volley", name = "volley", version.ref = "volley" }
\ No newline at end of file
diff --git a/ApiDemos/kotlin/app/src/main/res/layout/data_driven_styling_demo.xml b/ApiDemos/kotlin/app/src/main/res/layout/data_driven_styling_demo.xml
index ecf83903..a07c7686 100644
--- a/ApiDemos/kotlin/app/src/main/res/layout/data_driven_styling_demo.xml
+++ b/ApiDemos/kotlin/app/src/main/res/layout/data_driven_styling_demo.xml
@@ -28,7 +28,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
- app:title="@string/app_name"
+ app:title="@string/data_driven_styling_label"
app:titleTextColor="?attr/colorOnPrimary"
style="@style/Widget.MaterialComponents.Toolbar.Primary"
/>
diff --git a/ApiDemos/resources/README.md b/ApiDemos/resources/README.md
index 2528752b..4b75f4c8 100644
--- a/ApiDemos/resources/README.md
+++ b/ApiDemos/resources/README.md
@@ -10,110 +10,43 @@ polygons) based on the data associated with those features.
* **`boulder_polylines.geojson`:** This GeoJSON file contains data about trails in Boulder,
Colorado. Each feature in the file represents a trail, and the geometry is likely a polyline (a
- series of connected points). The file might also include attributes like trail name, difficulty,
+ series of connected points). The file also includes attributes like trail name, difficulty,
and length. This data can be used to create a map where trails are displayed as lines, and the
appearance of the lines (color, thickness, pattern) can be customized based on the trail's
attributes.
* **`kyoto_polygons.geojson`:** This GeoJSON file contains data about temples in Kyoto, Japan. Each
- feature in the file represents a temple, and the geometry is likely a polygon (an enclosed area).
- The file might also include attributes like temple name, founding date, and architectural style.
- This data can be used to create a map where temples are displayed as polygons, and the appearance
- of the polygons (fill color, border color) can be customized based on the temple's attributes."
+ feature in the file represents a temple, and the geometry is a polygon (an enclosed area).
**Uploading Data to Google Cloud Console and Using it with Google Maps:**
To use this data with data-driven styling in Google Maps, you'll need to upload it to the Google
Cloud Console and create a dataset. Here's a general outline of the process:
-1. **Go to the Google Cloud Console:** Open the Google Cloud Console in your web browser.
+## 1. Create a Map ID
+To create a new map ID, follow the steps in [Create a map ID](https://developers.google.com/maps/documentation/get-map-id#create-a-map-id).
+Make sure to set the **Map type** to **Android**.
-2. **Create a Project (If Needed):** If you don't already have a project, create one.
+## 2. Create a New Map Style
+Follow the instructions in [Manage map styles](https://developers.google.com/maps/documentation/android-sdk/cloud-customization/map-styles) to create a new style and [associate it with the map ID you just created](https://developers.google.com/maps/documentation/android-sdk/cloud-customization/map-styles#associate-style-with-map-id).
-3. **Enable the Maps Platform:** Make sure the Maps Platform is enabled for your project.
+## 3. Upload a Dataset
+To include data-driven styling in your map:
-4. **Go to the "Datasets" page:** In the Cloud Console, navigate to the "Datasets" page (you can
- search for it).
+1. Upload the dataset on the [Google Maps Platform Datasets](https://console.cloud.google.com/google/maps-apis/datasets) page.
+2. Confirm that the dataset upload is successful (sometimes there can be issues due to an invalid structure).
-5. **Create a Dataset:** Click "Create Dataset" and choose the appropriate type based on your data (
- e.g., "Point dataset" for `new_york_points.csv`, "Polyline dataset" for
- `boulder_polylines.geojson`, "Polygon dataset" for `kyoto_polygons.geojson`).
+## 4. Link the Dataset to the Map Style
+To enable data-driven styling:
-6. **Upload Your Data:** Follow the instructions to upload your data file. You might need to specify
- the data format (CSV or GeoJSON) and how to interpret the columns (e.g., which column contains
- latitude and longitude).
+1. Open your dataset in the [Google Maps Platform Datasets](https://console.cloud.google.com/google/maps-apis/datasets) page.
+2. Click on the **Preview** of the dataset.
+3. Associate the dataset with one of the previously created styles
-7. **Create a Dataset ID:** Once the data is uploaded, you'll get a Dataset ID. This is a unique
- identifier for your dataset.
-
-8. **Use the Dataset ID in Your Code:** In your Android code, when you create a
- `FeatureLayerOptions` object, use the `datasetId()` method to set the Dataset ID. This will link
- your map layer to the dataset you uploaded.
-
-9. **Apply Data-Driven Styling:** Use the `StyleFactory` to define how to style the features in your
- layer based on their attributes. The `StyleFactory` provides access to the feature's properties,
- which you can use to determine the appropriate styling.
-
-**Important Notes:**
-
-* **Data Preparation:** Make sure your data is properly formatted (CSV or GeoJSON) and that it
- includes the necessary columns (latitude, longitude, and any attributes you want to use for
- styling).
-* **Dataset Types:** Choose the correct dataset type when creating the dataset in the Cloud Console.
- This will ensure that the data is interpreted correctly.
-* **Dataset IDs:** Keep track of your Dataset IDs, as you'll need them to link your map layers to
- the correct datasets.
-* **Styling:** Data-driven styling is very powerful. You can create complex and dynamic map styles
- based on your data. Refer to the Google Maps documentation for more information and examples.
-
-By following these steps, you can upload your data to the Google Cloud Console, create datasets, and
-use those datasets to create beautiful and informative maps with data-driven styling in your Android
-application.
-
-
-
-## Using Dataset Styles in Android
-
-This guide explains how to create and apply dataset styles in Android. You'll learn how to create a map style, associate it with a map ID, upload datasets, and link the datasets to the map style to enable data-driven styling.
-
-### Sample Datasets
-
-This directory contains sample datasets for demonstrating data-driven styling:
-
-* **`new_york_points.csv`:** This CSV file contains data about squirrel sightings in New York City. Each row represents a sighting, and the columns likely include information like location (latitude and longitude), date, and other details about the squirrel (e.g., color, size). This data can be used to create a map where each squirrel sighting is represented by a point, and the appearance of the point (color, icon) can be customized based on the squirrel's attributes.
-
-* **`boulder_polylines.geojson`:** This GeoJSON file contains data about trails in Boulder, Colorado. Each feature in the file represents a trail, and the geometry is likely a polyline (a series of connected points). The file might also include attributes like trail name, difficulty, and length. This data can be used to create a map where trails are displayed as lines, and the appearance of the lines (color, thickness, pattern) can be customized based on the trail's attributes.
-
-* **`kyoto_polygons.geojson`:** This GeoJSON file contains data about temples in Kyoto, Japan. Each feature in the file represents a temple, and the geometry is likely a polygon (an enclosed area). The file might also include attributes like temple name, founding date, and architectural style. This data can be used to create a map where temples are displayed as polygons, and the appearance of the polygons (fill color, border color) can be customized based on the temple's attributes.
-
-### Steps to Enable Data-Driven Styling
-
-1. **Create a Map ID:**
-
- * Follow the steps in [Create a map ID](https://developers.google.com/maps/documentation/get-map-id#create-a-map-id). Make sure to set the **Map type** to **Android**.
-
-2. **Create a New Map Style:**
-
- * Follow the instructions in [Manage map styles](https://developers.google.com/maps/documentation/android-sdk/cloud-customization/map-styles) to create a new style.
- * [Associate the new style with the map ID you just created](https://developers.google.com/maps/documentation/android-sdk/cloud-customization/map-styles#associate-style-with-map-id).
-
-3. **Upload a Dataset:**
-
- * Go to the [Google Maps Platform Datasets](https://console.cloud.google.com/google/maps-apis/datasets) page in the Google Cloud Console.
- * Click "Create Dataset" and choose the appropriate type based on your data (e.g., "Point dataset" for `new_york_points.csv`, "Polyline dataset" for `boulder_polylines.geojson`, "Polygon dataset" for `kyoto_polygons.geojson`).
- * Upload your data file, specifying the data format (CSV or GeoJSON) and how to interpret the columns.
- * Confirm that the dataset upload is successful.
-
-4. **Link the Dataset to the Map Style:**
-
- * On the [Datasets](https://console.cloud.google.com/google/maps-apis/datasets) page, click on the **Preview** of your dataset.
- * Associate the dataset with one of the map styles you created.
-
-**Important Notes:**
-
-* **Data Preparation:** Ensure your data is properly formatted (CSV or GeoJSON) and includes the necessary columns (latitude, longitude, and any attributes you want to use for styling).
-* **Dataset Types:** Choose the correct dataset type when creating the dataset.
-* **Dataset IDs:** You'll need the Dataset ID to link your map layers to the correct datasets in your Android code.
-* **Styling:** Use the `StyleFactory` in your Android code to define how to style features based on their attributes.
-
-By following these steps, you can upload your data, create datasets, and use them to create informative maps with data-driven styling in your Android application.
\ No newline at end of file
+## 5. Set the Dataset ID in the secrets.properties file
+```
+BOULDER_DATASET_ID=
+NEW_YORK_DATASET_ID=
+KYOTO_DATASET_ID=
+```
+** Important: ** the map ID set in the strings.xml file must match the maps ID associated with the style.
\ No newline at end of file