10

我需要编写一个应用程序,它每 5 分钟确定一次手机的当前位置(使用所有免费、可用的位置提供程序)并将其发送到服务器。

如果某个位置提供程序在应用程序启动时不起作用,但稍后可用,则应用程序也应处理其位置数据。

为了做到这一点,我实现了以下课程。在我的一项活动中,我创建了它的一个实例并调用它的startTrackingUpdates方法。locationChangeHandler处理位置数据。

public class LocationTracker implements ILocationTracker, LocationListener {
    public static final long MIN_TIME_BETWEEN_UPDATES = 1000 * 60 * 5; // 5 minutes
    public static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
    private ILocationManager locationManager;
    private ILocationChangeHandler locationChangeHandler;

    public LocationTracker(final ILocationManager aLocationManager,
            final ILocationChangeHandler aLocationChangeHandler) {
        this.locationManager = aLocationManager;
        this.locationChangeHandler = aLocationChangeHandler;
    }

    public void startTrackingUpdates() {
        final List<String> providers = locationManager.getAllProviders();

        for (final String curProviderName : providers)
        {
            final ILocationProvider provider = locationManager.getLocationProvider(curProviderName);

            if (!provider.hasMonetaryCost())
            {
                subscribeToLocationChanges(provider);
            }
        }
    }

    private void subscribeToLocationChanges(final ILocationProvider aProvider) {
        locationManager.requestLocationUpdates(aProvider.getName(), MIN_TIME_BETWEEN_UPDATES, 
                (float)MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
    }

    public void onLocationChanged(final Location aLocation) {
        locationChangeHandler.processLocationChange(new LocationWrapper(aLocation));
    }

    public void onProviderDisabled(final String aProvider) {
    }

    public void onProviderEnabled(final String aProvider) {
    }

    public void onStatusChanged(final String aProvider, final int aStatus, 
            final Bundle aExtras) {
    }
}

我构建了应用程序并将其安装在我的手机上。然后,早上我拿起手机,去上班,然后回家。在家里,我检查了应用程序一天工作的结果,发现数据库中只有一条记录。

如果系统的其余部分(将位置数据传输到服务器,保存在数据库中)正常工作,我的位置跟踪代码肯定有一些问题(onLocationChanged即使我多次更改位置也没有调用)。

我的代码有什么问题(我应该如何更改它,以便根据定位提供商之一onLocationChanged在电话位置变化超过米时调用)?MIN_DISTANCE_CHANGE_FOR_UPDATES

更新 1(18.08.2013 13:59 MSK):

我根据msh的建议更改了我的代码。我使用以下代码启动计时器:

public void startSavingGeoData() {
    final IAlarmManager alarmManager = activity.getAlarmManager();
    final IPendingIntent pendingIntent = activity.createPendingResult(
            ALARM_ID, intentFactory.createEmptyIntent(), 0);
    alarmManager.setRepeating(INTERVAL, pendingIntent);
}

activity我放了以下计时器事件处理程序:

@Override
protected void onActivityResult(final int aRequestCode, final int aResultCode, 
        final Intent aData) {
    geoDataSender.processOnActivityResult(aRequestCode, aResultCode, 
            new IntentWrapper(aData));
}

当手机打开时,一切都按预期工作 -以毫秒为单位onActivityResult执行一次。INTERVAL

但是当我按下电源按钮(屏幕被禁用)时,onActivityResult根本不会被调用。当我再次按下电源按钮时,onActivityResult执行次数与INTERVAL我关闭手机后的时间一样多。如果我关闭手机1 * INTERVAL几毫秒,它会触发一次。如果我关闭手机2 * INTERVAL几毫秒,它会触发两次等。

注意:“关闭”是指短按电源按钮(例如,手机仍然“活着”并对传入的 SMS 做出反应)。

我应该如何修改代码startSavingGeoData以使该方法onActivityResult每毫秒执行一次INTERVAL,即使手机处于休眠状态?

更新 2(18.08.2013 19:29 MSK):既没有alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent),也没有alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent)解决问题。

4

1 回答 1

8

您的代码可能是正确的,但是当您的手机处于睡眠状态时,位置提供程序没有运行。您可能需要获取唤醒锁(如果您不关心功耗),或者使用 AlarmManager 并安排您的应用程序定期唤醒并检查位置(在等待更新时您仍然需要激活唤醒锁,或者由 AlamManager 或您自己获得)。

于 2013-08-15T20:34:36.907 回答