You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android天气APP开发:获取用户位置的当前最优方案咨询

Android 获取用户位置的最佳实践(2024年适用)

作为Android新手,推荐你使用Google Play Services提供的Fused Location Provider,这是当前官方推荐的定位方案——整合了GPS、网络定位、基站等多种数据源,效率更高且适配性更好,完全替代了旧的LocationManager方案。以下是完整实现步骤:

1. 配置依赖与权限

权限声明(AndroidManifest.xml)

根据APP需求添加定位权限,前台定位至少需要ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION;Android 10+版本中,若APP后台也需要定位,需额外申请ACCESS_BACKGROUND_LOCATION:

<!-- 高精度前台定位权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 可选:后台定位权限(仅当APP在后台需持续定位时添加) -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

添加依赖(Module级别build.gradle)

引入最新版的定位服务依赖:

dependencies {
    implementation "com.google.android.gms:play-services-location:21.0.1"
}

2. 动态申请权限(Android 6.0+)

危险权限需在运行时申请,先检查权限状态,未授权则发起请求:

private const val REQUEST_LOCATION_PERM = 1001

private fun checkAndRequestLocationPermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
            REQUEST_LOCATION_PERM
        )
    } else {
        // 权限已授予,开始获取位置
        fetchCurrentLocation()
    }
}

// 处理权限请求结果
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == REQUEST_LOCATION_PERM) {
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            fetchCurrentLocation()
        } else {
            // 用户拒绝权限,可弹出提示引导开启,或降级使用功能
        }
    }
}

3. 获取当前位置

使用FusedLocationProviderClient获取位置,同时处理定位设置不满足的情况(比如用户关闭了GPS):

private lateinit var fusedLocationClient: FusedLocationProviderClient

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
}

private fun fetchCurrentLocation() {
    // 配置定位请求参数
    val locationRequest = LocationRequest.create().apply {
        priority = LocationRequest.PRIORITY_HIGH_ACCURACY // 高精度定位,也可选择平衡功耗的模式
        interval = 10000 // 定位更新间隔(毫秒)
        fastestInterval = 5000 // 最快更新间隔
    }

    // 检查设备定位设置是否符合要求
    val settingsRequest = LocationSettingsRequest.Builder()
        .addLocationRequest(locationRequest)
        .build()

    LocationServices.getSettingsClient(this)
        .checkLocationSettings(settingsRequest)
        .addOnSuccessListener {
            // 定位设置正常,尝试获取最近一次定位
            fusedLocationClient.lastLocation
                .addOnSuccessListener { location: Location? ->
                    location?.let {
                        // 成功获取位置,处理经纬度
                        val lat = it.latitude
                        val lng = it.longitude
                        // 此处可将经纬度传入天气API
                    } ?: run {
                        // 最近无定位记录,请求实时定位更新
                        requestRealTimeLocation(locationRequest)
                    }
                }
        }
        .addOnFailureListener { exception ->
            if (exception is ResolvableApiException) {
                // 定位设置未开启,弹出对话框引导用户启用
                exception.startResolutionForResult(this, 1002)
            } else {
                // 无法修复的定位问题,提示用户
            }
        }
}

// 请求实时定位更新(当lastLocation为null时)
private fun requestRealTimeLocation(locationRequest: LocationRequest) {
    val locationCallback = object : LocationCallback() {
        override fun onLocationResult(result: LocationResult) {
            super.onLocationResult(result)
            result.lastLocation?.let { location ->
                // 获取到实时位置
                val lat = location.latitude
                val lng = location.longitude
                // 完成定位后停止更新,避免耗电
                fusedLocationClient.removeLocationUpdates(this)
            }
        }
    }
    fusedLocationClient.requestLocationUpdates(
        locationRequest,
        locationCallback,
        Looper.getMainLooper()
    )
}

关键注意事项

  • 避免直接使用LocationManager:Fused Location Provider会自动选择最优定位源,减少耗电并提升成功率。
  • 处理lastLocation为null的场景:设备首次开机、长时间未定位时,lastLocation会返回null,需通过requestLocationUpdates获取实时定位。
  • 及时停止定位更新:不需要持续定位时,调用removeLocationUpdates避免不必要的功耗。
  • 权限适配:根据APP场景申请对应权限,后台定位权限仅在必要时申请,避免被用户拒绝。

内容的提问来源于stack exchange,提问作者AzeaL87

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 02:10:39