こんにちは!日曜日のぱかぱかです!
昨日は大学時代の部活の後輩と大学祭に遊びに行ってきました。
私は就職後も大学の近くに住んでいるのですが、今でも声をかけてもらえるのがありがたい限りです。
ちょうど後輩たちは就活を終えた頃で、誰もが知っているような大企業の内定をもらっていて感心しました😌
自分はこの地に残りたいという理由で大学時代の研究と全く異なるITの分野に足を踏み入れ地方のベンチャーSIerに就職したわけですが、やっぱり大きな会社で働くことにも憧れがあります…
この地に残る理由も最近は薄れてきており、身につけつつあるITスキルという新たな武器と共に都会のIT企業にも第二新卒のうちにチャレンジできたらいいなと思っております🔥
今の会社が良すぎてとても迷ってしまうのですが…思い切りも大事ですよね…🥲
と日記はここら辺にして、今日は「GPSで取得した現在地の天気をお天気APIで取得する」という内容についてまとめたいと思います!
今回のゴール
今回は以下について学びたいと思います。
・非同期処理を用いたAPI連携
・GPSによる現在地取得と位置情報利用
そのために作ろうとしているのが
という機能になっております。
結構内容が盛りだくさんなので長くなってしまうかも…?
今回は後者の「GPSによる現在地取得と位置情報利用」について取り上げたいと思います!
ぶっちゃけ今作っているバードウォッチングアプリの機能として天気を取得する処理はいらない気もするのですが、完全にお勉強のためにねじ込もうとしています笑
成果物のイメージはこんな感じです。
トップページで「天気を見る」ボタンをタップすると、今いる地域の天気が表示されるというもの。
(別に今丸の内にいるわけではありません笑
AVDには位置情報取得機能が搭載されていないため自分で設定しています笑)
それではまず位置情報の取得について見ていきましょう!
位置情報取得ライブラリ
位置情報を取得する機能は以下のようなものがあります。
プロバイダ(位置情報提供元) | 特徴 |
---|---|
GPS | 精度が高いが電力消費が大きい |
Wi-Fi基地局のネットワーク | 精度が低いが電力消費が小さい |
GPSはパッと思いつきますが、それ以外の取得方法もあるんですね。
表のようにそれぞれで特徴があるのでうまく使い分ける必要があります。
実はなんとありがたいことに、それをうまく使い分けてくれるライブラリがGoogleのAPIで提供されているのです。
それが、FusedLoactionProviderClientというライブラリになります。
FusedLoactionProviderClientの取得
FusedLoactionProviderClientオブジェクトの取得にはLocationServicesクラスのgetFusedLoactionProviderClient()を使用し、引数にコンテキストを渡します。
「天気を見る」ボタンリスナのonClick()メソッド内に記述していきますよ。
_fusedLocationClient = LocationServices.getFusedLocationProviderClient(this@TopPageActivity)
requestLocationUpdates()の実行
取得したFusedLoactionProviderClientオブジェクトを使って位置情報の追跡を開始するにはrequestLocationUpdates()を利用します。
その際、以下の3つの引数が必要となります。
引数の型と名称 | 内容 | |
---|---|---|
第1引数 | LocationRequest request | 位置情報の更新に関する設定情報 |
第2引数 | LocationCallback callback | 位置情報が更新されたときに実行されるコールバックオブジェクト |
第3引数 | Looper looper | コールバックオブジェクトを実行させるスレッドのLooperオブジェクト |
第1引数 位置情報更新の設定 LocationRequest
第1引数のLocationRequestオブジェクトでは、位置情報を取得するにあたっての設定情報を格納します。
設定できるプロパティは様々ですが、例として以下のようなものがあります。
・interval:位置情報の更新間隔。
・priority:更新の優先度を定数で指定。
参考書ではLocationRequestを生成するcreate()メソッドが使われていましたが、どうやら今はdeprecatedになっているようです。
今回は推奨されているBuilderメソッドを使用して、intervalとpriorityを設定しました。
// LocationRequestオブジェクトを生成。
val locationBuilder = LocationRequest.Builder(60000).setPriority(Priority.PRIORITY_BALANCED_POWER_ACCURACY)
locationBuilder.let {
_locationRequest = locationBuilder.build()
}
インターバル60000ミリ秒(=1分)ごとに位置情報を取得することにします。
今回使用したpriorityの定数はPRIORITY_BALANCED_POWER_ACCURACYで、電力消費と精度のバランスを考慮して位置情報を取得するというものになっています。(ちょうどいい)
第2引数 コールバッククラス LocationCallback
位置情報が更新されたときに実行させるコールバックオブジェクトを指定します。
そのためにコールバッククラスを作る必要があります。
ここではOnUpdateLocationクラスとして以下のように作成します。
OnUpdateLocationクラスはLocationCallbackクラスを継承して作ります。
onLocationResult()メソッドをオーバライドし、その中に位置情報が更新された時の処理を記述します。
private inner class OnUpdateLocation: LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult.let { it ->
// 直近の位置情報を取得。
val location = it.lastLocation
location?.let {
// locationオブジェクトから緯度を取得。
_latitude = it.latitude
// locationオブジェクトから経度を取得。
_longitude = it.longitude
}
}
}
}
今回は取得した緯度と経度を元にお天気APIに天気を問い合わせたいので、ここで変数として取得しておきます。
第3引数 looperオブジェクト Looper looper
非同期処理の後に確実にUIスレッドを実行させるためにはLooperオブジェクトを利用する必要があります。
mainLooperを渡してUIスレッドで動作するようにします。
以上3つの引数を使ってrequestLocationUpdates()を実行します。
「天気を見る」ボタンリスナのonClick()メソッド内の処理を抜粋すると以下のようになりました。
private inner class WeatherListener: View.OnClickListener {
override fun onClick(view: View) {
…
// FusedLocationProviderClientオブジェクトを取得。
_fusedLocationClient = LocationServices.getFusedLocationProviderClient(this@TopPageActivity)
// LocationRequestオブジェクトを生成。
val locationBuilder = LocationRequest.Builder(60000).setPriority(Priority.PRIORITY_BALANCED_POWER_ACCURACY)
locationBuilder.let {
_locationRequest = locationBuilder.build()
}
// 位置情報が変更されたときの処理を行うコールバックオブジェクトを生成。
_onUpdateLocation = OnUpdateLocation()
// 位置情報の追跡を開始。
_fusedLocationClient.requestLocationUpdates(_locationRequest, _onUpdateLocation, mainLooper)
…
}
}
ここで取得した位置情報をもとにURLを作成しお天気APIに投げる処理は次の記事でまとめたいと思います!
長くなりましたが、ここまで読んでくださりありがとうございました!