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.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

View File

@@ -1,27 +1,113 @@
package de.jadehs.strassenschadenpro2.pages
import android.Manifest
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.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat
import com.arcgismaps.ApiKey
import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.location.LocationDisplayAutoPanMode
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.BasemapStyle
import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.toolkit.geoviewcompose.MapView
import com.arcgismaps.toolkit.geoviewcompose.rememberLocationDisplay
import de.jadehs.strassenschadenpro2.BuildConfig
import de.jadehs.strassenschadenpro2.MapViewModel
import kotlinx.coroutines.launch
@Composable
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)
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) }
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
)
)
}
}