LocationManagerと、ユーザーの位置を取得するためのさまざまなアプローチについては、多くの質問があります。ただし、それらのほとんどは精度に集中しており、要件が異なるため、私のアプローチは少し異なります。私が必要なのは約です。ユーザーのGPS位置ですが、できるだけ速く(ただし、ユーザーがボタンをタップした後のみ)、一部のEditTextボックスに座標を入力する必要があります。問題は、ほとんどの場合、デバイスでデータ転送が無効になるため、ネットワークロケーションが利用できないことです。私はGPSに固執する必要がありますが、これは設計上高速ではありません。だからこれが私がすることです:
ボタンをクリックすると、メインアクティビティのgetGPS()メソッドを呼び出します。精度は気にしないので(おおよその座標を取得する必要があります)、最後の既知の場所をチェックしています。コード内のコメントは次のとおりです。自明
public void getGPS(View view) {
// load all available Location providers
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(false);
// determine the last known location within 2 hours available from cache
Location myLocation = null;
Date now = new Date();
long time = now.getTime();
long timeDiff = LOCATION_MAX_AGE;
for (int i=providers.size()-1; i>=0; i--) {
Location l = locationManager.getLastKnownLocation(providers.get(i));
if (l != null) {
long t = l.getTime();
if (time - t < timeDiff) {
myLocation = l;
time = t;
timeDiff = time - t;
}
}
}
// if failed to get cached location or if it is older than 2 hours, request GPS position
if (myLocation == null) {
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
pIntent = PendingIntent.getBroadcast(context,
0,
new Intent(SINGLE_UPDATE_ACTION),
PendingIntent.FLAG_UPDATE_CURRENT);
IntentFilter iFilter = new IntentFilter(SINGLE_UPDATE_ACTION);
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// when received an answer from the LocationManager
Location gpsLocation = (Location) intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED);
fillLocation(gpsLocation);
Log.d(TAG, "Received GPS location: " + gpsLocation.getLatitude() + ", " + gpsLocation.getLongitude() + " Time: " + gpsLocation.getTime());
locationManager.removeUpdates(pIntent);
unregisterReceiver(receiver);
}
};
context.registerReceiver(receiver, iFilter);
// I'm absolutely fine with getting the first available GPS position and that's enough to me.
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, pIntent);
// if GPS is disabled in settings allow user to enable it
} else {
showGPSDisabledAlertToUser();
}
} else {
// if fresh enough lastKnownLocation is found
fillLocation(myLocation);
}
}
すべてが非常にうまく機能します。ほとんどの場合、lastKnownLocationがあり、ユーザーがボタンをタップした直後に座標が表示されます。しかし、運が悪ければGPSアイコンが表示され、ここで問題が発生します。利用可能なデータ接続がないため、GPS修正には通常よりも時間がかかります。この間、アクティビティはアクセス可能なままであり、ユーザーは座標がまもなく表示されることに気づいていません。もう1つの問題は、ユーザーが妥当な時間内にGPS修正を取得できない場合、要求をキャンセルできるはずです。
だから、私の質問は:ここでの最良のアプローチは何ですか?より具体的には、ユーザーに待機中のダイアログ(「GPS位置の取得...」など)や、リクエストを中断してユーザーをメインに戻す可能性のある「キャンセル」ボタンのようなものを表示することは可能ですか(そしてどのように?)アクティビティ、GPSアクティビティを停止し、ユーザーに座標を手動で入力するように求めるトーストを表示しますか?
申し訳ありませんが、これが非常に簡単なことである場合、私はAndroid向けの開発を学び始めたばかりであり、私のアプリはこれを除いてほぼ完了しています。本当に一生懸命検索しましたが、残念ながら何も見つかりませんでした。よろしくお願いします!
編集:質問を投稿してからわずか30分後に、私はすでに答えを知っているかもしれないことに気づきました。UIをブロックし、メッセージと[キャンセル]ボタンを表示して、そこからLocationManagerを要求するには、待機中のカーソルでダイアログを開く必要があります。修正を取得する前にユーザーが[キャンセル]をクリックした場合は、レシーバーの登録を解除してダイアログを閉じる必要があります。明日は絶対にやってみますが、どんな考えや提案、コメントも大歓迎です!