我试图了解如何在使用 Jetpack Compose 开发的 Android 应用程序中使用位置服务。经过一些教程后,我遇到了;我编写了以下代码组件来了解如何实现这一目标。
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
GetLocationTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
LocationDisplay()
}
}
}
}
}
@OptIn(ExperimentalPermissionsApi::class)
@SuppressLint("MissingPermission")
@Composable
private fun LocationDisplay() {
var locationText by remember { mutableStateOf("")}
val locationPermissionsState = rememberMultiplePermissionsState(
listOf(
android.Manifest.permission.ACCESS_COARSE_LOCATION,
android.Manifest.permission.ACCESS_FINE_LOCATION,
)
)
if (locationPermissionsState.allPermissionsGranted) {
Column {
Text(locationText)
Button(onClick = { /*TODO*/ }) {
Text("Stop")
}
}
val appContext = LocalContext.current.applicationContext
val fusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(appContext)
fusedLocationProviderClient.lastLocation
.addOnSuccessListener {location ->
location?.let {locationText = "Location ${it.latitude}, ${it.longitude}"}
Log.d("TAG", locationText)
}
}
else {
Column {
Button(
onClick = { locationPermissionsState.launchMultiplePermissionRequest() }
) { Text("Request permissions") }
}
}
}
据我了解,这种方法订阅 lambda 函数来捕获位置更新并使用更新后的值更新文本可组合项。因此,位置更新一旦开始就会继续。
我试图了解如何查询一次位置而不是注册侦听器。这可能吗?或者,如果我使用相同的方法,有没有办法在获得有效读数后取消注册回调?
我尝试查看 fusedLocationProviderClient.lastLocation 提供的其他方法,希望看到一个可以删除 OnSuccessListner 的函数。我找不到方法来做到这一点。
我还尝试看看是否可以使用协同例程来等待()获取位置结果。我没有成功地让这种方法发挥作用。
您可以浏览此存储库,因为它可能会对您有所帮助。
您可以使用类似的方法仅获取一次位置:
internal object LocationService {
suspend fun getCurrentLocation(context: Context): Location {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
when {
!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) -> throw LocationServiceException.LocationDisabledException()
!locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) -> throw LocationServiceException.NoNetworkEnabledException()
else -> {
val locationProvider = LocationServices.getFusedLocationProviderClient(context)
val request = CurrentLocationRequest.Builder()
.setPriority(Priority.PRIORITY_BALANCED_POWER_ACCURACY)
.build()
runCatching {
val location = if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
throw LocationServiceException.MissingPermissionException()
} else {
locationProvider.getCurrentLocation(request, null).await()
}
return location
}.getOrElse {
throw LocationServiceException.UnknownException(stace = it.stackTraceToString())
}
}
}
}
sealed class LocationServiceException : Exception() {
class MissingPermissionException : LocationServiceException()
class LocationDisabledException : LocationServiceException()
class NoNetworkEnabledException : LocationServiceException()
class UnknownException(val stace: String) :LocationServiceException()
}
}
您可以简单地调用该对象来获取位置。