我需要编写一个应用程序,它每 5 分钟确定一次手机的当前位置(使用所有免费、可用的位置提供程序)并将其发送到服务器.
I need to write an app, which every 5 minutes determines the current location of the mobile phone (using all free, available location providers) and sends it to a server.
如果某些位置提供程序在应用程序启动时不起作用,但稍后可用,则应用程序也应处理其位置数据.
If some location provider doesn't work at the start of the application, but becomes available later, the application should process its location data as well.
为了做到这一点,我实现了以下课程.在我的一项活动中,我创建了它的一个实例并调用它的 startTrackingUpdates
方法.locationChangeHandler
处理位置数据.
In order to do this, I implemented following class. In one of my activities, I create an instance of it and call its startTrackingUpdates
method. locationChangeHandler
does the processing of location data.
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) {
}
}
我构建了应用程序并将其安装在我的手机上.然后,早上我拿起手机,去上班,然后回家.在家查看应用程序一天工作的结果,发现数据库中只有一条记录.
I built the application and installed it on my mobile phone. Then, in the morning I took my phone, went to work, then went back home. At home I checked the results of a day-long work of the application and found only one record in the database.
如果系统的其余部分(将位置数据传输到服务器,保存在数据库中)正常工作,我的位置跟踪代码肯定有问题(onLocationChanged
没有被调用即使我多次更改我的位置).
Provided that the rest of the system (transmission of location data to the server, saving in the database) works correctly, I must have some problem in the location tracking code (onLocationChanged
wasn't invoked even though I changed my location several times).
我的代码有什么问题(我应该如何更改它,以便在手机位置更改超过 MIN_DISTANCE_CHANGE_FOR_UPDATES
米时调用 onLocationChanged
到定位提供者之一)?
What's wrong with my code (how should I change it, in order for the onLocationChanged
to be called whenever the location of the phone changes by more than MIN_DISTANCE_CHANGE_FOR_UPDATES
meters according to one of the locatin providers) ?
更新 1(18.08.2013 13:59 MSK):
我根据 msh 的建议更改了我的代码.我使用以下代码启动计时器:
I changed my code according to msh recommendations. I start the timer using following code:
public void startSavingGeoData() {
final IAlarmManager alarmManager = activity.getAlarmManager();
final IPendingIntent pendingIntent = activity.createPendingResult(
ALARM_ID, intentFactory.createEmptyIntent(), 0);
alarmManager.setRepeating(INTERVAL, pendingIntent);
}
在 activity
我放置了以下计时器事件处理程序:
In the activity
I put following timer event handler:
@Override
protected void onActivityResult(final int aRequestCode, final int aResultCode,
final Intent aData) {
geoDataSender.processOnActivityResult(aRequestCode, aResultCode,
new IntentWrapper(aData));
}
当手机开机时,一切都按预期工作 - onActivityResult
在 INTERVAL
毫秒内执行一次.
When the phone is turned on, everything works as expected - onActivityResult
is executed once in INTERVAL
milliseconds.
但是当我按下电源按钮(屏幕被禁用)时,根本不会调用 onActivityResult
.当我再次按下电源按钮时,onActivityResult
会执行多次,因为 INTERVAL
自我关闭手机以来已经过去了.如果我关闭手机 1 * INTERVAL
毫秒,它会触发一次.如果我将手机关机 2 * INTERVAL
毫秒,它会触发两次,以此类推.
But when I press the power button (screen becomes disabled), onActivityResult
is not invoked at all. When I press the power button again, onActivityResult
is executed as many times, as INTERVAL
has passed since the time when I turned the phone off. If I turned the phone off for 1 * INTERVAL
milliseconds, it will fire once. If I turned the phone off for 2 * INTERVAL
milliseconds, it will fire twice etc.
注意:关闭"是指短按电源按钮(例如,手机仍然活着"并对传入的 SMS 做出反应).
Note: By "turning off" I mean a short press of the power button (the phone still "lives" and reacts to incoming SMS, for example).
我应该如何修改 startSavingGeoData
的代码,以使 onActivityResult
方法每 INTERVAL
毫秒执行一次,即使手机处于休眠状态?
How should I modify the code of startSavingGeoData
in order for the method onActivityResult
to be executed every INTERVAL
milliseconds, even when the phone sleeps?
更新 2(18.08.2013 19:29 MSK): alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent)
和 alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent)
解决了这个问题.
Update 2 (18.08.2013 19:29 MSK): Neither alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent)
, nor alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent)
solved the problem.
您的代码可能是正确的,但是当您的手机处于睡眠状态时,位置提供程序没有运行.您可能需要获取唤醒锁(如果您不关心功耗),或者使用 AlarmManager 并安排您的应用程序唤醒并定期检查位置(在等待更新时您仍然需要激活唤醒锁,或者由 AlamManager 或您自己获得).
Your code is probably correct, but location providers are not running when your phone is sleeping. You may need to acquire a wakelock (if you don't care about power draw), or use AlarmManager and schedule your application to wake up and check location periodically (you still need to have active wakelock while you are waiting for an update, either acquired by AlamManager, or your own).
这篇关于如何持续追踪安卓手机的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!