Android原生获取经纬度位置信息

Android原生获取经纬度位置信息前言 因为项目中经常会遇到要上传一系列设备信息的功能 为了方便使用 所以就拆分成以下系列文章来单独介绍如何获取各类设备信息 手机运营商获取 AndroidID IMEI OAID 获取 地理位置信息经纬度获取 公网 IP 地址获取 移动网络 IP Wifi IP Build 类获取相关设备信息 屏幕相关信息 密度 物理尺寸获取

大家好,我是讯享网,很高兴认识大家。

前言

因为项目中经常会遇到要上传一系列设备信息的功能,为了方便使用,所以就拆分成以下系列文章来单独介绍如何获取各类设备信息

  • 手机运营商获取
  • AndroidID、IMEI、OAID获取
  • 地理位置信息经纬度获取
  • 公网IP地址获取:移动网络IP、Wifi IP
  • Build类获取相关设备信息
  • 屏幕相关信息:密度、物理尺寸获取
  • BuildConfig获取的一系列基础信息
  • UA、网络状态…等持续更新

1. 基础学习

在介绍之前,先讲一些获取经纬度信息相关的基础知识

1.1 LocationManager

位置管理器

想要获取经纬度信息,主要是通过LocationManager这个类,该类不能直接new,需要通过如下方式获取

val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager 

讯享网

获取位置信息是通过该类的getLastKnownLocation(provider:String)方法,可以看到,使用此方法需要我们传递个provider,位置提供器。

1.2 LocationProvider

位置提供器

位置提供器一共有三种

  • NETWORK_PROVIDER:通过蜂窝塔(基站)和WIFI接入点来获取
  • GPS_PROVIDER:通过GPS的方式获取
  • PASSIVE_PROVIDER:被动的通过其他程序获取经纬度
讯享网locationManager.getProviders(true) 

该方法会返回一个手机所支持的位置提供器集合

1.3 精度

假如我们通过以上三种provider都能获取到Location,那么选哪种作为经纬度最合适呢?


讯享网

Location有getAccuracy()方法来获取精度,看官方getAccuracy()的解释:

/ * Get the estimated horizontal accuracy of this location, radial, in meters. * * <p>We define horizontal accuracy as the radius of 68% confidence. In other * words, if you draw a circle centered at this location's * latitude and longitude, and with a radius equal to the accuracy, * then there is a 68% probability that the true location is inside * the circle. * * <p>This accuracy estimation is only concerned with horizontal * accuracy, and does not indicate the accuracy of bearing, * velocity or altitude if those are included in this Location. * * <p>If this location does not have a horizontal accuracy, then 0.0 is returned. * All locations generated by the {@link LocationManager} include horizontal accuracy. */ 

简单的理解就是:

若以该经纬度作为圆心,精度作为半径画圆,那么真实的位置落在该圆内的概率为68%。因为落在该圆内的概率是固定的68%,那么肯定是圆的半径即精度越小,就越准确。所以我们选取getAccuracy()返回值最小的那个provider。

1.4 LocationListener

有时候可能会因为没有网或者在室内,通过以上方式获取到的location均为null,那么此时我们可以开启位置信息的连续监听,当时间超过设定的秒数或者位置移动超过设定的米数时,更新位置信息。

讯享网private var locationListener: LocationListener = object : LocationListener { 
    override fun onLocationChanged(location: Location) { 
    Log.i(TAG, "onLocationChanged: 经纬度发生变化") //调用更新位置 updateToNewLocation(location) } override fun onProviderDisabled(provider: String) { 
    updateToNewLocation(null) Log.i(TAG, "onProviderDisabled: ") } override fun onProviderEnabled(provider: String) { 
    Log.i(TAG, "onProviderEnabled: ") } } 
locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 60000.toLong(), //每隔1分钟重新获取一次 8.toFloat(), //移动距离超过8米重新获取一次 locationListener ) 

2. 所需权限

权限 说明
INTERNET 允许使用网络
ACCESS_FINE_LOCATION 允许使用GPS定位
ACCESS_COARSE_LOCATION 允许使用WIFI热点或基站来获取粗略的定位

3. 获取步骤

3.1 申请权限

只有申请到了ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION后,才可以进行下一步获取经纬度信息的操作,这里不多讲,完整代码如下:

讯享网class LocationActivity : AppCompatActivity() { 
    companion object { 
    const val LOCATION_REQUEST_CODE = 1 const val LISTENER_REQUEST_CODE = 2 } override fun onCreate(savedInstanceState: Bundle?) { 
    //申请权限 if (PermissionUtil.requestPermission(LOCATION_REQUEST_CODE, permissionList.toList(), this)) { 
    //获取经纬度信息 getLocationInfo() } } / * 权限申请回调 */ override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { 
    //LOCATION_REQUEST_CODE权限申请 LOCATION_REQUEST_CODE -> { 
    if (PermissionUtil.verifyResult(grantResults, this)) { 
    getLocationInfo() } else { 
    Toast.makeText(this, "没有权限", Toast.LENGTH_SHORT).show() } } } } } 
