From 539dd5af221ecc3120ecd5e6031d97b2b9026737 Mon Sep 17 00:00:00 2001 From: kateb02 <44986130+kateb02@users.noreply.github.com> Date: Wed, 5 Mar 2025 23:38:39 -0500 Subject: [PATCH] Working map --- app/build.gradle.kts | 61 ++++++++---- app/src/main/AndroidManifest.xml | 27 +++++- .../com/example/myapplication/MainActivity.kt | 96 +++++++++++++++++-- app/src/main/res/values/strings.xml | 1 + build.gradle.kts | 7 ++ gradle/libs.versions.toml | 8 ++ local.defaults.properties | 1 + secrets.properties | 9 ++ 8 files changed, 177 insertions(+), 33 deletions(-) create mode 100644 local.defaults.properties create mode 100644 secrets.properties diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8fe0a63..4dd0895 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,7 +1,23 @@ +import org.jetbrains.kotlin.fir.declarations.builder.buildScript + + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) + alias(libs.plugins.google.android.libraries.mapsplatform.secrets.gradle.plugin) +} + +secrets { + // To add your Maps API key to this project: + // 1. If the secrets.properties file does not exist, create it in the same folder as the local.properties file. + // 2. Add this line, where YOUR_API_KEY is your API key: + // MAPS_API_KEY=YOUR_API_KEY + propertiesFileName = "secrets.properties" + + // A properties file containing default secret values. This file can be + // checked in version control. + defaultPropertiesFileName = "local.defaults.properties" } android { @@ -36,26 +52,33 @@ android { } buildFeatures { compose = true + viewBinding = true } } -dependencies { - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.activity.compose) - implementation(platform(libs.androidx.compose.bom)) - implementation(libs.androidx.ui) - implementation(libs.androidx.ui.graphics) - implementation(libs.androidx.ui.tooling.preview) - implementation(libs.androidx.material3) - implementation(libs.androidx.espresso.core) - testImplementation(libs.junit) - androidTestImplementation(libs.androidx.junit) - androidTestImplementation(libs.androidx.espresso.core) - androidTestImplementation(platform(libs.androidx.compose.bom)) - androidTestImplementation(libs.androidx.ui.test.junit4) - debugImplementation(libs.androidx.ui.tooling) - debugImplementation(libs.androidx.ui.test.manifest) - -} \ No newline at end of file +dependencies { + implementation("com.google.android.gms:play-services-maps:19.0.0") + implementation("com.google.android.gms:play-services-location:21.3.0") + implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") + implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.4") + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + implementation(libs.androidx.espresso.core) + implementation(libs.play.services.maps) + implementation(libs.androidx.appcompat) + implementation(libs.androidx.constraintlayout) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) + } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 81f9f73..38903da 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,10 +2,13 @@ - + + + - - + + + + + + + + - diff --git a/app/src/main/java/com/example/myapplication/MainActivity.kt b/app/src/main/java/com/example/myapplication/MainActivity.kt index 5e36f43..b2ce6a8 100644 --- a/app/src/main/java/com/example/myapplication/MainActivity.kt +++ b/app/src/main/java/com/example/myapplication/MainActivity.kt @@ -1,5 +1,6 @@ package com.example.myapplication +import kotlinx.coroutines.tasks.await import StepCounter import android.content.pm.PackageManager import android.icu.util.Calendar @@ -35,30 +36,58 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.compose.ui.viewinterop.AndroidView import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import com.google.android.gms.maps.CameraUpdateFactory +import com.google.android.gms.maps.MapView +import com.google.android.gms.maps.model.LatLng +import com.google.android.gms.maps.model.MarkerOptions +import com.google.android.gms.location.LocationServices +import com.google.android.gms.location.Priority + + +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.tasks.CancellationTokenSource class MainActivity : ComponentActivity() { + + + val LOCATION_PERMISSIONS = arrayOf( + android.Manifest.permission.ACCESS_COARSE_LOCATION, + android.Manifest.permission.ACCESS_FINE_LOCATION + ) val STEP_PERMISSIONS = arrayOf( android.Manifest.permission.ACTIVITY_RECOGNITION ) + fun hasStepPermission(): Boolean { - //gpt return ContextCompat.checkSelfPermission( applicationContext, android.Manifest.permission.ACTIVITY_RECOGNITION ) == PackageManager.PERMISSION_GRANTED } + fun hasLocationPermission(): Boolean { + + return ContextCompat.checkSelfPermission( + applicationContext, + android.Manifest.permission.ACTIVITY_RECOGNITION + ) == PackageManager.PERMISSION_GRANTED && + ContextCompat.checkSelfPermission(applicationContext, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if(!hasStepPermission()){ - ActivityCompat.requestPermissions( - this, STEP_PERMISSIONS, 0 - ) + ActivityCompat.requestPermissions(this, STEP_PERMISSIONS, 0) } + if(!hasLocationPermission()){ + ActivityCompat.requestPermissions(this, LOCATION_PERMISSIONS, 0) + } + enableEdgeToEdge() setContent { @@ -176,17 +205,64 @@ fun MainScreen() { } } - +//https://github.com/android/platform-samples/blob/main/samples/location/src/main/java/com/example/platform/location/currentLocation/CurrentLocationScreen.kt @Composable fun MapImage() { //TODO: make map appear - Box( - modifier = Modifier - .size(200.dp) - .background(Color.Gray, shape = RoundedCornerShape(8.dp)) - ) {} + + val context = LocalContext.current + val mapV = remember { MapView(context) } + var googleMapInstance by remember { mutableStateOf(null) } + + val locationClient = remember { + LocationServices.getFusedLocationProviderClient(context) + } + + var userLocation by remember { mutableStateOf((LatLng(-34.0, 151.0))) } + + LaunchedEffect(Unit) { + if (ContextCompat.checkSelfPermission( + context, android.Manifest.permission.ACCESS_FINE_LOCATION + ) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission( + context, android.Manifest.permission.ACCESS_COARSE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + ) { + + val loc = locationClient.getCurrentLocation( + Priority.PRIORITY_HIGH_ACCURACY, CancellationTokenSource().token + ).await() + + loc?.let { + userLocation = LatLng(it.latitude, it.longitude) + } + } + } + + LaunchedEffect(userLocation) { + googleMapInstance?.let { googleMap -> + googleMap.clear() + googleMap.addMarker(MarkerOptions().position(userLocation).title("You are here")) + googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15f)) + } + } + + //https://developers.google.com/maps/documentation/android-sdk/map + AndroidView( + factory = { mapV }, + modifier = Modifier.size(200.dp).background(Color.Gray, shape = RoundedCornerShape(8.dp)), + update = { map -> + map.onCreate(Bundle()) + map.getMapAsync { googleMap -> + googleMapInstance = googleMap + googleMap.addMarker(MarkerOptions().position(userLocation).title("Default marker")) + googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 10f)) + } + map.onResume() + } + ) } + @Composable fun ImageHolder(movementType: String) { var resourceId: Int diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3de1a39..bc52e20 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ My Application + MapsActivity \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 952b930..233b924 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,4 +3,11 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlin.compose) apply false + alias(libs.plugins.google.android.libraries.mapsplatform.secrets.gradle.plugin) apply false +} + +buildscript { + dependencies { + classpath("com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1") + } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b8bd58d..06373db 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,10 @@ espressoCore = "3.6.1" lifecycleRuntimeKtx = "2.8.7" activityCompose = "1.10.1" composeBom = "2024.04.01" +googleAndroidLibrariesMapsplatformSecretsGradlePlugin = "2.0.1" +playServicesMaps = "19.1.0" +appcompat = "1.7.0" +constraintlayout = "2.2.1" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -24,9 +28,13 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" } +play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +google-android-libraries-mapsplatform-secrets-gradle-plugin = { id = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin", version.ref = "googleAndroidLibrariesMapsplatformSecretsGradlePlugin" } diff --git a/local.defaults.properties b/local.defaults.properties new file mode 100644 index 0000000..995b0da --- /dev/null +++ b/local.defaults.properties @@ -0,0 +1 @@ +MAPS_API_KEY=DEFAULT_API_KEY diff --git a/secrets.properties b/secrets.properties new file mode 100644 index 0000000..19f81c6 --- /dev/null +++ b/secrets.properties @@ -0,0 +1,9 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +#Mon Mar 03 22:23:59 EST 2025 + +MAPS_API_KEY=AIzaSyC6ykX_pAp61zSWcPANWrtiqLaHPoD02C4