GPS(1)
次に、GPSから位置情報を取得し、地図に表示する部分を記述していきましょう。
緯度経度から地図表示
まず、先ほどの続きで、緯度と経度から地図アプリを表示させる処理を記述しましょう。IntentStartActivityに緯度と経度を表すフィールドと、「地図表示」ボタンの処理である、onMapShowCurrentButtonClick()メソッドを以下のように追記してください。
private double _latitude = 0;
private double _longitude = 0;
public void onMapShowCurrentButtonClick(View view) {
String uriStr = "geo:" + _latitude + "," + _longitude; // (1)
Uri uri = Uri.parse(uriStr);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
前項で解説した地図アプリとの連携URIですが、「geo:緯度,経度」とすることで、その地点を表示してくれます。ここでは、フィールドの緯度経度で地図アプリを表示するようなURI文字列を(1)で作成しています。
この状態で一度アプリを再起動し、「地図表示」ボタンをタップしてください。現地点では、フィールドの初期値の「0,0」を表示しています。ここはガーナの南にあたる赤道直下の大西洋なので、海の青色しか出てきません。
現在地の取得
では、この緯度経度フィールドをGPSから取得した現在地の緯度経度で書き換え、さらに、その値をTextViewに表示するように書き換えていきましょう。以下のように、緯度と経度を表示するTextViewフィールドの追加と、GPS機能を有効にする処理をonCreate()メソッドへ追記してください。
private TextView _tvLatitude;
private TextView _tvLongitude;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //(1)
setContentView(R.layout.activity_intent_start); //(1)
_tvLatitude = (TextView) findViewById(R.id.tvLatitude); //(2)
_tvLongitude = (TextView) findViewById(R.id.tvLongitude); //(2)
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); //(3)
GPSLocationListener locationListener = new GPSLocationListener(); //(4)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); //(5)
}
(1)はもともと記述されていたコードです。(2)は緯度経度TextViewフィールドの中身を取得しています。
位置情報を利用するには、LocationManagerクラスを使います。このオブジェクトは、前回解説したNotificationManager同様、newするのではなく、getSystemService()メソッドを使って取得します。それが(3)です。このクラスのrequestLocationUpdates()メソッドを実行することで、位置情報の追跡を開始します。それが(5)です。その際の引数は4個です。
第1引数で、どの位置情報サービス(これを「プロバイダ」といいます)から位置情報を取得するかをLocationManagerの定数で指定します。「GPS_PROVIDER」はGPS情報を、「NETWORK_PROVIDER」は電波の基地局などのネットワーク情報を利用します。
第2引数は、位置情報の更新を確認する間隔(ミリ秒)を指定します。
第3引数は、位置情報の更新通知を行う移動距離(メートル)を指定します。今回は両方とも0なので、常に位置情報を取得することになります。
第4引数は、位置情報が更新された際のリスナクラスを設定しますが、このリスナクラスをnewしているのが(4)です。
[Note]FusedLocationProviderApi
Android端末のプロバイダは、GPSの他にWiFi、電話基地局などがあります。それぞれメリットとデメリットがあります。例えば、GPSは精度が高いのですが、電力消費が大きいのです。それぞれのプロバイダのメリット、デメリットを考慮しながらケース・バイ・ケースでどれを使うかをプログラミングするのは骨が折れます。それを自動でしてくれるものとして、FusedLocationProviderApiというのがあります。これは、Android標準のAPIとは別のGoogle APIに含まれているものです。今回のサンプルでは、GPSに限定していますので、FusedLocationProviderApiは使わずに直接GPSをプロバイダとして指定しています。
リスナクラス
では、そのリスナクラスを作成しましょう。
LocationListenerインターフェースを実装して作成します。以下のメンバクラスを追加してください。
private class GPSLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
_latitude = location.getLatitude(); // (1)
_longitude = location.getLongitude(); // (1)
_tvLatitude.setText(Double.toString(_latitude)); // (2)
_tvLongitude.setText(Double.toString(_longitude)); // (2)
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
}
LocationListenerインターフェースを実装した場合、以下の4個のメソッドを実装する必要があります。
- onLocationChanged():位置情報が変更されたときの処理
- onStatusChanged():プロバイダが変更されたときの処理
- onProviderEnabled():プロバイダが有効になった時の処理
- onProviderDisabled():プロバイダが無効になった時の処理
今回は、onLocationChanged()のみを実装することにします。onLocationChanged()の引数のLocationオブジェクトにプロバイダ(今の設定ではGPS)から取得した位置情報が格納されています。そのメソッドgetLatitude()、および、getLongitude()で緯度、経度が取得できますので、それをフィールドに格納します。それが(1)です。と同時に、その値をTextViewに表示させます。それが(2)です。
