現在地の更新情報をリクエストする

位置情報を適切に使用すると、アプリのユーザーにメリットをもたらすことができます。たとえば、歩行中や運転中に道案内をするアプリや、貴重品がある場所を追跡するアプリを作成できます。このようなアプリは、定期的にデバイスの位置情報を取得する必要があります。地理的位置(緯度と経度)だけでなく、デバイスの方位(移動の水平方向)、高度、移動速度などの情報を追加でユーザーに提供することもできます。これらの情報は(それ以外の情報も)アプリが融合された位置予測プロバイダから取得できる Location オブジェクトを通じて入手できます。それに応じて、API は Wi-Fi や GPS(グローバル ポジショニング システム)など、その時点で利用可能な位置情報プロバイダに基づき、取得できる最適な位置情報を定期的にアプリに提供します。位置情報の精度は、プロバイダ、リクエストした位置情報権限、位置情報リクエストで設定したオプションによって決まります。

このレッスンでは、融合された位置予測プロバイダの requestLocationUpdates() メソッドを使用して、デバイスの位置情報に関する定期的な更新をリクエストする方法について説明します。

直近の位置情報を取得する

デバイスの直近の位置情報は出発点として便利です。これを使用して、アプリは位置情報の定期的な更新を開始する前に、必ず既知の位置情報を持つことができます。getLastLocation() を呼び出して直近の位置情報を取得する方法については、直近の位置情報を取得するレッスンをご覧ください。以降のセクションのスニペットでは、アプリが直近の位置情報を取得済みで、それをグローバル変数 mCurrentLocation 内の Location オブジェクトとして保存しているものと仮定します。

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

アプリは位置情報の更新データをリクエストする前に、位置情報サービスに接続して位置情報リクエストを作成する必要があります。そのための手順については、位置情報の設定を変更するレッスンをご覧ください。位置情報リクエストの準備が完了したら、requestLocationUpdates() を呼び出して、定期的な更新を開始できます。

融合された位置予測プロバイダは、リクエストの形式に応じて、LocationCallback.onLocationResult() コールバック メソッドを呼び出して Location オブジェクトのリストを渡すか、または拡張データ内に位置情報を含んでいる PendingIntent を発行します。更新の精度と頻度は、リクエストした位置情報権限と、位置情報リクエスト オブジェクトに設定したオプションによって変わります。

このレッスンでは、LocationCallback コールバックを使用して更新を取得する方法を示します。requestLocationUpdates() を呼び出して、LocationRequest オブジェクトのインスタンスと LocationCallback を渡します。startLocationUpdates() メソッドを定義します。次のコードサンプルをご覧ください。

Kotlin

override fun onResume() {
    super.onResume()
    if (requestingLocationUpdates) startLocationUpdates()
}

private fun startLocationUpdates() {
    fusedLocationClient.requestLocationUpdates(locationRequest,
            locationCallback,
            Looper.getMainLooper())
}

Java

@Override
protected void onResume() {
    super.onResume();
    if (requestingLocationUpdates) {
        startLocationUpdates();
    }
}

private void startLocationUpdates() {
    fusedLocationClient.requestLocationUpdates(locationRequest,
            locationCallback,
            Looper.getMainLooper());
}

上記のコード スニペットでは、requestingLocationUpdates というブール値のフラグを参照しています。このフラグにより、ユーザーが位置情報の更新をオンにしているかオフにしているかをトラッキングできます。ユーザーが位置情報の更新をオフにしている場合は、アプリが位置情報を必要とすることをユーザーに通知できます。アクティビティの複数のインスタンスで��のブール値フラグの値を保持する方法については、アクティビティの状態を保存するをご覧ください。

位置情報更新コールバックを定義する

融合された位置予測プロバイダは、LocationCallback.onLocationResult() コールバック メソッドを呼び出します。このメソッドが受け取る引数には、位置情報の緯度と経度を格納するリスト形式の Location オブジェクトが含まれています。以下のスニペットは、LocationCallback インターフェースを実装してメソッドを定義し、次に位置情報の更新のタイムスタンプを取得してアプリのユーザー インターフェースに緯度、経度、タイムスタンプを表示する方法を示しています。

Kotlin

