如何使用 FusedLocationProviderClient 获取准确的位置(纬度和经度)

Posted

技术标签:

【中文标题】如何使用 FusedLocationProviderClient 获取准确的位置(纬度和经度)【英文标题】:How to get accurate Location (Latitude & Longitude) using FusedLocationProviderClient 【发布时间】:2018-11-08 19:52:37 【问题描述】:

嗨,我正在使用 FusedLocationClient 从用户那里获取位置。它的工作我能够定期获取纬度和经度,但有时显示错误的距离会在几秒钟内从 10.0 变为 200.0,然后返回10.0。我想向用户展示他们距离商店 200m。但即使他们距离商店只有 10m,应用程序有时也会显示他们距离商店 200m。

我能做些什么来提高定位客户端的准确性。

   class LocServices : Service()  
        private val TAG = ""
        private val UPDATE_INTERVAL_IN_MILLISECONDS: Long = 5000
        private val FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2

        private var mLocationRequest: LocationRequest? = null
        private var mFusedLocationClient: FusedLocationProviderClient? = null
        private var mLocationCallback: LocationCallback? = null
        private var mLocation: Location? = null

        var existLongitude: String? = null
        var existLatitude: String? = null
        var sharedPrefs: SharedPreferences? = null

        override fun onCreate() 
            mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
            mLocationCallback = object : LocationCallback() 
                override fun onLocationResult(locationResult: LocationResult?) 
                    super.onLocationResult(locationResult)
                    onNewLocation(locationResult!!.lastLocation)
                
            
            createLocationRequest()
            getLastLocation()
            requestLocationUpdates()
        

        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int 
            Log.i(TAG, "Service started")
            return Service.START_STICKY
        

        override fun onBind(intent: Intent): IBinder? 
            return null

        

        private fun requestLocationUpdates() 

         sharedPrefs = this.getSharedPreferences("GEO", Context.MODE_PRIVATE)
            if (sharedPrefs != null) 
                existLatitude = sharedPrefs!!.getString("LAT", null)
                existLongitude = sharedPrefs!!.getString("LONG", null)
            

                    if (existLatitude != null && existLongitude != null) 
                        Log.i(TAG, "Requesting location updates")
                        setRequestingLocationUpdates(this, true)
                        try 
                            mFusedLocationClient!!.requestLocationUpdates(mLocationRequest, mLocationCallback!!, Looper.myLooper())
                         catch (unlikely: SecurityException) 
                            setRequestingLocationUpdates(this, false)
                            Log.e(TAG, "Lost location permission. Could not request updates. $unlikely")
                        
                    


        
        private fun getLastLocation() 
            try 
                mFusedLocationClient!!.lastLocation
                        .addOnCompleteListener  task ->
                            if (task.isSuccessful && task.result != null) 
                                mLocation = task.result
                             else 
                                Log.w(TAG, "Failed to get location.")
                            
                        
             catch (unlikely: SecurityException) 
                Log.e(TAG, "Lost location permission.$unlikely")
            

        

        private fun onNewLocation(location: Location) 
            Log.i(TAG, "New location: $location")
            mLocation = location


                    if (existLatitude != null && existLongitude != null) 
                        val selected_location = Location("locationA")
                        selected_location.latitude = existLatitude!!.toDouble()
                        selected_location.longitude = existLongitude!!.toDouble()
                        val near_locations = Location("locationB")
                        near_locations.latitude = mLocation!!.latitude
                        near_locations.longitude = mLocation!!.longitude
                        val distance = selected_location.distanceTo(near_locations)
                        Toast.makeText(this, distance.toString(), Toast.LENGTH_SHORT).show()
                        if (distance > 53.0) 
                            Toast.makeText(this, "You are outside $distance", Toast.LENGTH_SHORT).show()
                        
                    
                

        private fun createLocationRequest() 
            mLocationRequest = LocationRequest()
            mLocationRequest!!.interval = UPDATE_INTERVAL_IN_MILLISECONDS
            mLocationRequest!!.fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS
            mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        

       companion object 

            val KEY_REQUESTING_LOCATION_UPDATES = "requesting_locaction_updates"

            fun setRequestingLocationUpdates(context: Context, requestingLocationUpdates: Boolean) 
                PreferenceManager.getDefaultSharedPreferences(context)
                        .edit()
                        .putBoolean(KEY_REQUESTING_LOCATION_UPDATES, requestingLocationUpdates)
                        .apply()
            
        

    

【问题讨论】:

【参考方案1】:

我认为从 GPS 计算距离的最佳方法是计算两个位置之间的距离并相加。计算两个位置之间的距离 -

 public static double GetDistanceInMeter(Location source, Location destination) 
    double distance = 0d;
    if (source != null && destination != null) 
        double lat1 = source.getLatitude();
        double lon1 = source.getLongitude();
        double lat2 = destination.getLatitude();
        double lon2 = destination.getLongitude();

        final int R = 6371;
        // Radius of the earth in km
        double dLat = deg2rad(lat2 - lat1);
        // deg2rad below
        double dLon = deg2rad(lon2 - lon1);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        // Distance in m
        distance = (R * c) * 1000;
    
    return distance;

方法是保存以前的位置,然后计算新旧之间的距离,然后将其添加到总距离中。这是解决此问题的最佳方法,也是最准确的方法。由于 GPS 不是那么准确,因此您的总行驶距离将是 +-50 米。

【讨论】:

我已经编辑了问题,问题不在于距离计算,您的方法给出的结果与“float distanceTo(Location dest)”相同。我认为进出建筑物时,latlong值会变为50m以上。会发生这种情况还是我的实施有误?

以上是关于如何使用 FusedLocationProviderClient 获取准确的位置(纬度和经度)的主要内容,如果未能解决你的问题,请参考以下文章

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等