object PermissionUtil { 
    / * 验证是否有权限,没有则申请 */ fun requestPermission(requestCode: Int, permissionList: List<String>, context: Context): Boolean { 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
    //没有同意需要申请的权限 val requestPermissionList = mutableListOf<String>() for (permission in permissionList) { 
    if (ContextCompat.checkSelfPermission( context, permission ) != PackageManager.PERMISSION_GRANTED ) { 
    requestPermissionList.add(permission) } } if (requestPermissionList.size > 0) { 
    ActivityCompat.requestPermissions( context as Activity, requestPermissionList.toTypedArray(), requestCode ) return false } else { 
    return true } } else { 
    return true } } / *验证权限申请的结果 */ fun verifyResult(grantResults: IntArray,context: Context): Boolean { 
    if (grantResults.isNotEmpty()) { 
    for (result in grantResults) { 
    if (result != PackageManager.PERMISSION_GRANTED) { 
    Toast.makeText(context, "必须同意所有权限才能使用该功能", Toast.LENGTH_SHORT).show() return false } } return true } else { 
    Toast.makeText(context, "发生未知错误", Toast.LENGTH_SHORT).show() return false } } } 

3.2 获取经纬度信息

在申请到权限后,进行如下操作来获取经纬度信息

  • 判断是否开启位置服务,没有则跳转至系统设置打开定位服务

    判断定位服务有没有开启主要通过以下方法

    讯享网var gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) 

    当返回true,代表GPS定位服务开启,NETWORK_PROVIDER同理

  • 获取所有支持的provider,然后通过provider来获取定位信息
  • 当返回true,代表GPS定位服务开启,NETWORK_PROVIDER同理
  • 若所支持的provider获取到的经纬度均为空,则开启连续定位监听

完整代码如下:

fun getLocationInfo() { 
    //判断是否开启位置服务,没有则跳转至设置来开启 if (isLocationServiceOpen()) { 
    //获取所有支持的provider val providers = locationManager.getProviders(true) //用来存储最优的结果 var betterLocation: Location? = null for (provider in providers) { 
    val location = locationManager.getLastKnownLocation(provider) location?.let { 
    Log.i(TAG, "$provider 精度为:${ 
     it.accuracy}") if (betterLocation == null) { 
    betterLocation = it } else { 
    //因为半径等于精度,所以精度越低代表越准确 if (it.accuracy < betterLocation!!.accuracy) betterLocation = it } } if (location == null) { 
    Log.i(TAG, "$provider 获取到的位置为null") } } betterLocation?.let { 
    Log.i(TAG, "精度最高的获取方式:${ 
     it.provider} 经度:${ 
     it.longitude} 纬度:${ 
     it.latitude}") } //(四)若所支持的provider获取到的位置均为空,则开启连续定位服务  if (betterLocation == null) { 
    for (provider in locationManager.getProviders(true)) { 
    locationMonitor(provider) } Log.i(TAG, "getLocationInfo: 获取到的经纬度均为空,已开启连续定位监听") } } else { 
    Toast.makeText(this, "请跳转到系统设置中打开定位服务", Toast.LENGTH_SHORT).show() } } / * 判断定位服务是否开启 */ private fun isLocationServiceOpen(): Boolean { 
    var gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) var network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) //有一个开启就可 return gps || network } 

3.2 开启连续监听

在1.4中我们已经讲了LocationListener,如何开启连续监听,这里就不再详细讲述

具体代码如下

讯享网fun locationMonitor(provider: String) { 
    if (PermissionUtil.requestPermission( LISTENER_REQUEST_CODE, permissionList.toList(), this ) ) { 
    locationManager.requestLocationUpdates( provider, 60000.toLong(), //超过1分钟则更新位置信息 8.toFloat(), //位置超过8米则更新位置信息 locationListener ) } } 

4. 总结

以上就是安卓原生获取经纬度信息的全部内容,如果通过以上方法都获取不到的话,那就使用高德或百度等第三方SDK吧。

如果本文对你有帮助,请别忘记点赞start,如果有不恰当的地方也请提出来,下篇文章见。

关注公众号,回复 原生经纬度 获取文章源码
在这里插入图片描述

项目地址

5. 参考文章

10.14 Android GPS初涉 | 菜鸟教程 (runoob.com)

小讯
上一篇 2025-02-06 16:27
下一篇 2025-01-19 13:58

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/38436.html