Add location services to MapPage with permission handling and LocationDisplay integration
This commit is contained in:
@@ -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>
|
||||||
@@ -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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user