1

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

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

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

4

3 回答 3

4

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

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

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

对于不使用该库的教程,我没有任何好的指导,但我可以使用 ReactiveLocation 提供我的代码片段。此代码在服务中运行,因此无论应用程序是否处于焦点,它都会跟踪当前活动:

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;
    }
}

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

于 2015-04-24T20:51:00.470 回答
1

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

LocationRequest location= new LocationRequest();

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

因此,对于位置请求,您具有以下功能,

设置间隔,设置最小位移,每隔几秒或几米他移动一次的位置。

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

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

于 2015-04-24T19:01:42.113 回答
0

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

您可能想要使用 requestLocationUpdates,特别是这个版本,它最适合与后台任务一起使用。在 LocationRequest 中,您可以使用setInterval来定义更新间隔。

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

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

于 2015-04-24T19:19:32.613 回答