Skip to content
Merged
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
25 changes: 20 additions & 5 deletions .github/workflows/lint-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,26 @@ jobs:
- name: Run Android Lint
run: ./gradlew lint

- name: Merge SARIF files
run: |
jq -s '{ "$schema": "https://json.schemastore.org/sarif-2.1.0", "version": "2.1.0", "runs": map(.runs) | add }' maps-compose/build/reports/lint-results.sarif maps-compose-utils/build/reports/lint-results.sarif maps-compose-widgets/build/reports/lint-results.sarif maps-app/build/reports/lint-results.sarif > merged.sarif
- name: Upload SARIF from maps-compose
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: maps-compose/build/reports/lint-results.sarif
category: maps-compose

- name: Upload SARIF from maps-compose-utils
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: maps-compose-utils/build/reports/lint-results.sarif
category: maps-compose-utils

- name: Upload SARIF from maps-compose-widgets
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: maps-compose-widgets/build/reports/lint-results.sarif
category: maps-compose-widgets

- name: Upload SARIF file
- name: Upload SARIF from maps-app
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: merged.sarif
sarif_file: maps-app/build/reports/lint-results.sarif
category: maps-app
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ mapsecrets = "2.0.1"
mapsktx = "5.2.0"
org-jacoco-core = "0.8.12"
screenshot = "0.0.1-alpha10"
constraintlayout = "2.2.1"
material = "1.12.0"

[libraries]
android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }
Expand Down Expand Up @@ -48,6 +50,8 @@ maps-ktx-utils = { module = "com.google.maps.android:maps-utils-ktx", version.re
maps-secrets-plugin = { module = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin", version.ref = "mapsecrets" }
org-jacoco-core = { module = "org.jacoco:org.jacoco.core", version.ref = "org-jacoco-core" }
test-junit = { module = "junit:junit", version.ref = "junit" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
Expand Down
2 changes: 2 additions & 0 deletions maps-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ dependencies {
implementation(libs.kotlin)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.androidx.compose.ui.preview.tooling)
implementation(libs.androidx.constraintlayout)
implementation(libs.material)
debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.leakcanary.android)

Expand Down
3 changes: 3 additions & 0 deletions maps-app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
<activity
android:name=".RecompositionActivity"
android:exported="false"/>
<activity
android:name=".FragmentDemoActivity"
android:exported="false"/>
<activity
android:name=".markerexamples.markerdragevents.MarkerDragEventsActivity"
android:exported="false"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.google.maps.android.compose


import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.widget.ViewPager2

class FragmentDemoActivity : FragmentActivity() {

private lateinit var viewPager: ViewPager2
private lateinit var pagerAdapter: MapFragmentPagerAdapter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fragment_demo)

viewPager = findViewById(R.id.view_pager)

pagerAdapter = MapFragmentPagerAdapter(this)
viewPager.adapter = pagerAdapter

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package com.google.maps.android.compose

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.geometry.Offset // For MarkerComposable anchor
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng


enum class MarkerType {
CUSTOM_CONTENT_MARKER, // To use com.google.maps.android.compose.MarkerComposable with your Text
STANDARD_MARKER_WITH_SNIPPET // To use the standard com.google.maps.android.compose.Marker
}

data class MapConfig(
val initialLatLng: LatLng,
val initialZoom: Float,
val title: String,
val markerType: MarkerType = MarkerType.CUSTOM_CONTENT_MARKER, // Default
val standardMarkerSnippet: String? = null
)

class GoogleMapComposeFragment : Fragment() {

private var mapConfig: MapConfig? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
val lat = it.getDouble(ARG_LAT, Double.NaN)
val lng = it.getDouble(ARG_LNG, Double.NaN)
val zoom = it.getFloat(ARG_ZOOM, 10f)
val title = it.getString(ARG_TITLE, "Map")

val markerTypeName = it.getString(ARG_MARKER_TYPE)
val markerType = markerTypeName?.let { name ->
try {
MarkerType.valueOf(name)
} catch (e: IllegalArgumentException) {
MarkerType.CUSTOM_CONTENT_MARKER
}
} ?: MarkerType.CUSTOM_CONTENT_MARKER

val snippet = it.getString(ARG_STANDARD_MARKER_SNIPPET)

if (!lat.isNaN() && !lng.isNaN()) {
mapConfig = MapConfig(
initialLatLng = LatLng(lat, lng),
initialZoom = zoom,
title = title,
markerType = markerType,
standardMarkerSnippet = snippet
)
}
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme {
val currentConfig = mapConfig ?: MapConfig(
initialLatLng = LatLng(0.0, 0.0),
initialZoom = 2f,
title = "Default Map",
markerType = MarkerType.CUSTOM_CONTENT_MARKER
)
MapContent(config = currentConfig)
}
}
}

@Composable
fun MapContent(config: MapConfig) {
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(config.initialLatLng, config.initialZoom)
}

GoogleMap(
cameraPositionState = cameraPositionState
) {
when (config.markerType) {
MarkerType.CUSTOM_CONTENT_MARKER -> {
val markerState = rememberUpdatedMarkerState(position = config.initialLatLng)
markerState.position = config.initialLatLng

MarkerComposable(
state = markerState,
anchor = Offset(0.5f, 1.0f)
){
Text(text = "Hello, World! (from ${config.title})")
}
}
MarkerType.STANDARD_MARKER_WITH_SNIPPET -> {
val markerState = rememberUpdatedMarkerState(position = config.initialLatLng)
markerState.position = config.initialLatLng

Marker(
state = markerState,
title = config.title,
snippet = config.standardMarkerSnippet ?: "Standard Marker Snippet" // Snippet for the info window
)
}
}
}
}

