用ref="/tag/2032/" style="color:#EB6E00;font-weight:bold;">Kotlin轻松实现定位功能
现在出门导航、点外卖、打车,都离不开位置信息。作为开发者,如果你正在做一个需要定位的Android应用,Kotlin是个不错的选择。它语法简洁,配合Android Studio和官方API,能快速集成定位功能。
比如你正在开发一个记录跑步轨迹的App,或者做一个附近商家推荐的功能,第一步就是准确获取用户的位置。下面来看看怎么用Kotlin实现。
添加权限声明
在Android中获取位置,首先要申请权限。打开AndroidManifest.xml文件,添加以下两行:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />前者是精确位置(比如GPS),后者是粗略位置(比如基站或Wi-Fi定位)。建议两个都加上,系统会根据情况自动选择。
在Activity中请求运行时权限
从Android 6.0开始,除了在清单文件中声明,还要在运行时动态申请。Kotlin中可以用registerForActivityResult来处理:
private val locationPermissionRequest = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
when {
permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
// 用户授予了精确位置权限
startLocationUpdates()
}
permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
// 用户只给了粗略位置
startLocationUpdates()
}
else -> {
// 权限被拒绝
Toast.makeText(this, "需要位置权限才能继续", Toast.LENGTH_SHORT).show()
}
}
}在用户点击“开始定位”按钮时调用:
locationPermissionRequest.launch(arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
))使用FusedLocationProviderClient获取位置
Google推荐使用FusedLocationProviderClient,它能智能选择最佳定位方式,省电又高效。
先在onCreate中初始化:
private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
}然后写一个方法来获取当前位置:
private fun getLastLocation() {
fusedLocationClient.lastLocation
.addOnSuccessListener { location ->
if (location != null) {
val lat = location.latitude
val lng = location.longitude
Toast.makeText(this, "位置:$lat, $lng", Toast.LENGTH_LONG).show()
} else {
Toast.makeText(this, "暂时无法获取位置", Toast.LENGTH_SHORT).show()
}
}
}这个方法适合一次性获取位置,比如用户点击“刷新我的位置”时调用。
持续监听位置变化
如果是跑步类App,需要持续跟踪位置。可以设置位置更新间隔:
private fun startLocationUpdates() {
val locationRequest = LocationRequest.create().apply {
interval = 10000 // 每10秒更新一次
fastestInterval = 5000 // 最快5秒
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
fusedLocationClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}再定义一个回调:
private val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
for (location in locationResult.locations) {
// 处理新位置
Log.d("Location", "更新位置:${location.latitude}, ${location.longitude}")
}
}
}记得在不需要时取消监听,避免耗电:
fusedLocationClient.removeLocationUpdates(locationCallback)实际场景中的小细节
比如你在做一款“附近停车场”App,用户打开就自动定位。但有时候第一次拿不到位置,可能是因为GPS还没启动。这时候可以提示用户“正在定位中”,并设置一个超时机制,最多等10秒,否则切换到网络定位作为备用。
另外,别忘了在设置里加个开关,让用户能手动开启或关闭定位。尊重隐私,才能赢得信任。