Android で GPS 衛星からの情報を NMEA 形式で取得する方法
Android 2.0 から GpsStatus.NmeaListener というリスナが追加されました。このリスナは NMEA-0183という形式で GPS 衛星の情報を取得できます。このリスナかなり細かい情報がとれて面白いのでデータを取得するプログラムを作成してみました。
なお NMEA のデータ形式については以下のサイトが詳しいのでこちらをご覧ください。
プログラム
画面イメージ
初期化処理
GpsStatus.NmeaListener リスナを追加します。このリスナを追加して LocationManager#requestLocationUpdates すると1秒おきに onNmeaReceived メソッドが呼びだされます。
※addNmeaListener するだけでは onNmeaReceived メソッドが呼び出されないので注意してください。
public class LocationCheckerActivity extends Activity implements LocationListener, GpsStatus.NmeaListener { private LocationManager locationManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); locationManager = (LocationManager)getSystemService(LOCATION_SERVICE); locationManager.addNmeaListener(this); // requestLocationUpdatesと連動して動きます。 LocationProvider p = locationManager.getProvider("gps"); locationManager.requestLocationUpdates(p.getName(), 0, 0, this); } : }
終了処理
リスナを削除します。
@Override protected void onDestroy() { super.onDestroy(); locationManager.removeUpdates(this); locationManager.removeNmeaListener(this); }
GPS 衛星の情報を表示する
実際に実機(SoftbankのDesire)で取得できたデータは GPGSV,GPGSA,GPRMC,GPVTG,GPGGA の5種類でした。なお GPGSV は1データで4機の衛星データが取得できます。4機以上のデータが取れる場合は分割して送られてきます。
// LocationListenerの処理は割愛します。 @Override public void onNmeaReceived(long timestamp, String nmea) { String[] data = nmea.split(","); // GPGSV,GPGSA,GPRMC,GPVTG,GPGGA if (data[0].equals("$GPGSA")) { TextView tv = (TextView)findViewById(R.id.nmea_gpgsa); tv.setText(nmea.trim()); } else if (data[0].equals("$GPRMC")) { TextView tv = (TextView)findViewById(R.id.nmea_gprmc); tv.setText(nmea.trim()); } else if (data[0].equals("$GPVTG")) { TextView tv = (TextView)findViewById(R.id.nmea_gpvtg); tv.setText(nmea.trim()); } else if (data[0].equals("$GPGGA")) { TextView tv = (TextView)findViewById(R.id.nmea_gpgga); tv.setText(nmea.trim()); } else if (data[0].equals("$GPGSV")) { LinearLayout layout = (LinearLayout)findViewById(R.id.nmea_gpgsv_layout); // データ件数を取得 int messageNum = Integer.valueOf(data[2]); TextView tv = (TextView)layout.findViewById(messageNum); if (tv == null) { tv = new TextView(this); layout.addView(tv); tv.setId(messageNum); } tv.setText(nmea.trim()); } }
ちなみに NMEA は National Marine Electronics Association の略らしいです。