companion object {
private const val ARG_LAT = "arg_lat"
private const val ARG_LNG = "arg_lng"
private const val ARG_ZOOM = "arg_zoom"
private const val ARG_TITLE = "arg_title"
private const val ARG_MARKER_TYPE = "arg_marker_type"
private const val ARG_STANDARD_MARKER_SNIPPET = "arg_standard_marker_snippet"

@JvmStatic
fun newInstance(config: MapConfig): GoogleMapComposeFragment {
return GoogleMapComposeFragment().apply {
arguments = Bundle().apply {
putDouble(ARG_LAT, config.initialLatLng.latitude)
putDouble(ARG_LNG, config.initialLatLng.longitude)
putFloat(ARG_ZOOM, config.initialZoom)
putString(ARG_TITLE, config.title)
putString(ARG_MARKER_TYPE, config.markerType.name)
config.standardMarkerSnippet?.let { putString(ARG_STANDARD_MARKER_SNIPPET, it) }
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ class MainActivity : ComponentActivity() {
}) {
Text(getString(R.string.draggable_markers_collection_with_polygon))
}
Spacer(modifier = Modifier.padding(5.dp))
Button(
onClick = {
context.startActivity(Intent(context, FragmentDemoActivity::class.java))
}) {
Text(getString(R.string.fragment_demo_activity))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.google.maps.android.compose

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.gms.maps.model.LatLng

class MapFragmentPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {

private val mapConfigs = listOf(
MapConfig( // First map - Los Angeles
initialLatLng = LatLng(34.0522, -118.2437),
initialZoom = 10f,
title = "Los Angeles",
// LA gets the custom content marker
markerType = MarkerType.CUSTOM_CONTENT_MARKER
),
MapConfig( // Second map - New York City
initialLatLng = LatLng(40.7128, -74.0060),
initialZoom = 10f,
title = "New York City",
// NYC gets the standard marker
markerType = MarkerType.STANDARD_MARKER_WITH_SNIPPET,
standardMarkerSnippet = "The Big Apple!"
)
)

override fun getItemCount(): Int = mapConfigs.size

override fun createFragment(position: Int): Fragment {
return GoogleMapComposeFragment.newInstance(mapConfigs[position])
}
}
31 changes: 31 additions & 0 deletions maps-app/src/main/res/layout/activity_fragment_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FragmentDemoActivity">

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="#80000000"
android:padding="16dp"
android:text="Swipe to switch between views"

Check warning

Code scanning / Android Lint

Hardcoded text Warning

Hardcoded string "Swipe to switch between views", should use @string resource
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
1 change: 1 addition & 0 deletions maps-app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<string name="syncing_draggable_marker_with_data_model">Syncing Draggable Marker With Model</string>
<string name="updating_non_draggable_marker_with_data_model">Updating Non-Draggable Marker With Model</string>
<string name="draggable_markers_collection_with_polygon">Polygon around draggable markers</string>
<string name="fragment_demo_activity">Fragment Demo Activity</string>
<string name="recomposition_activity">Recomposition Map</string>
<string name="street_view">Street View</string>
<string name="custom_location_button">Custom Location Button</string>
Expand Down
Loading