問題描述
我需要編寫一個應用程序,它每 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).
這篇關于如何持續追蹤安卓手機的位置?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!