5 分ごとに携帯電話の現在の位置を (無料で利用可能なすべての位置情報プロバイダーを使用して) 決定し、それをサーバーに送信するアプリを作成する必要があります。
アプリケーションの開始時には位置情報プロバイダーが機能せず、後で利用可能になった場合、アプリケーションはその位置データも処理する必要があります。
これを行うために、次のクラスを実装しました。私のアクティビティの 1 つで、そのインスタンスを作成し、その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) {
}
}
アプリケーションを作成し、携帯電話にインストールしました。それから、朝、携帯電話を持って仕事に行き、家に帰りました。自宅でアプリケーションの 1 日にわたる作業の結果を確認したところ、データベースに 1 つのレコードしか見つかりませんでした。
システムの残りの部分 (サーバーへの位置データの送信、データベースへの保存) が正しく機能していれば、位置追跡コードに何らかの問題があるはずです (onLocationChanged
位置を数回変更したにもかかわらず、呼び出されませんでした)。
私のコードの何が問題なのですか (ロカチン プロバイダーの 1 つに従って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 回起動します。電話をミリ秒1 * INTERVAL
オフにすると、2回起動します。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)
問題を解決しませんでした。