2012年6月25日

【Android】位置情報取得に関するまとめ



今回のOneClickHomeのアップデートに伴い、
GPSを使用するActivityのまとめをしたいと思います。



まずは、端末上でGPSがONになっているかを確認するメソッドです。

/**
 * @description check whether location information is enable.
 * @return true if location information is enable, false if not.
 */
private boolean checkGpsSettings() {
  // 位置情報の設定の取得
  String gps = android.provider.Settings.Secure.getString(
      getContentResolver(),
      android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
  // GPS機能か無線ネットワークがONになっているかを確認
  if (gs.indexOf("gps", 0) < 0 && gs.indexOf("network", 0) < 0) {
    // GPSサービスがOFFになっている場合、ダイアログを表示
    new AlertDialog.Builder(this)
        .setTitle("位置情報の設定");
        .setMessage("位置情報の設定がOFFになっている為、アプリの機能がご利用いただけません。位置情報の設定をONに変更して下さい。");
        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
              // 位置情報設定画面へ移動する
              Intent intent = new Intent(
                  android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
              intent.addCategory(Intent.CATEGORY_DEFAULT);
              startActivity(intent);
            }
        })
        .create()
        .show();
    return false;
  } else {
    return true;
  }
}
次に、GPS機能の設定がONで無線ネットワークの設定がOFFの場合、 位置情報取得までに時間が掛かる事を通知するようにします。
public class GpsActivity extends Activity 
    implements LocationListener, GpsStatus.Listener{
  private LocationManager locationManager;
  private ProgressDialog dialog; // 時間が掛かっている事を表示するダイアログ

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    // LocationManagerの初期化
    locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
    // GPSのリスナーの登録
    locationManager.addGpsStatusListener(this);

    // 位置情報取得中ダイアログの初期化
    dialog = new ProgressDialog(this);
    dialog.setTitle(R.string.loading);
    dialog.setMessage("GPS機能で位置情報を取得していますので、時間が掛かっております。無線ネットワークでの位置情報取得をONにすると早くなります。");
    dialog.setButton("設定を変更", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int which) {
        // 位置情報設定画面へ移動する
        Intent intent = new Intent(
            android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        startActivity(intent);
      }
    });
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    locationManager.removeUpdates(this);
    locationManager.removeGpsStatusListener(this);
  }

  private void getLocation() {
    // 位置情報設定の確認
    if (!checkGpsSettings()) {
      return;
    }
    // locationの取得キャンセル
    locationManager.removeUpdates(this);
    // LOCATION_PROVIDERの取得
    List providers = locationManager.getAllProviders();
    for(String provider : providers) {
      locationManager.requestLocationUpdates(provider, 0, 0, this);
    }
  }

  @Override
  public void onLocationChanged(Location location) {
    // 位置情報の取得
    locationManager.removeUpdates(this);
    locationManager.removeGpsStatusListener(this);
    fromLat = (float) location.getLatitude();
    fromLon = (float) location.getLongitude();
  }

  @Override
  public void onProviderDisabled(String provider) {
    // TODO Auto-generated method stub
  }

  @Override
  public void onProviderEnabled(String provider) {
    // TODO Auto-generated method stub
  }

  @Override
  public void onStatusChanged(String provider, int status, Bundle extras) {
    // TODO Auto-generated method stub
  }

  @Override
  public void onGpsStatusChanged(int event) {
    // 衛星を使った位置情報取得は時間が掛かる為、警告
    if(event == GpsStatus.GPS_EVENT_SATELLITE_STATUS
        && !dialog.isShowing()) {
       dialog.show();
    }
  }
}

getLocation()で位置情報の取得を開始します。
位置情報はネットワークと衛星を利用した取得方法がありますが、
衛星は遅く正確、ネットワークは早く若干のズレがある感じです。
どちらでも大丈夫ですが、衛星を使う場合は遅い事をユーザへ通知したほうが良いかと思います。