使用 Kotlin 获取当前 GPS 位置(仅一次)

问题描述 投票:0回答:2

我希望我的 Kotlin 应用程序仅在用户请求时获取当前准确的 (GPS) 位置一次。

到目前为止我一直在使用

fusedLocationClient.lastLocation
。这通常是成功的,但有时,即使 Google 地图和同一手机上运行的另一个应用程序具有准确的 GPS 位置,该应用程序也会返回一个遥远的位置(有时是一两英里)。

我尝试使用如何在 Kotlin 中使用“fusedLocationClient.getCurrentLocation”方法获取位置?中的代码来实现 getCurrentLocation 方法。但是,Android Studio 在

fusedLocationClient.getCurrentLocation(PRIORITY_HIGH_ACCURACY, object : CancellationToken()

报告错误

说我应该:

“重命名参考”

“为‘FusedLocationProviderClient.getCurrentLocation’创建扩展函数”

是否可以强制

lastLocation
方法使用GPS位置? (在清单中,我只包含了
ACCESS_FINE_LOCATION
权限,但这似乎不起作用。)

如果不行,谁能告诉我如何为

getCurrentLocation
方法创建扩展函数?我在网上没有找到任何例子。


编辑,按照 Gabe Sechan 的回答

虽然 Google Play 服务提供的 FusedLocation 通常被认为是 Google 更喜欢的,但不能依赖它来提供最准确的可用位置,正如 Gabe Sechan 在他的回答中评论的那样。

因此,出于我的目的,我转向了imthegaga在他在Android位置管理器,获取GPS位置的答案中提供的代码,如果没有GPS,则获取网络提供商位置 - 堆栈内存溢出。此代码使用 Android 位置类从 GPS 提供商(如果可用)和网络提供商(如果可用)获取最后的已知位置,如果两者都可用,则返回更准确的位置。

android kotlin location fusedlocationproviderclient
2个回答
1
投票

好吧,这里有一些令人困惑的概念。

1) 融合位置不是 GPS。可以是,但也可能不是。 Fused 是一种将 GPS(高功耗、慢锁定)与网络(低功耗、需要服务器协助)结合起来的尝试,以提供准确性和功耗的结合。如果你想要 GPS,你需要使用 Android 位置类,而不是 Google Play FusedLocation 东西(好处是即使你的设备上没有 Google Play,Android 东西也能工作)。

2)lastLocation 返回缓存的位置。它不会更新位置,也不会获取当前位置。它返回上次打开定位功能时的位置。它可能非常旧,或者如果没有缓存数据则可能为空。这是一种优化,仅当您知道自己在做什么并且不需要最新数据时才应使用。如果这样做,您需要使用 requestLocationUpdates,它实际上打开位置子系统并找到位置。


0
投票

花了几个小时后,我解决了当前的位置问题。我已将代码分离到一个单独的类中。您可以使用以下课程来获取当前位置。

public class LocationTracker {

    public static void getCurrentLocation(
            @NonNull Context context,
            OnLocationChangeListener onLocationChangeListener
    ) {
        LocationManager locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
        AtomicBoolean foundLocation = new AtomicBoolean(false);
        Consumer<Location> locationConsumer = location -> {
            if (!foundLocation.get()) {
                foundLocation.set(true);
                if (location != null) {
                    onLocationChangeListener.onComplete(getLatLng(location));
                } else {
                    onLocationChangeListener.onComplete(new LatLng(0.0, 0.0));
                }
            }
        };
        registerLocationCallbackListener(locationManager, LocationManager.GPS_PROVIDER, locationConsumer);
        registerLocationCallbackListener(locationManager, LocationManager.NETWORK_PROVIDER, locationConsumer);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            registerLocationCallbackListener(locationManager, LocationManager.FUSED_PROVIDER, locationConsumer);
        }
    }

    private static void registerLocationCallbackListener(
            LocationManager locationManager, String networkProvider, Consumer<Location> locationConsumer
    ) {
        LocationManagerCompat.getCurrentLocation(locationManager, networkProvider,
                new CancellationSignal(), Executors.newSingleThreadExecutor(), locationConsumer
        );
    }

    @NonNull
    private static LatLng getLatLng(@NonNull Location location) {
        return new LatLng(location.getLatitude(), location.getLongitude());
    }

    public interface OnLocationChangeListener {
        void onComplete(LatLng latLng);
    }
}

用法

LocationTracker.getCurrentLocation(context, new OnLocationChangeListener() {
        @Override
        public void onComplete(LatLng latLng) {

        }
    }
);
© www.soinside.com 2019 - 2024. All rights reserved.