GPS で位置情報を取得する際に、GPS モジュールが一体どのようなデータを処理しているのか、その生データ(?)を取得することができます。GPS モジュールが出力する NMEA メッセージを解読することで、更に詳細な情報を得ることができます。
基本的な処理の流れは次の通りです。
LocationManager を取得するLocationManager に LocationListener を登録するLocationManager に GpsStatus.NmeaListener を登録するGpsStatus.NmeaListener のメンバ関数 onNmeaReceived がコールバックされるLocationManager から LocationListener と GpsStatus.NmeaListener を外す
必要なリスナを生成して、LocationManager と併せて一緒に登録/解除する手順は、GPS 衛星の情報を取得するケースと同じです。
人工衛星を利用した衛星測位システムのことをざっくりと "GPS" と呼んでいますが、本来の "GPS" とはアメリカが運用する衛星測位システムのことであって、実際の測位には、ロシアが運用・開発中の GLONASS や、ヨーロッパが運用・開発中の Galileo、また日本が運用・開発中の準天頂衛星システムの衛星からの電波を受信して動作しています。ですので、正しくは Global Navigation Satellite System と呼ぶのが良いようです。コンピュータ ゲーム一般のことを"ファミコン"と呼んでいるような感じですかね。
NMEA メッセージの "$" を除く最初の 2 文字は Talker ID と呼ばれ、どの機器から送信されたメッセージか識別するためのものです。例えば、手元にある実機で動作させてみたところ、LG L-05D は GPS 信号しか受信できないため、GLONASS を表す GL や、準天頂衛星システムの QZ は現れません。Nexus 7 (2012) では、準天頂衛星システムの衛星からの信号を受信できるため、GPS に加えて QZ の NMEA メッセージが現れます。Nexus 7 (2013) では更に GLONASS を受信できるようですが、手元にないため確認できていません。
GPGLQZこの NMEA メッセージには衛星に関する情報や測位情報など全て含まれているので、メッセージを自前で解析してやれば、GPS 衛星の情報や、測位情報など全て得ることができます。
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.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.NmeaListener GpsNmeaListener = 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) {}
};
GpsNmeaListener = new GpsStatus.NmeaListener()
{
public void onNmeaReceived(long timestamp, String nmea) {
TextView t = (TextView) findViewById( R.id.textView1 );
String buf = t.getText().toString();
// バッファの先頭に追加
buf = nmea + buf;
// 改行で分割
String[] bufs = buf.split( "\\r\\n" );
// 最初の 20 行だけ取り出して
buf = ""; for( int i = 0; i < 25 && i < bufs.length; i++ ) buf += bufs[i] + "\r\n";
t.setText( buf );
}
};
}
protected void onStart() { // ⇔ onStop
super.onStart();
mLocationManager.addNmeaListener( GpsNmeaListener );
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
1000 * 1/*mSec*/, 1/*meter*/,
mLocationListener );
}
protected void onStop() { // ⇔ onStart
super.onStop();
mLocationManager.removeNmeaListener( GpsNmeaListener );
mLocationManager.removeUpdates( mLocationListener );
}
}
ソースコードの基本的な部分は、前回までとほとんど同じです。
GpsStatus.NmeaListener インスタンスを生成しています。