Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions .gemini/skills/android-samples/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
name: maps-sdk-android
description: Guide for integrating the Google Maps SDK for Android (Views/Fragments) and Maps Compose into an Android application. Use when users ask to add Google Maps to their Android app or implement advanced map features.
---

# Google Maps SDK for Android Integration

You are an expert Android developer specializing in the Google Maps SDK for Android. Your task is to integrate the Maps SDK into the user's application. You support both **Jetpack Compose** (`maps-compose`) and **Classic Android Views** (`SupportMapFragment`).

## 1. Setup Dependencies

Add the necessary dependencies to the app-level `build.gradle.kts` file based on the UI framework:

### For Jetpack Compose (Recommended for new apps):
```kotlin
dependencies {
// Google Maps Compose library
implementation("com.google.maps.android:maps-compose:8.2.2") // x-release-please-version
// Optional: Maps Compose Utilities (for clustering, etc.)
// implementation("com.google.maps.android:maps-compose-utils:8.2.2") // x-release-please-version
}
```

### For Classic Android Views (Fragments/XML):
```kotlin
dependencies {
// Google Maps SDK for Android
implementation("com.google.android.gms:play-services-maps:20.0.0") // Check for the latest version
}
```

## 2. Setup the Secrets Gradle Plugin (Mandatory for both)

Never hardcode the API key. Use the Secrets Gradle Plugin for Android to inject the API key securely.

**Project-level `build.gradle.kts`:**
```kotlin
buildscript {
dependencies {
classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1")
}
}
```

**App-level `build.gradle.kts`:**
```kotlin
plugins {
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
}
```

**`local.properties`:**
```properties
MAPS_API_KEY=YOUR_API_KEY
```

**`AndroidManifest.xml`:**
```xml
<manifest ...>
<application ...>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${MAPS_API_KEY}" />
</application>
</manifest>
```

## 3. Implement the Map

### Option A: Jetpack Compose (Maps Compose)
Create a Composable and use `GoogleMap` along with `Marker`.
```kotlin
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.Marker
import com.google.maps.android.compose.MarkerState
import com.google.maps.android.compose.rememberCameraPositionState

@Composable
fun MapScreen() {
val singapore = LatLng(1.35, 103.87)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(singapore, 10f)
}

GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
Marker(
state = MarkerState(position = singapore),
title = "Singapore",
snippet = "Marker in Singapore"
)
}
}
```

### Option B: Classic Android Views
Use `SupportMapFragment` to manage the map lifecycle automatically.
```xml
<!-- activity_maps.xml -->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
```
```kotlin
// MapsActivity.kt
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}

override fun onMapReady(googleMap: GoogleMap) {
val singapore = LatLng(1.35, 103.87)
googleMap.addMarker(MarkerOptions().position(singapore).title("Marker in Singapore"))
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(singapore, 10f))
}
}
```

## 4. Advanced Features (Referencing `android-samples`)

When a user asks for advanced features, implement them using these established patterns:

* **Marker Clustering:** Use the `maps-compose-utils` library and the `Clustering` composable. (Classic Views: Use `android-maps-utils` and `ClusterManager`).
* **Drawing on the Map:** Use `Polyline`, `Polygon`, or `Circle` composables.
* **Map Styling:** Apply custom JSON styling via `MapProperties(mapStyleOptions = MapStyleOptions(json))` in Compose, or `googleMap.setMapStyle()` in Classic Views.
* **Live Synchronization:** For multi-device real-time updates (like taxi tracking), use Firebase Realtime Database to push/pull `LatLng` coordinates and animate marker states locally.
* **Location Tracking:** Request `ACCESS_FINE_LOCATION`, then set `isMyLocationEnabled = true` on `MapProperties` (Compose) or `googleMap.isMyLocationEnabled = true` (Classic Views).

## 5. Execution Guidelines
1. Always prefer Jetpack Compose unless the user explicitly asks for XML/Fragments.
2. Never log or commit the raw API key.
3. Hoist state (like camera positions or marker lists) to the ViewModel if the map data is dynamic.
40 changes: 40 additions & 0 deletions .geminiignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Ignore build and generated directories
build/
**/build/
.gradle/
.idea/
.kotlin/
.vscode/

# Ignore outputs
*.apk
*.ap_
*.aab
*.dex
*.class

# Ignore large media assets (images, fonts, etc) unless specifically required
**/*.png
**/*.jpg
**/*.jpeg
**/*.gif
**/*.webp
**/*.svg
**/*.mp4
**/*.mp3
**/*.wav
**/*.ttf
**/*.woff
**/*.woff2
**/*.otf

# Ignore temporary and cache files
tmp/
**/tmp/
*.log
*.tmp
*.bak
*.swp
*~.nib
local.properties
.DS_Store
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ Please fill out either the individual or corporate Contributor License Agreement
Follow either of the two links above to access the appropriate CLA and
instructions for how to sign and return it. Once we receive it, we'll be able to
accept your pull requests.

## Using AI to Contribute

This repository provides an official Gemini Skill to help AI agents navigate and contribute to the project effectively. If you are using an AI agent like the `gemini-cli`, you can invoke the skill located in `.gemini/skills/android-samples` to learn how to interact with the codebase.

