2023年Kotlin获取用户当前地址的更佳方案咨询
2023年Kotlin实现更可靠的用户定位方案(替代lastLocation)
fusedLocationClient.lastLocation的问题很明确:它优先返回缓存的位置数据,要是没有缓存就直接返回null,而且完全不保证数据的新鲜度,这就是你觉得它慢或者失效的核心原因。2023年更推荐使用getCurrentLocation()方法,这是Google Play Services Location库提供的更可靠的方案,专门用来获取实时的当前位置。
核心方案步骤
1. 确保依赖版本
在Module级别的build.gradle中引入2023年稳定版的定位库:
dependencies { implementation 'com.google.android.gms:play-services-location:21.0.1' }
2. 权限准备
先在AndroidManifest.xml中声明必要权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 12+ 如需前台定位通知,添加以下权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
注意:Android 6.0+需要动态请求ACCESS_FINE_LOCATION权限,按钮触发定位前一定要先检查权限状态。
3. 用Kotlin协程实现定位逻辑
结合协程能更优雅地处理异步请求,避免回调嵌套:
import android.Manifest import android.content.pm.PackageManager import android.os.Bundle import android.widget.Button import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import com.google.android.gms.location.CurrentLocationRequest import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationServices import com.google.android.gms.tasks.CancellationTokenSource import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.tasks.await import java.util.Locale class LocationActivity : AppCompatActivity() { private lateinit var fusedLocationClient: FusedLocationProviderClient private lateinit var locationBtn: Button private lateinit var addressTv: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_location) fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) locationBtn = findViewById(R.id.btn_get_location) addressTv = findViewById(R.id.tv_address) locationBtn.setOnClickListener { CoroutineScope(Dispatchers.Main).launch { getCurrentLocationAndAddress() } } } private suspend fun getCurrentLocationAndAddress() { // 检查权限 if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { // 请求权限 ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1001 ) return } // 创建当前位置请求,设置优先级和超时 val currentLocationRequest = CurrentLocationRequest.Builder() .setPriority(CurrentLocationRequest.PRIORITY_HIGH_ACCURACY) .setDurationMillis(10000) // 10秒超时 .setMaxUpdateAgeMillis(0) // 不接受缓存数据,必须实时获取 .build() val cancellationTokenSource = CancellationTokenSource() try { // 获取实时位置 val location = fusedLocationClient.getCurrentLocation( currentLocationRequest, cancellationTokenSource.token ).await() location?.let { // 解析地址 val address = getAddressFromLocation(it.latitude, it.longitude) addressTv.text = address ?: "无法解析地址" } ?: run { addressTv.text = "无法获取当前位置" } } catch (e: Exception) { addressTv.text = "定位失败:${e.message}" } } private fun getAddressFromLocation(lat: Double, lng: Double): String? { val geocoder = android.location.Geocoder(this, Locale.getDefault()) return try { val addresses = geocoder.getFromLocation(lat, lng, 1) addresses?.firstOrNull()?.run { "${getAddressLine(0)}, ${locality}, ${countryName}" } } catch (e: Exception) { null } } // 处理权限请求结果 override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == 1001 && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { CoroutineScope(Dispatchers.Main).launch { getCurrentLocationAndAddress() } } } }
关键优势
getCurrentLocation()会主动请求设备的实时位置,不依赖缓存,解决了lastLocation返回null或过时数据的问题- 可设置超时时间,避免无限等待定位结果
- 通过
setMaxUpdateAgeMillis(0)强制获取新鲜位置数据,确保准确性 - 结合Kotlin协程,代码逻辑更清晰,避免回调嵌套
注意事项
- 如果设备处于飞行模式或无定位信号,
getCurrentLocation()会抛出异常或返回null,务必做好错误处理 - 高优先级定位会消耗更多电量,若不需要高精度,可把优先级改为
PRIORITY_BALANCED_POWER_ACCURACY - Android 12+中,前台定位需要显示通知,可在
CurrentLocationRequest中通过setForegroundServiceType()配置
内容的提问来源于stack exchange,提问作者Cipri
相关产品推荐
相关产品推荐

