Android - 像 Google 地图一样准确获取坐标

Android - get coordinates accurately like Google Maps

如何像 Google 地图一样准确获取当前坐标?

到目前为止,我已经使用了 getLastLocation - 它有效,但我得到了相同 20 米区域的相同坐标 - 它不是那么准确。在 Google 地图中,您可以看到大约 3 米的精度。我怎样才能做到这一点?

我只对坐标感兴趣

您需要做一些事情。确保你有权限,确保用户有他的 GPS 启用与否。您需要制作一个位置管理器和一个位置侦听器,每次更改时都会更新。请参阅下面的不同代码。

将此添加到清单文件以获取权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

创建位置管理器

LocationManager locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);

检查 GPS 是否开启

try {
    gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {}

try {
    network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {}
if(!gps_enabled && !network_enabled){
// It's not enabled address the problem here
}

创建监听器

LocationListener locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 5000, 10, locationListener);

侦听器Class示例代码

/*---------- Listener class to get coordinates ------------- */
private class MyLocationListener implements LocationListener {

    @Override
    public void onLocationChanged(Location loc) {
        editLocation.setText("");
        pb.setVisibility(View.INVISIBLE);
        Toast.makeText(
                getBaseContext(),
                "Location changed: Lat: " + loc.getLatitude() + " Lng: "
                    + loc.getLongitude(), Toast.LENGTH_SHORT).show();
        String longitude = "Longitude: " + loc.getLongitude();
        Log.v(TAG, longitude);
        String latitude = "Latitude: " + loc.getLatitude();
        Log.v(TAG, latitude);

        /*------- To get city name from coordinates -------- */
        String cityName = null;
        Geocoder gcd = new Geocoder(getBaseContext(), Locale.getDefault());
        List<Address> addresses;
        try {
            addresses = gcd.getFromLocation(loc.getLatitude(),
                    loc.getLongitude(), 1);
            if (addresses.size() > 0) {
                System.out.println(addresses.get(0).getLocality());
                cityName = addresses.get(0).getLocality();
            }
        }
catch (IOException e) {
            e.printStackTrace();
        }
        String s = longitude + "\n" + latitude + "\n\nMy Current City is: "
            + cityName;
        editLocation.setText(s);
    }

    @Override
    public void onProviderDisabled(String provider) {}

    @Override
    public void onProviderEnabled(String provider) {}

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {}
}

用户授予位置权限后,您可以执行以下操作。 1- 要求用户启用 GPS 以获得高精度位置 2- 使用 fusedLocationProviderClient.getCurrentLocation() 方法获取用户当前位置

private fun askToEnableGPS() {
        LocationServices.getSettingsClient(requireActivity())
            .checkLocationSettings(
                LocationSettingsRequest.Builder()
                    .addLocationRequest(LocationRequest.create().apply {
                        priority = LocationRequest.PRIORITY_HIGH_ACCURACY
                    }).build()
            )
            .addOnSuccessListener {
                //  GPS is already enable, callback GPS status through listener
                getCurrentUserLocation()
            }
            .addOnFailureListener { e ->
                when ((e as ApiException).statusCode) {
                    LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {
                        // system open location
                        val rae = e as ResolvableApiException
                        launchGPS.launch(IntentSenderRequest.Builder(rae.resolution).build())

                    } catch (sie: IntentSender.SendIntentException) {
                        Log.i(
                            TAG,
                            "PendingIntent unable to execute request."
                        )
                        viewModel.handleNoGPS()
                    }
                    LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                        Log.i(
                            TAG,
                            "SETTINGS CHANGE UNAVAILABLE"
                        )
                        viewModel.handleNoGPS()
                    }
                }

            }
    }

    private val launchGPS =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
            if (result.resultCode == AppCompatActivity.RESULT_OK) {
                getCurrentUserLocation()
            } else {
                MaterialAlertDialogBuilder(requireContext())
                    .setMessage(getString(R.string.gps_in_need_message))
                    .setPositiveButton(getString(R.string.confirm)) { dialog, _ ->
                        dialog.dismiss()
                        // retry here asking for GPS permission
                    }
                    .setNegativeButton(getString(R.string.get_default)) { dialog, _ ->
                        dialog.dismiss()
                        viewModel.handleNoGPS()
                    }
                    .setCancelable(false)
                    .show()
            }
        }

    fun getCurrentUserLocation() {
        fusedLocationProviderClient.getCurrentLocation(
            LocationRequest.PRIORITY_HIGH_ACCURACY,
            object : CancellationToken() {
                override fun isCancellationRequested(): Boolean = false

                override fun onCanceledRequested(p0: OnTokenCanceledListener): CancellationToken =
                    this

            }
        )
            .addOnSuccessListener {
                // here is user current location
                viewModel.setSelectedByLocation(it.longitude, it.latitude)

            }
            .addOnFailureListener {
                MaterialAlertDialogBuilder(requireContext())
                    .setMessage(getString(R.string.failed_to_get_current_location))
                    .setPositiveButton(getString(R.string.retry)) { dialog, _ ->
                        dialog.dismiss()
                        // retry getCurrentUserLocation or askToEnableGPS
                    }
                    .setNegativeButton(getString(R.string.get_default)) { dialog, _ ->
                        dialog.dismiss()
                        // handle failure in getting current location
                    }
                    .setCancelable(false)
                    .show()
            }
    }