位置情報を取得する|Android開発

作成したアプリケーションで位置情報を取得するための手順です。
なお、本サンプルのActivity名はMainActivityとなっています。

権限の追加

AndroidManifest.xmlに次の権限を追加します。

<!-- 位置情報 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 位置情報 正確な情報が欲しい場合に追加で指定する -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

位置情報の有効化をユーザーに要求する

位置情報(GPS)がOFFの場合にユーザーに設定を要求する方法です。設定画面ダイアログの2パターンがあります。

設定画面を表示する場合

Activityにて以下の処理を行います。

LocationManagerの生成

private LocationManager mLocationManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}

位置情報がONかどうかを確認する

boolean isGpsEnabled;
try {
    int locationMode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE);
    isGpsEnabled = locationMode != android.provider.Settings.Secure.LOCATION_MODE_OFF;
} catch (Settings.SettingNotFoundException e) {
    isGpsEnabled = false;
}

または

boolean isGpsEnabled;
if (Build.VERSION_CODES.P <= Build.VERSION.SDK_INT) {
    isGpsEnabled = mLocationManager.isLocationEnabled();
} else {
    isGpsEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    boolean isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    isGpsEnabled |= isNetworkEnabled;
}
位置情報がONになっていてもLocationManager.GPS_PROVIDERfalseの場合がありました。 その場合、LocationManager.NETWORK_PROVIDERtrueだったため、2つの論理和を取っています。

位置情報設定画面の表示

位置情報がOFFの場合に、次のようにして設定画面を表示します。

private static final int REQUEST_ENABLE_GPS = 100;

Intent enableGpsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(enableGpsIntent, REQUEST_ENABLE_GPS);
android gps settings

この場合、onActivityResult()RESULT_OK(Activity.RESULT_OK)が取得できません。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_ENABLE_GPS) {
        if (resultCode != RESULT_OK) {
            // 必ずここになる.
        }
    }
}

設定ダイアログを表示する場合

設定画面を開かずに次のようなダイアログで設定を行うための方法です。

android gps dialog

依存関係の追加

build.gradledependenciesに以下を追加します。

implementation 'com.google.android.gms:play-services-location:11.8.0'

位置情報がONかどうかを取得する

LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(60000);
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

final LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
        .addLocationRequest(locationRequest);

SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());

Taskの結果から位置情報設定がチェックできます。

  • setInterval()ではGPSの更新間隔をミリ秒単位で指定する
  • setPriority()ではリクエストの優先度を設定する

位置情報設定ダイアログの表示

位置情報がOFFの場合に、次のようにして設定ダイアログを表示します。

private static final int REQUEST_ENABLE_GPS = 100;

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
    @Override
    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
        Log.i(TAG, "## 設定ON");
    }
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            Log.i(TAG, "## 設定OFF");
            try {
                // 設定ダイアログを表示.
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this, REQUEST_ENABLE_GPS);
                // 結果は onActivityResult() で取得.
            } catch (IntentSender.SendIntentException sende) {
                //
            }
        }
    }
});

結果の判定

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_ENABLE_GPS) {
        if (resultCode != RESULT_OK) {
            // ONにしなかった場合
            return;
        }
    }
}

参考

位置情報の取得

LocationRequestは設定の確認に使ったものとは別のインスタンスを用意します。

private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest mLocationRequest;

@Override
protected void onCreate(Bundle savedInstanceState) {
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(60000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}

位置情報をリクエストする

requestLocationUpdates()を使って位置情報の更新をリクエストします。

private void startLocationUpdates() {
    try {
        mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper());
    } catch (SecurityException unlikely) {
        Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
    }
}

位置情報の更新を停止する

private void stopLocationUpdates() {
    mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}

位置情報更新コールバック

private final LocationCallback mLocationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {
        super.onLocationResult(locationResult);
        if (locationResult == null) {
            Log.i(TAG, "locationResult is null");
            return;
        }

        Location lastLocation = locationResult.getLastLocation();
        if (lastLocation == null) {
            return;
        }
        // 緯度
        lastLocation.getLatitude();
        // 経度
        lastLocation.getLongitude();
    }
};

未確認ですが、ドキュメントでは、次のようになっているので複数取得(履歴?)もできそうです。

for (Location location : locationResult.getLocations()) {
    // 処理
}
このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

コメント

メールアドレスが公開されることはありません。 が付いている欄は必須項目です