private lateinit var locationCallback: LocationCallback

// ...

override fun onCreate(savedInstanceState: Bundle?) {
    // ...

    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            for (location in locationResult.locations){
                // Update UI with location data
                // ...
            }
        }
    }
}

Java

private LocationCallback locationCallback;

// ...

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...

    locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            if (locationResult == null) {
                return;
            }
            for (Location location : locationResult.getLocations()) {
                // Update UI with location data
                // ...
            }
        }
    };
}

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

ユーザーが別のアプリに切り替えたときや同じアプリの別のアクティビティに切り替えたときなど、アクティビティがフォーカスを失ったときは、位置情報の更新を停止することを検討してください。アプリがバックグラウンドで実行されていたとしても、位置情報を収集する必要がなければ、位置情報の更新を停止することで簡単に消費電力を低減できます。このセクションでは、アクティビティの onPause() メソッドを使用して更新を停止する方法について説明します。

位置情報の更新を停止するには、removeLocationUpdates() を呼び出して LocationCallback を渡します。次のコードサンプルをご覧ください。

Kotlin

override fun onPause() {
    super.onPause()
    stopLocationUpdates()
}

private fun stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback)
}

Java

@Override
protected void onPause() {
    super.onPause();
    stopLocationUpdates();
}

private void stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback);
}

ブール値 requestingLocationUpdates を使用して、位置情報の更新がオンになっているかどうかをトラッキングします。アクティビティの onResume() メソッドで、位置情報の更新がアクティブになっているかどうかをチェックし、なっていなければアクティブにします。

Kotlin

override fun onResume() {
    super.onResume()
    if (requestingLocationUpdates) startLocationUpdates()
}

Java

@Override
protected void onResume() {
    super.onResume();
    if (requestingLocationUpdates) {
        startLocationUpdates();
    }
}

アクティビティの状態を保存する

デバイスの構成(画面の向きや言語)を変更すると、現在のアクティビティが破棄されることがあります。そのため、アプリではアクティビティの再作成に必要な情報を保存する必要があります。その方法の 1 つは、Bundle オブジェクト内にインスタンス状態を保存することです。

アクティビティの onSaveInstanceState() コールバックを使用してインスタンス状態を保存する方法を次のコードサンプルに示します。

Kotlin

override fun onSaveInstanceState(outState: Bundle?) {
    outState?.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, requestingLocationUpdates)
    super.onSaveInstanceState(outState)
}

Java

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY,
            requestingLocationUpdates);
    // ...
    super.onSaveInstanceState(outState);
}

updateValuesFromBundle() メソッドを定義して、アクティビティの以前のインスタンスから保存した値(利用可能な場合)を復元します。このメソッドをアクティビティの onCreate() メソッドから呼び出します。次のコードサンプルをご覧ください。

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    updateValuesFromBundle(savedInstanceState)
}

private fun updateValuesFromBundle(savedInstanceState: Bundle?) {
    savedInstanceState ?: return

    // Update the value of requestingLocationUpdates from the Bundle.
    if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
        requestingLocationUpdates = savedInstanceState.getBoolean(
                REQUESTING_LOCATION_UPDATES_KEY)
    }

    // ...

    // Update UI to match restored state
    updateUI()
}

Java

@Override
public void onCreate(Bundle savedInstanceState) {
    // ...
    updateValuesFromBundle(savedInstanceState);
}

private void updateValuesFromBundle(Bundle savedInstanceState) {
    if (savedInstanceState == null) {
        return;
    }

    // Update the value of requestingLocationUpdates from the Bundle.
    if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
        requestingLocationUpdates = savedInstanceState.getBoolean(
                REQUESTING_LOCATION_UPDATES_KEY);
    }

    // ...

    // Update UI to match restored state
    updateUI();
}

インスタンス状態の保存については、Android Activity クラスのリファレンスをご覧ください。

注: 永続的に保存したい場合は、アプリの SharedPreferences 内にユーザーの環境設定を保存する方法があります。アクティビティの onPause() メソッドで共有環境設定を設定し、onResume() で環境設定を取得します。環境設定の保存については、Key-Value セットを保存するをご覧ください。

参考情報

詳細については、以下のリソースをご覧ください。

サンプル