Add location services to MapPage with permission handling and LocationDisplay integration

This commit is contained in:
2025-11-20 11:06:08 +01:00
parent 78b5e0264e
commit 3c1c91b5b7
2 changed files with 89 additions and 1 deletions

View File

@@ -26,4 +26,6 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest> </manifest>

View File

@@ -1,27 +1,113 @@
package de.jadehs.strassenschadenpro2.pages package de.jadehs.strassenschadenpro2.pages
import android.Manifest
import android.app.Application import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat
import com.arcgismaps.ApiKey import com.arcgismaps.ApiKey
import com.arcgismaps.ArcGISEnvironment import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.location.LocationDisplayAutoPanMode
import com.arcgismaps.mapping.ArcGISMap import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.BasemapStyle import com.arcgismaps.mapping.BasemapStyle
import com.arcgismaps.mapping.Viewpoint import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.toolkit.geoviewcompose.MapView import com.arcgismaps.toolkit.geoviewcompose.MapView
import com.arcgismaps.toolkit.geoviewcompose.rememberLocationDisplay
import de.jadehs.strassenschadenpro2.BuildConfig import de.jadehs.strassenschadenpro2.BuildConfig
import de.jadehs.strassenschadenpro2.MapViewModel import de.jadehs.strassenschadenpro2.MapViewModel
import kotlinx.coroutines.launch
@Composable @Composable
fun MapPage(modifier: Modifier = Modifier, application: Application) { fun MapPage(modifier: Modifier = Modifier, application: Application) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
ArcGISEnvironment.applicationContext = context.applicationContext
ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ARCGIS_TOKEN) ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ARCGIS_TOKEN)
val locationDisplay = rememberLocationDisplay().apply {
setAutoPanMode(LocationDisplayAutoPanMode.Off)
}
if (checkPermissions(context)) {
// Permissions are already granted.
LaunchedEffect(Unit) {
locationDisplay.dataSource.start()
}
} else {
RequestPermissions(
context = context,
onPermissionsGranted = {
coroutineScope.launch {
locationDisplay.dataSource.start()
}
}
)
}
val mapViewModel = remember { MapViewModel(application) } val mapViewModel = remember { MapViewModel(application) }
MapView(modifier = Modifier.fillMaxSize(), MapView(modifier = Modifier.fillMaxSize(),
arcGISMap = mapViewModel.map arcGISMap = mapViewModel.map,
locationDisplay = locationDisplay
) )
} }
fun checkPermissions(context: Context): Boolean {
// Check permissions to see if both permissions are granted.
// Coarse location permission.
val permissionCheckCoarseLocation = ContextCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED
// Fine location permission.
val permissionCheckFineLocation = ContextCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
return permissionCheckCoarseLocation && permissionCheckFineLocation
}
fun showError(context: Context, message: String) {
Toast.makeText(context, message, Toast.LENGTH_LONG).show()
}
@Composable
fun RequestPermissions(context: Context, onPermissionsGranted: () -> Unit) {
// Create an activity result launcher using permissions contract and handle the result.
val activityResultLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
// Check if both fine & coarse location permissions are true.
if (permissions.all { it.value }) {
onPermissionsGranted()
} else {
showError(context, "Location permissions were denied")
}
}
LaunchedEffect(Unit) {
activityResultLauncher.launch(
// Request both fine and coarse location permissions.
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
}
}