位置情報を取得する|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_PROVIDER
がfalse
の場合がありました。
その場合、LocationManager.NETWORK_PROVIDER
がtrue
だったため、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);
この場合、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) {
// 必ずここになる.
}
}
}
設定ダイアログを表示する場合
設定画面を開かずに次のようなダイアログで設定を行うための方法です。
依存関係の追加
build.gradleのdependencies
に以下を追加します。
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()) {
// 処理
}