Android 定位 获取当前位置 (Kotlin)

导入:

复制代码
implementation 'com.google.android.gms:play-services-location:21.3.0'

头文件:

复制代码
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.google.android.gms.tasks.CancellationTokenSource
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import android.os.Looper
import androidx.core.app.ActivityCompat

代码实现:

复制代码
private val PLAY_SERVICES_RESOLUTION_REQUEST = 9000
private var fusedLocationClient: FusedLocationProviderClient? = null

1.requestLocationUpdates:持续获取定位,根据更新间隔和最快频率

复制代码
fusedLocationClient = LocationServices.getFusedLocationProviderClient(thisContext!!)
if (ActivityCompat.checkSelfPermission(
        thisContext!!,
        Manifest.permission.ACCESS_FINE_LOCATION
    ) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
        thisContext!!,
        Manifest.permission.ACCESS_COARSE_LOCATION
    ) == PackageManager.PERMISSION_GRANTED
) {
    val locationRequest: LocationRequest = LocationRequest.create()
    locationRequest.interval = 2000 // 更新间隔,例如10秒
    locationRequest.fastestInterval = 5000 // 最快频率,例如5秒
    locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
    fusedLocationClient!!.requestLocationUpdates(
        locationRequest,
        object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult) {
                if (locationResult == null) {
                    LogUtils.d("requestLocationUpdates locationResult == null")
                    return
                }
                for (location in locationResult.locations) {
                    var latitude = location.latitude.toString()
                    var longitude = location.longitude.toString()
                    if (latitude.contains(".")) {
                        latitude = subString(latitude)
                    }
                    if (longitude.contains(".")) {
                        longitude = subString(longitude)
                    }
                    LogUtils.d("requestLocationUpdates onLocationResult latitude = $latitude  longitude = $longitude")
                }
            }
        },
        Looper.myLooper()
    )
}

2.getCurrentLocation:获取一次定位

复制代码
private fun startLocation() {
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    if (ActivityCompat.checkSelfPermission(
            this,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
            this,
            Manifest.permission.ACCESS_COARSE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        LogUtils.d("fusedLocationClient Ok")
        val priority = Priority.PRIORITY_BALANCED_POWER_ACCURACY
        val cancellationTokenSource = CancellationTokenSource()
        val cancellationToken = cancellationTokenSource.token
        fusedLocationClient.getCurrentLocation(
            priority,
            cancellationToken
        )
            .addOnSuccessListener(
                this
            ) { location ->
                if (location != null) {
                    val latitude = location.latitude
                    val longitude = location.longitude
                    LogUtils.d("fusedLocationClient latitude = $latitude  longitude = $longitude")
                } else {
                    LogUtils.d("fusedLocationClient location = null")
                }
            }
            .addOnFailureListener { exception ->
                LogUtils.d("fusedLocationClient exception = $exception")

            }
    }
}
复制代码
//上面方法中 addOnFailureListener 报错如下:
//com.google.android.gms.common.api.ApiException: 17: API: LocationServices.API is not available on this device. Connection failed with: ConnectionResult{statusCode=SERVICE_INVALID, resolution=null, message=null}
//如发生这个错误,可能是当前手机设备没有安装Google Play 服务,可以用如下两个方法检查当前设备是否安装Google Play 服务,再调用获取上面定位方法
复制代码
private fun checkPlayServices(): Boolean {
    val apiAvailability = GoogleApiAvailability.getInstance()
    val resultCode = apiAvailability.isGooglePlayServicesAvailable(this)
    if (resultCode != ConnectionResult.SUCCESS) {
        if (apiAvailability.isUserResolvableError(resultCode)) {
            LogUtils.d("GoogleApiAvailability NO")
            apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                ?.show()
        } else {
            LogUtils.d("GoogleApiAvailability Google Play")
            finish()
        }
        return false
    }
    return true
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == PLAY_SERVICES_RESOLUTION_REQUEST) {
        if (resultCode == Activity.RESULT_OK) {
            if (checkPlayServices()) {
                startLocation()
            }
        } else {
            LogUtils.d("无法使用 Google Play 服务")
            finish()
        }
    }
}
相关推荐
石山岭13 小时前
自己动手写了一个 Android 虚拟定位 App:GPSSimulate 技术实
android·前端
杉氧15 小时前
副作用 (Side Effects) 全攻略:如何像大师一样掌控 Composable 的生命周期?
android·架构·android jetpack
Kapaseker20 小时前
Kotlin Toolchain 0.11 发布:主要是把 Amper 干没了
android·kotlin
三少爷的鞋21 小时前
Android 现代架构不需要事件总线进阶篇
android
杉氧1 天前
深入理解 Compose 重组机制:快照系统如何驱动 UI 精准刷新?
android·架构·android jetpack
召钱熏1 天前
状态枚举正确≠渲染正确:一个语音按钮的状态机边界修复实录
android·前端
杉氧2 天前
深度解析:Jetpack Compose 核心架构与底层原理 —— 十年安卓老兵的“破茧重生”
android·架构·android jetpack
通玄2 天前
Jetpack Compose 入门系列(七):ViewModel 与界面状态管理
android
落魄Android在线炒饭2 天前
Android Framework 开发技巧:android.jar 生成与系统快速编译验证
android
如此风景2 天前
Kotlin Flow操作符学习
android·kotlin