使用Android 原生LocationManager获取经纬度

一、常用方案

1、使用LocationManager GPS和网络定位

缺点:个别设备,室内或者地下停车场获取不到gps定位,故需要和网络定位相结合使用

2、使用Google Play服务

这种方案需要Android手机中有安装谷歌服务,然后导入谷歌的第三方库:

例如:implementation 'com.google.android.gms:play-services-location:20.0.0'

缺点:一些厂商可能会阉割掉谷歌服务

3、使用第三方地图定位

缺点:该方法准确度较高,但需要在第三方平台注册账号和集成key

这里介绍第一种方案,如果获取不到gps,先通过网络定位获取,然后再尝试去获取gps

博主这里就遇到同一个地方,小米可以通过gps获取到数据,但一加的两个手机,都无法通过gps获取到经纬度,故只能先从网络获取经纬度

二、方案实现

class LocationManagerUtil {

    val TAG: String = "LocationManagerUtil_"
    var mLocationManager:LocationManager?=null
    var mLocationListener:LocationListener?=null
    var isSendLocation=true

    companion object {
        private var singleInstance: LocationManagerUtil? = null
            get() {
                // 懒汉模式
                if (null == field) {
                    field = LocationManagerUtil()
                }
                return field
            }

        @Synchronized // 添加注解,线程同步,线程安全
        fun getInstance(): LocationManagerUtil {
            return singleInstance!!
        }
    }



     fun registerListener(callback: LocationCallback){
         isSendLocation=true
         unRegisterListener()

         mLocationManager = WebrtcSdkApplication.instance.getSystemService(Context.LOCATION_SERVICE) as LocationManager?

         mLocationListener = object : LocationListener {
             override fun onLocationChanged(location: Location) {
                 if(location!=null){
                     // 当位置发生变化时调用
                     val latitude = location.latitude
                     val longitude = location.longitude
                     val provider=location.provider
                     // 使用位置信息
                     XLogUtil.d("${TAG}onLocationChanged longitude:$longitude,,,latitude:$latitude")

                     //在室内或者地下室,gps可能会获取不到地位,这时先根据网络定位,待获取到gps值后,关闭监听
                     if(provider==LocationManager.GPS_PROVIDER){
                         isSendLocation=false
                         unRegisterListener()
                         callback.onLocationChanged(longitude,latitude)
                     }else if(provider==LocationManager.NETWORK_PROVIDER){
                         if(isSendLocation){
                             callback.onLocationChanged(longitude,latitude)
                         }
                         isSendLocation=false
                     }

                 }else{
                     XLogUtil.d("${TAG}onLocationChanged location==null")
                 }
             }

             override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
                 // 当GPS状态改变时调用
             }

             override fun onProviderEnabled(provider: String) {
                 // 当选中的位置提供者被激活时调用
             }

             override fun onProviderDisabled(provider: String) {
                 // 当选中的位置提供者被停用时调用
             }
         }

         if (ActivityCompat.checkSelfPermission(
                 WebrtcSdkApplication.instance,
                 Manifest.permission.ACCESS_FINE_LOCATION
             ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                 WebrtcSdkApplication.instance,
                 Manifest.permission.ACCESS_COARSE_LOCATION
             ) != PackageManager.PERMISSION_GRANTED
         ) {
            //Toast.makeText(WebrtcSdkApplication.instance,WebrtcSdkApplication.instance.getString(R.string.please_enable_location_permissions_in_settings),Toast.LENGTH_SHORT).show()

             XLogUtil.d("${TAG}checkSelfPermission 定位权限未授权")
         }

         mLocationManager?.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 5f,
             mLocationListener!!
         )//更新间隔1000毫秒,距离间隔5米

         mLocationManager?.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000L, 5f,
             mLocationListener!!
         )//更新间隔1000毫秒,距离间隔5米
    }

    fun unRegisterListener(){
        if(mLocationListener!=null){
            mLocationManager?.removeUpdates(mLocationListener!!)
            mLocationManager=null
            mLocationListener=null
        }
    }

}

三、相关权限

  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" 
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" 
    <uses-permission android:name="android.permission.INTERNET" />

    <!--定位权限-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
   <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"/>



 //以下两个权限需要动态申请权限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

四、判断是否打开了gps

    val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            // 提示用户开启GPS
            val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
            startActivity(intent)
        }

五、获取的经纬度在不同地图上显示不一致问题解答

GPS获得的经纬度所用的坐标系和谷歌地图、百度地图上的坐标系是不同的,GPS硬件获得的经纬度是WGS-84标准,国际通用,
可以看成是正常的GPS位置,在google earth上全部坐标,谷歌地图上除中国以外的坐标均为这个标准,但是谷歌地图的中国坐标使用的是GCJ-02标准,
是天朝测绘局在WGS-84的基础上加入随机偏差加密后的一种经纬度,会随机偏移一公里左右,所以导致无论怎样定位总是显示不对。
而百度地图在GCJ-02上又加入了自己的加密算法,变成了BD-09标准,另外其他很多的地图都有自己的加密方法。
这些都是硬件获取经纬度在地图上指示不对的原因,网上有免费做转换的网站,
在这里推荐一个:http://map.yanue.NET/gps.html,如果发现GPS定位结果总是有误差,可以用这个转换一下

经纬度转换为地点:【经纬度查询】在线地图经度纬度查询|经纬度地名坐标转换

在 SQL Server 中,`EXISTS` 是一个用于检查是否存在符合特定条件的记录的逻辑运算符。`EXISTS` 返回一个布尔值,即 `TRUE` 或 `FALSE`,表示查询结果集是否包含匹配条件的记录。下面是 `EXISTS` 的详细用法: 1. 基本语法: ```sql SELECT column_name(s) FROM table_name WHERE EXISTS (SELECT column_name FROM table_name WHERE condition); ``` 2. 示例: 假设有两个表,分别为 `customers` 和 `orders`, `customers` 表中包含了所有客户的信息,而 `orders` 表中包含了所有的订单信息。我们需要查询所有已经下过订单的客户的姓名和地址,可以使用以下 SQL 语句: ```sql SELECT customerName, address FROM customers WHERE EXISTS (SELECT * FROM orders WHERE orders.customerID = customers.customerID); ``` 在上面的 SQL 语句中,`EXISTS` 子查询中的条件是查找 `orders` 表中的所有记录,其中 `orders.customerID = customers.customerID` 表示连接两个表的条件,即匹配两个表中的 `customerID` 列。如果 `EXISTS` 子查询返回 `TRUE`,则 `customerName` 和 `address` 列的值会被返回。 3. 注意事项: - `EXISTS` 子查询必须包含一个 `SELECT` 语句,该语句必须返回一个结果集。 - `EXISTS` 子查询中的条件必须使用外部查询中的列或表。 - `EXISTS` 子查询中的 `SELECT` 语句可以是任何有效的 T-SQL 查询语句,包括 `SELECT *`。 - `EXISTS` 子查询中的条件可以包含任何有效的 T-SQL 表达式和运算符。 - `EXISTS` 的性能比使用 `JOIN` 进行连接查询要高,特别是在查询大型数据集时。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

粤M温同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值