像 Google 一样跟踪用户位置

Track user location like Google does

我正在开发一个必须跟踪用户位置并将其发送到远程服务器的应用程序。我知道这里已经有很多其他问题,但我找不到我需要的东西。

基本上我使用 FusedLocationProviderApi 来接收位置更新。它非常有用且易于使用。问题是我需要非常频繁地查询位置并且它会很快耗尽电池电量(尽管可能部分电池使用来自网络操作以将位置发送到服务器)。但是,我只需要在用户移动时频繁更新。

所以我正在寻找类似 Google 的东西来跟踪 Android 用户(正如我们在 LocationHistory 中看到的那样)。有谁知道 Google 从智能手机获取的位置是否在某处可用?或者也许是实施类似措施的策略?

您可以根据需要使用 LocationRequest..

LocationRequest location= new LocationRequest();

我确定构造函数接受了一个值..查看 android 文档。

因此,对于位置请求,您可以使用

等功能

设置间隔,设置最小位移,每隔几秒或几米就获取位置。

您还可以为此实现一个位置侦听器,每次获取新位置时都会调用它。

最后您要做的就是从融合 api 请求位置更新并将请求作为参数传递。

您可以使用 FusedLocationProviderApi 来通知您位置更改,而不是查询当前位置。

您可能想使用 requestLocationUpdates,特别是 this version,它最适合用于后台任务。 在 LocationRequest 中,您可以使用 setInterval 来定义更新间隔。

关于电池消耗:显然,不断打开网络套接字(或保持打开状态)以发送您的位置数据并不是最佳解决方案。您的应用应确定何时实际需要向您的服务器发送更新。

Google 不提供 API 来直接拉取 LocationHistory,这是他们自己保留的东西。可以查询kml位置文件并阅读,但更不适合实时监控。

降低电池消耗的建议,您可以使用 Activity 检测来确定您需要多久确定一次位置。在这方面,我可以推荐 https://github.com/mcharmas/Android-ReactiveLocation,我在 Activity 检测部分做出了贡献。该库还大大减少了获得融合位置所需的代码行。

该库包含一个简单的用法示例:https://github.com/mcharmas/Android-ReactiveLocation/blob/master/sample/src/main/java/pl/charmas/android/reactivelocation/sample/MainActivity.java

正如您在评论中所写,要找到使用 ActivityDetectionApi 的好示例并不容易。这也是我将其添加到库中的原因之一。事实上,google 当时提供的文档已经过时,因为他们更新了 Google Play 服务 API,但教程没有。

对于不使用该库的教程,我没有任何好的建议,但我可以使用 ReactiveLocation 提供我的代码片段。此代码在服务中 运行,因此它会跟踪当前 activity 而不管应用是否处于焦点状态:

private void requestFilteredActivityUpdates() {

    ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(getApplicationContext());
    filteredActivitySubscription = locationProvider.getDetectedActivity(0).doOnError(new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            String message = "Error on activitySubscription: " + throwable.getMessage();
            Log.e(TAG, message, throwable);
            Crashlytics.logException(throwable);
        }
    }).onErrorReturn(new Func1<Throwable, ActivityRecognitionResult>() {
        @Override
        public ActivityRecognitionResult call(Throwable throwable) {
            List<DetectedActivity> list = new ArrayList<DetectedActivity>();
            list.add(new DetectedActivity(DetectedActivity.UNKNOWN, 0));
            return new ActivityRecognitionResult(list, System.currentTimeMillis(), SystemClock.elapsedRealtime());
        }
    }).filter(new Func1<ActivityRecognitionResult, Boolean>() {
        @Override
        public Boolean call(ActivityRecognitionResult activityRecognitionResult) {

            DetectedActivity detectedActivity = activityRecognitionResult.getMostProbableActivity();

            boolean highConfidence =  detectedActivity.getConfidence() > 75;


            DetectedActivity previousActivity = ActivityDetectionModule.Recent.getDetectedActivity();
            boolean isNewActivity = detectedActivity.getType() != previousActivity.getType();
            boolean hasHigherConfidence = detectedActivity.getConfidence() > previousActivity.getConfidence();


            return mJustStarted || (highConfidence && (isNewActivity || hasHigherConfidence)); 
        }
    }).subscribe(new Action1<ActivityRecognitionResult>() {
        @Override
        public void call(ActivityRecognitionResult activityRecognitionResult) {

            DetectedActivity detectedActivity = activityRecognitionResult.getMostProbableActivity();

            Log.i(TAG, "Activity changed or increased in confidence:");

            Log.i(TAG, "New: " + ActivityDetectionModule.getNameFromType(detectedActivity.getType()) + " confidence: " + detectedActivity.getConfidence());

        }
    });
}

然后在 onDestroy() 我打电话给

public void unsubscribeActivityUpdates() {
    unsubscribe(filteredActivitySubscription);
}

private void unsubscribe(Subscription subscription) {
    if (subscription != null && !subscription.isUnsubscribed()) {
        Log.i(TAG, "Unsubscribe activity updates");
        try {
            subscription.unsubscribe();
        } catch (Exception e) {
            e.printStackTrace();
        }
        subscription = null;
    }
}

我希望这充分说明了如何使用该库,否则请随时提问。