GPS を利用して端末の位置情報を得るところまで実装できましたが、更に GPS エンジンの動作情報を取得することもできます。具体的には、GPS 測位に利用した GPS 衛星の位置や GPS 信号の受信状況を取得できるので、例えば GPS Status & Toolbox や GPS Essentials のように、GPS 衛星の位置をレーダーっぽく表示するようなことができるようになります。
位置情報を求めるシーンで、これら個々の GPS 衛星の情報まで必要とするケースはまず無いと思いますが、自分の書いたコードで、上空 20,000km を飛行する個々の GPS 衛星を追跡できていると思うとちょっとワクワクしますね。
基本的な処理の流れは次の通りです。
LocationManager
を取得するLocationManager
に LocationListener
を登録するLocationManager
に GpsStatus.Listener
を登録するGpsStatus.Listener
のメンバ関数 onGpsStatusChanged
がコールバックされるLocationManager
から LocationListener
と GpsStatus.Listener
を外す
必要なリスナを生成して LocationManager
に登録する手順は、GPS で位置情報を得る場合と同じです。しかし注意すべき点として、GpsStatus.Listener
だけでなく、位置情報を必要としていない場合であっても LocationListener
も忘れずに登録しないと、更新通知がされません*1。
package com.example.helloworld; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.content.Context; import android.location.LocationManager; import android.location.LocationListener; import android.location.Location; import android.location.GpsStatus; import android.location.GpsSatellite; import android.widget.TextView; // http://developer.android.com/reference/android/app/Activity.html public class MainActivity extends ActionBarActivity { private LocationManager mLocationManager = null; private LocationListener mLocationListener = null; private GpsStatus.Listener mGpsStatusListener = null; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLocationManager = (LocationManager) getSystemService( Context.LOCATION_SERVICE ); final boolean gpsEnabled = mLocationManager.isProviderEnabled( LocationManager.GPS_PROVIDER ); if (!gpsEnabled) { // ToDo: GPS 有効にしてくれー } mLocationListener = new LocationListener() { public void onLocationChanged(Location location) {} public void onStatusChanged(String provider, int status, Bundle extras) {} public void onProviderEnabled(String provider) {} public void onProviderDisabled(String provider) {} }; mGpsStatusListener = new GpsStatus.Listener() { public void onGpsStatusChanged( int event ) { // http://developer.android.com/reference/android/location/GpsSatellite.html Iterable<GpsSatellite> satellites = mLocationManager.getGpsStatus(null).getSatellites(); int sat_used = 0; int sat_total = 0; // GpsStaus.getMaxSatellites() の返り値が謎 String str = "PRN : Azimuth : Elevation : S/N\n"; for( GpsSatellite sat : satellites ) { if( sat.usedInFix()) { str += "*"; sat_total++; sat_used++; } else { str += " "; sat_total++; } str += String.format( "%2d", (int) sat.getPrn()) + " : "; str += String.format( "%7d", (int) sat.getAzimuth()) + " : "; str += String.format( "%9d", (int) sat.getElevation()) + " : "; str += String.format( "%4.1f", sat.getSnr()) + "\n"; } str += String.format( "\nsatellites %d/%d\n" , sat_used, sat_total ); TextView t = (TextView) findViewById( R.id.textView1 ); t.setText( str ); } }; } protected void onStart() { // ⇔ onStop super.onStart(); mLocationManager.addGpsStatusListener( mGpsStatusListener ); mLocationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 1000 * 1/*mSec*/, 1/*meter*/, mLocationListener ); } protected void onStop() { // ⇔ onStart super.onStop(); mLocationManager.removeGpsStatusListener( mGpsStatusListener ); mLocationManager.removeUpdates( mLocationListener ); } }
基本的な部分は、GPS で位置情報のみを取得する場合と同じです。
LocationListener
のインスタンスを生成しています(概要の手順 3)。ただし、今回のサンプルでは位置情報を利用しないので、実装すべきメンバ関数は何の動作もしませんが、動作に必須のためインスタンスを省略できません。GpsStatus.Listener
のインスタンスを生成しています(概要の手順 4)。ここでは匿名クラスとしてリスナを生成していますが、お行儀よく GpsStatus.Listener を implements したサブクラスを定義すべきです。ここでリスナを生成していますが、まだ LocationManager に登録されていないので、位置情報は取得しません。GpsStatus
オブジェクトから GpsSatellite
オブジェクトを取得できるので、確認のために内容を整形して、アクティビティに配置した TextView に出力しています。GpsStatus.Listener
だけでなく、LocationListener
と一緒に登録しないと更新通知されません。GpsStatus.Listener
だけでなく、LocationListener
も忘れずに一緒に止めます。ついでに開発中に出会った単語などのメモ。
GpsSatellite.usedInFix()
LocationListener
からは位置情報を同時に取得できますが、このサンプルでは本題ではないので、取得した情報はそのまま捨てています。