如何在Jetpack Compose中请求用户开启系统定位设置以获取GPS位置
Jetpack Compose 请求开启系统定位设置实现方案
明确:权限申请和系统定位开关是两个完全独立的流程,即使位置权限已经授予,系统全局定位关闭时依然无法获取位置信息,需要单独调用系统定位开启请求流程。
前置依赖
首先需要引入Google定位服务依赖,在app模块build.gradle的dependencies块中添加:
implementation "com.google.android.gms:play-services-location:21.0.1"
如果是无GMS的国产设备,可以直接跳转系统定位设置页,不需要引入上述依赖,下文会补充对应兼容方案。
完整实现代码
import android.content.Intent import android.provider.Settings import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.material.Button import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import com.google.android.gms.location.LocationRequest import com.google.android.gms.location.LocationServices import com.google.android.gms.location.LocationSettingsRequest import com.google.accompanist.permissions.rememberMultiplePermissionsState @Composable fun LocationRequestScreen() { val context = LocalContext.current // 原有权限申请状态 val multiplePermissionsState = rememberMultiplePermissionsState( listOf( android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_BACKGROUND_LOCATION ) ) // 注册定位设置请求的返回处理 launcher(GMS设备用) val locationSettingsLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartIntentSenderForResult() ) { result -> if (result.resultCode == android.app.Activity.RESULT_OK) { // 用户已同意开启定位,可直接执行位置获取逻辑 } else { // 用户拒绝开启定位,可按需做降级提示 } } // 无GMS设备跳转系统设置页的launcher val locationSettingPageLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartActivityForResult() ) { // 回到页面时可重新检查定位是否开启 } // 检查并请求开启定位设置的方法 fun requestEnableLocation() { val locationRequest = LocationRequest.create().apply { priority = LocationRequest.PRIORITY_HIGH_ACCURACY } val builder = LocationSettingsRequest.Builder() .addLocationRequest(locationRequest) val client = LocationServices.getSettingsClient(context) val task = client.checkLocationSettings(builder.build()) task.addOnSuccessListener { // 定位已经开启,直接执行位置获取逻辑 } task.addOnFailureListener { exception -> if (exception is com.google.android.gms.common.api.ResolvableApiException) { // 定位未开启,弹出系统弹窗请求用户开启 locationSettingsLauncher.launch( android.content.IntentSenderRequest.Builder(exception.resolution.intentSender).build() ) } else { // 设备无GMS服务,直接跳转系统定位设置页 val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) locationSettingPageLauncher.launch(intent) } } } Button( onClick = { if (multiplePermissionsState.allPermissionsGranted) { // 权限已经授予,直接检查定位开关 requestEnableLocation() } else { // 先申请权限,权限申请成功后再检查定位开关 multiplePermissionsState.launchMultiplePermissionRequest() } }, modifier = Modifier.background(MaterialTheme.colors.primary) ) { Text(text = "获取位置权限") } // 监听权限申请结果,权限全部授予后自动触发定位开启检查 LaunchedEffect(multiplePermissionsState.allPermissionsGranted) { if (multiplePermissionsState.allPermissionsGranted) { requestEnableLocation() } } }
逻辑说明
- 点击按钮后先判断位置权限是否已经全部授予,未授予则先走原有权限申请流程
- 权限全部授予后自动调用定位设置检查,若定位未开启则弹出系统原生的定位开启确认弹窗,无需用户手动进入设置页
- 无GMS的设备会自动降级跳转到系统定位设置页,用户开启后返回应用即可正常获取位置
内容的提问来源于stack exchange,提问作者alexb
相关产品推荐
相关产品推荐

