如何通过点击在 Android 中获得准确的 GPS 位置

Posted

技术标签:

【中文标题】如何通过点击在 Android 中获得准确的 GPS 位置【英文标题】:How to get exact GPS position in Android on click 【发布时间】:2021-06-10 08:48:37 【问题描述】:

我试图通过单击按钮获得准确的 GPS 位置。我正在使用 fusesLocationProviderClient 并拥有 FINE_LOCATION 权限。

private void getCurrentGPSLocation() 
   // get the new location from the fused client
   // update the UI - i.e. set all properties in their associated text view items

   //Initialize new location request
        LocationRequest locationRequest = new LocationRequest()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(10000)
                .setFastestInterval(1000)
                .setNumUpdates(1);
  //Initialize location call back
        LocationCallback locationCallback = new LocationCallback() 
            @Override
            public void onLocationResult(LocationResult locationResult) 
                //Initialize location1
                Location location1 = locationResult.getLastLocation();
   //Set Accuracy
            double accura1 = location1.getAccuracy();
;
        //Request location updates
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
            return;
        
        fusedLocationProviderClient.requestLocationUpdates(locationRequest
                , locationCallback, Looper.myLooper());
    

然后我从 location1 变量中获取坐标,因为我从中获得了准确性。问题是这非常不精确,因为我得到的精度为 800-1000m。在打开 GoogleMaps 几秒钟后返回到我的应用程序调用 getLastLocation();使用另一个按钮(不是我的代码示例的一部分),我的精度为 4-5m。再次使用我的代码时,精度再次为 800-1000m。 所以我的问题是,如何更改我的代码以在我的 getCurrentGLSLpcation() 方法中获得这种准确性。

【问题讨论】:

去掉.setNumUpdates(1),设置.setInterval(5000),.setFastestInterval(4000) 然后等待onLocationResult 5或10s,效果会更好。 感谢您的回复。我实际上被困在如何将 onLocationResult 的延迟放入我的代码中。我发现了这个:link 但我不知道如何将处理程序放入我的代码中。你能帮帮我吗? new Handler().postDelayed(new Runnable() @Override public void run() //在这里调用你的函数。 , mInterval); 【参考方案1】:

我正在使用此代码获取位置,使用 FusedLocationProviderClient 及其提供的几乎准确的位置,最高可达 5..7 米

try 
   
        Task<Location> locationResult = mFusedLocationClient.getLastLocation();
        locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() 
            @Override
            public void onComplete(@NonNull Task<Location> task) 
                if (task.isSuccessful()) 
                  Location  location = task.getResult();
                    if (location != null) 
                        
                        //fo your job
                        
                     else 
                        Toast.makeText(context, "Please on GPS", Toast.LENGTH_SHORT).show();
                    
                
                else 
                    Toast.makeText(context, "error:"+task.getException().getMessage(), Toast.LENGTH_SHORT).show();
                
            
        );
    
 catch (SecurityException e) 
    Log.e("Exception: %s", e.getMessage(), e);

【讨论】:

这不是简单地获取最后一个位置而不触发新的位置请求吗?正如我所说,在启动 GoogleMaps 一次以强制更新精确位置后,我有另一个按钮精确显示最后一个已知位置。我需要在我的代码中有这样一个精确的新位置请求。【参考方案2】:

在尝试了您的想法后,我找到了解决方案:

 private void getCurrentGPSLocation() 
        // get the new location from the fused client
        // update the UI - i.e. set all properties in their associated text view items

        //Initialize new location request
        LocationRequest locationRequest = new LocationRequest()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(2500)
                .setFastestInterval(2000)
                .setNumUpdates(8);

        //Initialize location call back
        LocationCallback locationCallback = new LocationCallback() 
            @Override

            public void onLocationResult(LocationResult locationResult) 
                //Initialize location1
                Location location1 = locationResult.getLastLocation();
                //Set latitude
                tvLatitude.setText(String.valueOf(location1.getLatitude()));
                //Set longitude
                tvLongitude.setText(String.valueOf(location1.getLongitude()));
                //Set Accuracy
                double accura1 = location1.getAccuracy();
                tvAccuracy.setText(new DecimalFormat("##.##").format(accura1) + " m");
                //Set Altitude
                double altit1 = location1.getAltitude();
                tvAltitude.setText(new DecimalFormat("##.##").format(altit1) + " m");

                //Get Adress
                double longitude1 = location1.getLongitude();
                double latitude1 = location1.getLatitude();
                Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
                try 
                    List<Address> listAddresses = geocoder.getFromLocation(latitude1, longitude1, 1);
                    if (null != listAddresses && listAddresses.size() > 0) 
                        String _Location1 = listAddresses.get(0).getAddressLine(0);
                        //Set Location
                        tvLocation.setText(String.valueOf(_Location1));
                    
                 catch (IOException e) 
                    e.printStackTrace();
                

                //Set Update Time
                TextView textView = findViewById(R.id.tv_update);
                SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy 'um ' HH:mm:ss z");
                String currentDateandTime = sdf.format(new Date());
                textView.setText(currentDateandTime);


            

        ;
        //Call method to insert data into database
        (new Handler()).postDelayed(this::OnReg, 30000);
        //OnReg();
        //Call Method to save data in SharedPreferences
        (new Handler()).postDelayed(this::saveData, 30000);
        //saveData();
        //call Method to save data in Internal File
        (new Handler()).postDelayed(this::saveToFile, 30000);
        //saveToFile();
        //Request location updates
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
            return;
        
        fusedLocationProviderClient.requestLocationUpdates(locationRequest
                , locationCallback, Looper.myLooper());
    

所以这是从该位置更新文本视图的完整代码。基本上,在获取最后一个也是最精确的位置来调用我的方法之前,我有 8 个位置更新,这些方法将位置保存在数据库 (OnReg)、内部文件 (saveToFile) 和 SharedPreferences(saveData) 中。这些方法的调用延迟 30 秒,以确保位置准确。

【讨论】:

以上是关于如何通过点击在 Android 中获得准确的 GPS 位置的主要内容,如果未能解决你的问题,请参考以下文章

Android:无法获得准确的经纬度值

如何在android中处理音频(.3gp)文件[关闭]

如何获得 SKShapeNode 的准确触摸位置?

如何在 android 中获得 ClusterManager 点击和 ClusterManager 项目点击

为了在 Android 中获得更准确的位置结果,使用 FusedLocationApi 和 FusedLocationProviderClient 哪个?

如何在Android中获得气压高度?