位置情報 (1) 無線ネットワークを使った位置情報 ================================================================================ ■ 無線ネットワークを使った位置情報 無線ネットワークを使った位置情報を取得する。 これも、センサーを使ったものと同じようにプログラミングできる。 基本は、以下の手順による。 1. LocationManager のオブジェクトを取得する 2. LocationManager オブジェクトに位置情報取得のリスナーを登録する 3. 位置情報が変化したら、その値を取得する ◆ アクティビティのクラス。 □ Gps01Activity.java --- package jp.marunomaruno.android.sample; import android.app.Activity; import android.location.Criteria; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import android.widget.TextView; /** * 位置情報を取得して表示する。 * @author marunomaruno * @version 1.0, 2011-12-14 * @since 1.0 */ public class Gps01Activity extends Activity { // TextView private TextView sensorValueTextView; // GPS値 private LocationManager locationManager; // (1) private LocationListener sensorEventListener; // onPause()が呼ばれたときに、すべてのリスナーを解除するため @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); sensorValueTextView = (TextView) findViewById(R.id.sensor_value); locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // (2) Log.d(getString(R.string.logTag), "locationManager = " + locationManager); } @Override protected void onResume() { super.onResume(); // プロバイダーを取得する条件を作成する Criteria fineAndLowPower = new Criteria(); // (3) fineAndLowPower.setAccuracy(Criteria.ACCURACY_FINE); // (4) fineAndLowPower.setPowerRequirement(Criteria.POWER_LOW); // (5) fineAndLowPower.setAltitudeRequired(true); // (6) fineAndLowPower.setBearingRequired(true); // (7) fineAndLowPower.setSpeedRequired(true); // (8) // プロバイダーを取得する String provider = locationManager .getBestProvider(fineAndLowPower, true); // (9) Log.d(getString(R.string.logTag), "provider = " + provider); TextView providerNameTextView = (TextView) findViewById(R.id.provider_name); providerNameTextView.setText(provider); // プロバイダーがみつからなければ、NETWORK_PROVIDER を設定しておく if (provider == null) { // (10) provider = LocationManager.NETWORK_PROVIDER; providerNameTextView.setText(R.string.no_provider); } // 位置情報のリスナーを取得して登録する sensorEventListener = new GpsLocationListener(sensorValueTextView); // (11) locationManager.requestLocationUpdates( provider, 0, 0, sensorEventListener); // (12) } @Override public void onPause() { super.onPause(); // すべてのリスナーを解除する locationManager.removeUpdates(sensorEventListener); // (13) } } --- (1)(2) LocationManager とその取得 private LocationManager locationManager; // (1) □ LocationManager LocationManager は、位置情報を管理するクラス。ここに、位置情報が変更すると起こる イベントに対するリスナーを登録する。 java.lang.Object + android.location.LocationManager このクラスのオブジェクトは、 Context.getSystemService(Context.LOCATION_SERVICE) をとおして取得する。実際は(2)を参照。 Context のサブクラスである Activity クラスのサブクラス中なので、つぎのように取得 できる。 locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // (2) (3)-(8) プロバイダーを取得する基準を作成する 位置情報を取得するためのプロバイダーを選ぶための基準を作成する。この基準に基づい て、システムは最適と思われるプロバイダーを選ぶ。 Criteria fineAndLowPower = new Criteria(); // (3) 基準オブジェクトを作成して、つぎのメソッドを使って基準を設定する。 fineAndLowPower.setAccuracy(Criteria.ACCURACY_FINE); // (4) fineAndLowPower.setPowerRequirement(Criteria.POWER_LOW); // (5) fineAndLowPower.setAltitudeRequired(true); // (6) fineAndLowPower.setBearingRequired(true); // (7) fineAndLowPower.setSpeedRequired(true); // (8) □ Criteria クラス プロバイダーを選択する上での基準になる。ここに、選択する基準を設定する。 java.lang.Object + android.location.Criteria □ 定数 --- int ACCURACY_COARSE おおよその精度 int ACCURACY_FINE 細かい精度 int ACCURACY_HIGH 高い精度 int ACCURACY_LOW 低い精度 int ACCURACY_MEDIUM 中間の精度 int NO_REQUIREMENT 要求しない int POWER_HIGH 電池を多く使う int POWER_LOW 電池をそれほど使わない int POWER_MEDIUM 電池を普通に使う --- □ コンストラクター --- Criteria() Criteria(Criteria criteria) --- □ おもな基準を設定するメソッド --- void setAccuracy(int accuracy) 緯度・経度の精度を設定 void setBearingAccuracy(int accuracy) ベアリングの精度を設定 void setHorizontalAccuracy(int accuracy) 緯度・経度の精度を設定 void setPowerRequirement(int level) 最大電力レベルを設定 void setSpeedAccuracy(int accuracy) 速度の精度を設定 void setVerticalAccuracy(int accuracy) 高度の精度を設定 void setCostAllowed(boolean costAllowed) プロバイダがコストを負担するかどうか void setAltitudeRequired(boolean altitudeRequired) 標高を出すかどうか void setBearingRequired(boolean bearingRequired) ベアリングを出すかどうか void setSpeedRequired(boolean speedRequired) 速度を出すかどうか --- なお、それぞれの基準を設定するメソッドによって、指定できる基準の定数が決まってい る。この定数以外だと、IllegalArgumentException 例外がスロー。 --------------------- ------ ------ ------ ------ ------ -------------- COARSE FINE HIGH LOW MEDIUM NO_REQUIREMENT --------------------- ------ ------ ------ ------ ------ -------------- setAccuracy ○ ○ setBearingAccuracy ○ ○ ○ setHorizontalAccuracy ○ ○ ○ ○ setSpeedAccuracy ○ ○ ○ setVerticalAccuracy ○ ○ ○ ○ --------------------- ------ ------ ------ ------ ------ -------------- ★ 今回のサンプルの(6)-(8)のように、標高、ベアリング、速度を要求しても、ネット ワーク・プロバイダーの場合、できなければ 0 が返るようだ。 GPS プロバイダーの場合、動きが止まるようだ(?)。 (9)(10) プロバイダーを取得する 作成した基準に基づいて、プロバイダーを取得する。 String provider = locationManager .getBestProvider(fineAndLowPower, true); // (9) if (provider == null) { // (10) provider = LocationManager.NETWORK_PROVIDER; providerNameTextView.setText(R.string.no_provider); } プロバイダーを取得するのは、基準を指定して、その基準にしたがって、よりよいプロバ イダーをシステムが選択する。 getBestProvider() メソッドの 2 番目の引数 enabledOnly が true の場合は、使用でき るものだけが取得されるの。使用できるプロバイダーがなければ、null が返る。 □ メソッド --- String getBestProvider(Criteria criteria, boolean enabledOnly) 基準を満たすプロバイダー名を取得する --- 上記以外にも、プロバイダーを取得したり、確認するメソッドがある。 --- List<String> getAllProviders() すべてのプロバイダー名を取得する LocationProvider getProvider(String name) 指定されたプロバイダー名のプロバイダーのオブジェクトを取得する List<String> getProviders(boolean enabledOnly) 基準を満たす、すべてのプロバイダー名を取得する List<String> getProviders(Criteria criteria, boolean enabledOnly) 基準を満たす、すべてのプロバイダー名を取得する boolean isProviderEnabled(String provider) 指定されたプロバイダー名のプロバイダーが使用できるかどうかを返す --- (11)(12) 位置情報のリスナーを取得して登録 センサーのときと同じように、リスナーのオブジェクトを取得する。 sensorEventListener = new GpsLocationListener(sensorValueTextView); // (11) 位置情報のリスナーは、LocationListener インターフェースを実装しているオブジェク トで、つぎのメソッドを実装しなければならない。 abstract void onLocationChanged(Location location) abstract void onProviderDisabled(String provider) abstract void onProviderEnabled(String provider) abstract void onStatusChanged(String provider, int status, Bundle extras) 位置情報リスナーの登録には、LocationManager.requestLocationUpdates() メソッドを 使う。 locationManager.requestLocationUpdates( provider, 0, 0, sensorEventListener); // (12) このメソッドは、いくつかオーバーロードされている。 □ requestLocationUpdates のオーバーロードされたメソッド --- void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent) 基準 に基づいた インテント を登録する void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, LocationListener listener, Looper looper) 基準 に基づいた リスナー を登録する void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) プロバイダーに基づいた リスナー を登録する void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener, Looper looper) プロバイダーに基づいた リスナー を登録する void requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent) プロバイダーに基づいた インテント を登録する --- それぞれの引数 --- long minTime 位置情報を更新する最小の時間間隔(ミリ秒) float minDistance 位置情報を更新する最小の距離間隔(メートル) Criteria criteria 基準 PendingIntent intent 位置を更新するためのインテント LocationListener listener 位置が更新されたときに呼ばれるリスナー Looper looper メッセージループのオブジェクト String provider プロバイダー --- なお、この引数 minTime や minDistance は、指定したとおりになるかどうかはわからな い。プロバイダー次第か。 □ プロバイダー LocationManager クラスのプロバイダー関係の定数 --- String GPS_PROVIDER GPS ロケーションを利用したプロバイダー String NETWORK_PROVIDER ネットワークを利用したプロバイダー String PASSIVE_PROVIDER 位置情報の修正を行わない特殊なプロバイダー --- (13) すべてのリスナーを解除する locationManager.removeUpdates(sensorEventListener); // (13) ◆ 位置情報のリスナーのクラス。 位置情報が変わったことに対するリスナーのクラス。LocationListener インターフェー スを実装する。 位置情報が変わったら、onLocationChanged() が呼ばれる。 □ GpsLocationListener.java --- package jp.marunomaruno.android.sample; import android.location.Location; import android.location.LocationListener; import android.location.LocationProvider; import android.os.Bundle; import android.util.Log; import android.widget.TextView; /** * GPSによるロケーションのリスナー * * @author maruno * @version 1.0, 2011-12-14 * @since 1.0 */ public class GpsLocationListener implements LocationListener { // (1) protected TextView textView; public GpsLocationListener(TextView textView) { this.textView = textView; } @Override public void onLocationChanged(Location location) { // (2) Log.d(textView.getResources().getString(R.string.logTag), "onLocationChanged()"); textView.setText(""); textView.append(String.format(textView.getResources().getString( R.string.sensor_value_format_for_timestamp), textView.getResources().getString(R.string.time), location.getTime())); // (3) textView.append("\n"); textView.append(String.format(textView.getResources().getString( R.string.sensor_value_format_for_real), textView.getResources().getString(R.string.latitude), location.getLatitude())); // (4) textView.append("\n"); textView.append(String.format(textView.getResources().getString( R.string.sensor_value_format_for_real), textView.getResources().getString(R.string.longitude), location.getLongitude())); // (5) textView.append("\n"); textView.append(String.format(textView.getResources().getString( R.string.sensor_value_format_for_real), textView.getResources().getString(R.string.accuracy), location.getAccuracy())); // (6) textView.append("\n"); textView.append(String.format(textView.getResources().getString( R.string.sensor_value_format_for_real), textView.getResources().getString(R.string.altitude), location.getAltitude())); // (7) textView.append("\n"); textView.append(String.format(textView.getResources().getString( R.string.sensor_value_format_for_real), textView.getResources().getString(R.string.speed), location.getSpeed())); // (8) textView.append("\n"); textView.append(String.format(textView.getResources().getString( R.string.sensor_value_format_for_real), textView.getResources().getString(R.string.bearing), location.getBearing())); // (9) textView.append("\n"); } @Override public void onProviderDisabled(String provider) { // (10) Log.d(textView.getResources().getString(R.string.logTag), "onProviderDisabled()"); } @Override public void onProviderEnabled(String provider) { // (11) Log.d(textView.getResources().getString(R.string.logTag), "onProviderEnabled()"); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { // (12) Log.d("TEST", "onStatusChanged()"); switch (status) { case LocationProvider.AVAILABLE: // (13) Log.d(textView.getResources().getString(R.string.logTag), "onStatusChanged() - AVAILABLE"); break; case LocationProvider.OUT_OF_SERVICE: // (14) Log.d(textView.getResources().getString(R.string.logTag), "onStatusChanged() - OUT_OF_SERVICE"); break; case LocationProvider.TEMPORARILY_UNAVAILABLE: // (15) Log.d(textView.getResources().getString(R.string.logTag), "onStatusChanged() - TEMPORARILY_UNAVAILABLE"); break; default: Log.d(textView.getResources().getString(R.string.logTag), "onStatusChanged() - Other"); break; } } } --- (1) LocationListener インターフェースを実装 位置情報を取得するリスナーは、LocationListener インターフェースを実装する。 public class GpsLocationListener implements LocationListener { // (1) □ LocationListener インターフェース 実装すべきメソッド --- abstract void onLocationChanged(Location location) 場所が変更されたときに呼び出される abstract void onProviderDisabled(String provider) プロバイダーが無効になったときに呼び出される abstract void onProviderEnabled(String provider) プロバイダーが有効になったときに呼び出される abstract void onStatusChanged(String provider, int status, Bundle extras) プロバイダーの状態が変更されたときに呼び出される --- (2) 場所が変更されたときに呼び出されるハンドラー・メソッド つぎのメソッドを実装する。 public void onLocationChanged(Location location) { // (2) 引数は Location オブジェクト。 □ Location クラス 位置情報を持つクラス。 java.lang.Object + android.location.Location 定数は、以下の 3 つがある。これは、緯度や経度の形式を決める。 定数 --- int FORMAT_DEGREES [+-]DDD.DDDDD、 D: 度 int FORMAT_MINUTES [+-]DDD:MM.MMMMM、D: 度、M: 分、1 度 = 60 分 int FORMAT_SECONDS [+-]DDD:MM:SS.SSSSS、D: 度、M: 分、S: 秒、1 度 = 60 分、1 分 = 60 秒 --- おもなメソッド --- static String convert (double coordinate, int outputType) 度(coordinate)を指定された緯度や経度の形式(outputType)の文字列にする float getAccuracy() 精度 double getAltitude() 標高 float getBearing() ベアリング Bundle getExtras() プロバイダー固有の情報 double getLatitude() 緯度 double getLongitude() 経度 String getProvider() プロバイダー float getSpeed() 速度 long getTime() 時間 --- convert() メソッドの実行例 Location.convert(123.456789, Location.FORMAT_DEGREES) = "123.45679" Location.convert(123.456789, Location.FORMAT_MINUTES) = "123:27.40734" Location.convert(123.456789, Location.FORMAT_SECONDS) = "123.27:24.4404" (3)-(9) 次のメソッドで、緯度や経度を取得している。 location.getTime())); // (3) location.getLatitude())); // (4) location.getLongitude())); // (5) location.getAccuracy())); // (6) location.getAltitude())); // (7) location.getSpeed())); // (8) location.getBearing())); // (9) (10) プロバイダーが無効になったときに呼び出されるハンドラー・メソッド public void onProviderDisabled(String provider) { // (10) (11) プロバイダーが有効になったときに呼び出されるハンドラー・メソッド public void onProviderEnabled(String provider) { // (11) (12) プロバイダーの状態が変更されたときに呼び出されるハンドラー・メソッド public void onStatusChanged(String provider, int status, Bundle extras) { // (12) 今回のように、ひとつのプロバイダーを登録しているだけだと動かないようだ。 (13)-(15) 状態の変化 LocationProvider の定数によって、どいう状態かを判断する。 case LocationProvider.AVAILABLE: // (13) case LocationProvider.OUT_OF_SERVICE: // (14) case LocationProvider.TEMPORARILY_UNAVAILABLE: // (15) LocationProvider の定数 --- int AVAILABLE int OUT_OF_SERVICE int TEMPORARILY_UNAVAILABLE --- ◆ レイアウト □ res/layout/main.xml --- <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <!-- プロバイダー名 --> <TextView android:id="@+id/provider_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <!-- センサー値 --> <TextView android:id="@+id/sensor_value" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> --- ◆ 文字列の定数 □ res/values/string.xml --- <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Gps01</string> <string name="logTag">TEST</string> <string name="no_provider">プロバイダーは見つかりませんでした。</string> <string name="gpsUnit">m/s^2</string> <string name="sensor_value_format_for_real">%1$s = %2.2f</string> <string name="sensor_value_format_for_timestamp">%1$s = %2$tF %2$tT</string> <string name="latitude">緯度</string> <string name="longitude">経度</string> <string name="accuracy">精度</string> <string name="altitude">標高</string> <string name="time">時間</string> <string name="speed">速度</string> <string name="bearing">ベアリング</string> </resources> --- ◆マニフェスト ユーザーパーミッションをつける。 □AndroidManifest.xml --- <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="jp.marunomaruno.android.sample" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <!-- (1) --> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/> <!-- (2) --> <uses-permission android:name="android.permission.INTERNET"/> <!-- (3) --> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".Gps01Activity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> --- (1)-(3) パーミッションは以下のものを使う ACCESS_FINE_LOCATION GPS を使う ACCESS_MOCK_LOCATION エミュレーターで GPS をエミュレートする INTERNET 無線を使う これを、AndroidManifest.xml に記述する。
最新の画像[もっと見る]
-
あけましておめでとうございます 11年前
-
今年もよろしくお願いいたします 12年前
-
あけましておめでとうございます 13年前
-
あけましておめでとうございます 16年前
※コメント投稿者のブログIDはブログ作成者のみに通知されます