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

如何使用Kotlin在后台获取Android设备的经纬度?

Kotlin 实现 Android 后台经纬度检测方案

1. 前置配置:声明权限

首先在AndroidManifest.xml中添加所需定位权限,根据你的定位精度需求和目标系统版本选择:

<!-- 基础定位权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 网络定位精度,误差百米级 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- GPS定位精度,误差十米级 -->
<!-- 后台定位权限(Android 10及以上需要) -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!-- 网络权限,用于后续拉取天气数据 -->
<uses-permission android:name="android.permission.INTERNET" />

如果选择Google Play服务的融合定位SDK(推荐,功耗更低、定位精度更高),需要在模块级build.gradle中添加依赖:

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

2. 动态申请权限

定位属于危险权限,必须在运行时动态申请,推荐使用Activity Result API实现:

// 注册权限申请回调
val requestLocationPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
    val fineLocationGranted = permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: false
    val coarseLocationGranted = permissions[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false
    val backgroundLocationGranted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        permissions[Manifest.permission.ACCESS_BACKGROUND_LOCATION] ?: false
    } else true

    when {
        fineLocationGranted || coarseLocationGranted -> {
            // 基础定位权限已获取,可以开始定位
            getCurrentLocation()
        }
        else -> {
            // 权限被拒绝,引导用户到设置页开启
        }
    }
}

// 触发权限申请
fun requestLocationPermissions() {
    val permissionList = mutableListOf(
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_COARSE_LOCATION
    )
    // Android 10及以上追加后台定位权限申请
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        permissionList.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
    }
    requestLocationPermissionLauncher.launch(permissionList.toTypedArray())
}

3. 核心定位逻辑实现

单次定位获取(适合启动时拉取当前位置天气)

private lateinit var fusedLocationClient: FusedLocationProviderClient

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

@SuppressLint("MissingPermission")
fun getCurrentLocation() {
    fusedLocationClient.lastLocation
        .addOnSuccessListener { location: Location? ->
            location?.let {
                val latitude = it.latitude
                val longitude = it.longitude
                // 拿到经纬度后调用天气接口拉取数据
                fetchWeatherData(latitude, longitude)
            } ?: run {
                // 历史位置为空,主动请求一次新鲜定位
                val locationRequest = LocationRequest.create().apply {
                    priority = LocationRequest.PRIORITY_HIGH_ACCURACY
                    interval = 10000
                    fastestInterval = 5000
                    numUpdates = 1
                }
                fusedLocationClient.requestLocationUpdates(
                    locationRequest,
                    object : LocationCallback() {
                        override fun onLocationResult(locationResult: LocationResult) {
                            super.onLocationResult(locationResult)
                            val newLocation = locationResult.lastLocation ?: return
                            val latitude = newLocation.latitude
                            val longitude = newLocation.longitude
                            fetchWeatherData(latitude, longitude)
                            fusedLocationClient.removeLocationUpdates(this)
                        }
                    },
                    Looper.getMainLooper()
                )
            }
        }
}

后台定时定位(适合每隔几小时更新一次位置天气)

推荐使用WorkManager实现后台定时任务,避免被系统后台策略杀死:

// 定义定位Worker
class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        val fusedLocationClient = LocationServices.getFusedLocationProviderClient(applicationContext)
        return try {
            val location = Tasks.await(fusedLocationClient.lastLocation)
            location?.let {
                // 这里执行天气数据拉取逻辑,可以存到本地SP或者数据库
                saveLocationAndFetchWeather(it.latitude, it.longitude)
            }
            Result.success()
        } catch (e: Exception) {
            Result.retry()
        }
    }
}

// 注册定时任务,每隔6小时执行一次
fun schedulePeriodicLocationCheck() {
    val periodicWorkRequest = PeriodicWorkRequestBuilder<LocationWorker>(6, TimeUnit.HOURS)
        .setConstraints(
            Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build()
        )
        .build()
    WorkManager.getInstance(context).enqueueUniquePeriodicWork(
        "location_weather_update",
        ExistingPeriodicWorkPolicy.KEEP,
        periodicWorkRequest
    )
}

注意事项

  • 若用户拒绝后台定位权限,只能在app前台运行时获取位置,需要做好降级处理
  • 不要设置过高的定位频率,避免不必要的功耗消耗,天气类应用2-6小时更新一次位置足够
  • 国内部分厂商系统有自定义后台权限限制,需要适配厂商的权限白名单引导逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:27:05