数码帮手
白蓝主题五 · 清爽阅读
首页  > 手机应用

用Kotlin开发获取位置信息的Android应用实战

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秒,否则切换到网络定位作为备用。

另外,别忘了在设置里加个开关,让用户能手动开启或关闭定位。尊重隐私,才能赢得信任。