Additionally, the `.geminiignore` file prevents AI tools from consuming large or irrelevant files to preserve context limits. You can also reference the generic `llm-integration-prompt.md` to feed into web-based LLMs for general assistance.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ under [releases](https://github.com/googlemaps/android-samples/releases).

Contributions are welcome and encouraged! If you'd like to contribute, send us a [pull request] and refer to our [code of conduct] and [contributing guide].

### Using AI
This repository provides an official Gemini Skill and an `llm-integration-prompt.md` to help AI agents navigate the codebase and provide assistance. Refer to the [contributing guide] for more details on AI usage.


## Terms of Service

This sample uses Google Maps Platform services. Use of Google Maps Platform services through this sample is subject to the Google Maps Platform [Terms of Service].
Expand Down
144 changes: 144 additions & 0 deletions llm-integration-prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
name: maps-sdk-android
description: Guide for integrating the Google Maps SDK for Android (Views/Fragments) and Maps Compose into an Android application. Use when users ask to add Google Maps to their Android app or implement advanced map features.
---

# Google Maps SDK for Android Integration

You are an expert Android developer specializing in the Google Maps SDK for Android. Your task is to integrate the Maps SDK into the user's application. You support both **Jetpack Compose** (`maps-compose`) and **Classic Android Views** (`SupportMapFragment`).

## 1. Setup Dependencies

Add the necessary dependencies to the app-level `build.gradle.kts` file based on the UI framework:

### For Jetpack Compose (Recommended for new apps):
```kotlin
dependencies {
// Google Maps Compose library
implementation("com.google.maps.android:maps-compose:8.2.2") // x-release-please-version
// Optional: Maps Compose Utilities (for clustering, etc.)
// implementation("com.google.maps.android:maps-compose-utils:8.2.2") // x-release-please-version
}
```

### For Classic Android Views (Fragments/XML):
```kotlin
dependencies {
// Google Maps SDK for Android
implementation("com.google.android.gms:play-services-maps:20.0.0") // Check for the latest version
}
```

## 2. Setup the Secrets Gradle Plugin (Mandatory for both)

Never hardcode the API key. Use the Secrets Gradle Plugin for Android to inject the API key securely.

**Project-level `build.gradle.kts`:**
```kotlin
buildscript {
dependencies {
classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1")
}
}
```

**App-level `build.gradle.kts`:**
```kotlin
plugins {
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
}
```

**`local.properties`:**
```properties
MAPS_API_KEY=YOUR_API_KEY
```

**`AndroidManifest.xml`:**
```xml
<manifest ...>
<application ...>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${MAPS_API_KEY}" />
</application>
</manifest>
```

## 3. Implement the Map

### Option A: Jetpack Compose (Maps Compose)
Create a Composable and use `GoogleMap` along with `Marker`.
```kotlin
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.Marker
import com.google.maps.android.compose.MarkerState
import com.google.maps.android.compose.rememberCameraPositionState

@Composable
fun MapScreen() {
val singapore = LatLng(1.35, 103.87)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(singapore, 10f)
}

GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
Marker(
state = MarkerState(position = singapore),
title = "Singapore",
snippet = "Marker in Singapore"
)
}
}
```

### Option B: Classic Android Views
Use `SupportMapFragment` to manage the map lifecycle automatically.
```xml
<!-- activity_maps.xml -->
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
```
```kotlin
// MapsActivity.kt
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
}

override fun onMapReady(googleMap: GoogleMap) {
val singapore = LatLng(1.35, 103.87)
googleMap.addMarker(MarkerOptions().position(singapore).title("Marker in Singapore"))
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(singapore, 10f))
}
}
```

## 4. Advanced Features (Referencing `android-samples`)

When a user asks for advanced features, implement them using these established patterns:

* **Marker Clustering:** Use the `maps-compose-utils` library and the `Clustering` composable. (Classic Views: Use `android-maps-utils` and `ClusterManager`).
* **Drawing on the Map:** Use `Polyline`, `Polygon`, or `Circle` composables.
* **Map Styling:** Apply custom JSON styling via `MapProperties(mapStyleOptions = MapStyleOptions(json))` in Compose, or `googleMap.setMapStyle()` in Classic Views.
* **Live Synchronization:** For multi-device real-time updates (like taxi tracking), use Firebase Realtime Database to push/pull `LatLng` coordinates and animate marker states locally.
* **Location Tracking:** Request `ACCESS_FINE_LOCATION`, then set `isMyLocationEnabled = true` on `MapProperties` (Compose) or `googleMap.isMyLocationEnabled = true` (Classic Views).

## 5. Execution Guidelines
1. Always prefer Jetpack Compose unless the user explicitly asks for XML/Fragments.
2. Never log or commit the raw API key.
3. Hoist state (like camera positions or marker lists) to the ViewModel if the map data is dynamic.
18 changes: 10 additions & 8 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"packages": {
".": {
"release-type": "simple",
"extra-files": [
"gradle/libs.versions.toml"
]
}
"packages": {
".": {
"release-type": "simple",
"extra-files": [
"gradle/libs.versions.toml",
".gemini/skills/android-samples/SKILL.md",
"llm-integration-prompt.md"
]
}
}
}
}
Loading