そんなにBlog updateするなら俺だってLocationManager - User Location情報取得
前回Postの予告通り、今回はLocationManagerを実装したいと思います。LocationManagerを使用し、User Location情報を取得しGoogle Map等と連携する事が出来ます。下記のScreen shotのような情報を取得出来ます
LocationManagerとは
LocationManagerを使用するとSystemが提供するLocation serviceにaccessすることが出来ます。Location serviceにより定期的にLocation情報を取得したり、ある特定の場所に近づくと通知を受け取ったりすることが出来ます(原文、ここ)
実装の要点は下記です
- AndroidManifest.xmlにandroid.permission.ACCESS_FINE_LOCATIONを追加
- LocationManagerを取得
- Intentを作成
- 上記IntentからPendingIntentを作成
- LocationManagerにPendingIntentを登録
- 該当のIntentに反応するようにReceiverにIntentFilterを登録
- BroadcastReceiverを拡張したclassでLocationManagerから発行されたIntentを受信した際の処理を記載
- LocationManagerに登録していたIntentをキャンセル(キャンセルしないとBatteryの消耗量がとてつもないことになります)
気づいた点をまとめます
- Geocoder#getFromLocation()はNetworkにaccessするので本来ならUI threadとは別threadで処理をした方がよい
んで実装です
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.practice" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".LocationManagerActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.android.practice.LocationUpdateReceiver"/> </application> <!-- AndroidManifest.xmlにandroid.permission.ACCESS_FINE_LOCATIONを追加 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> </manifest>
Activity, BroadcastReceiver
package com.android.practice; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Locale; import android.app.Activity; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.location.Address; import android.location.Geocoder; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class LocationManagerActivity extends Activity { private static final boolean DEBUG = true; private static final String TAG = "LocationManagerActivity"; private static final String ACTION_LOCATION_UPDATE = "com.android.practice.ACTION_LOCATION_UPDATE"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); setOnClickListeners(); setIntentFilterToReceiver(); } private void setOnClickListeners(){ final Button requestLocationBtn = (Button)findViewById(R.id.request_location); final Button removeUpdateBtn = (Button)findViewById(R.id.remove_update); requestLocationBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { requestLocationUpdates(); } }); removeUpdateBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { removeUpdates(); } }); } private void requestLocationUpdates(){ final Context context = LocationManagerActivity.this; final PendingIntent requestLocation = getRequestLocationIntent(context); //LocationManagerを取得する LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE); for(String providerName: lm.getAllProviders()){ if(lm.isProviderEnabled(providerName)){ if(DEBUG)Log.d(TAG, "Provider: " + providerName); //LocationManagerにPendingIntentを登録 lm.requestLocationUpdates(providerName, 0, 0, requestLocation); } } if(DEBUG){ Toast.makeText(context, "Request Location", Toast.LENGTH_SHORT).show(); } } private void removeUpdates(){ final Context context = LocationManagerActivity.this; final PendingIntent requestLocation = getRequestLocationIntent(context); LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE); //LocationManagerに登録していたIntentをキャンセル lm.removeUpdates(requestLocation); if(DEBUG){ Toast.makeText(context, "Remove update", Toast.LENGTH_SHORT).show(); } } private PendingIntent getRequestLocationIntent(Context context){ //Intentを作成 final Intent intent = new Intent(); intent.setAction(ACTION_LOCATION_UPDATE); //PendingIntentを作成 return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } private void setIntentFilterToReceiver(){ //該当のIntentに反応するようにReceiverにIntentFilterを登録 final IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_LOCATION_UPDATE); registerReceiver(new LocationUpdateReceiver(), filter); } public class LocationUpdateReceiver extends BroadcastReceiver{ //BroadcastReceiverを拡張したclassでLocationManagerから発行されたIntentを受信した際の処理を記載 @Override public void onReceive(Context context, Intent intent) { if(DEBUG)Log.d(TAG, "onReceive"); String action = intent.getAction(); if(action != null && action.equals(ACTION_LOCATION_UPDATE)){ final Location location = (Location) intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED); if(location == null){ return; } updateView(location); if(DEBUG)Toast.makeText(context, "Location update", Toast.LENGTH_SHORT).show(); } } private void updateView(Location location){ final Activity activity = LocationManagerActivity.this; ((TextView)activity.findViewById(R.id.accuracy)).setText("Accuracy: " + String.valueOf(location.getAccuracy())); ((TextView)activity.findViewById(R.id.altitude)).setText("Altitude: " + String.valueOf(location.getAltitude())); ((TextView)activity.findViewById(R.id.bearing)).setText("Bearing: " + String.valueOf(location.getBearing())); ((TextView)activity.findViewById(R.id.latitude)).setText("latitude: " + String.valueOf(location.getLatitude())); ((TextView)activity.findViewById(R.id.longitude)).setText("longitude: " + String.valueOf(location.getLongitude())); ((TextView)activity.findViewById(R.id.provider)).setText("Provider: " + String.valueOf(location.getProvider())); ((TextView)activity.findViewById(R.id.speed)).setText("Speed: " + String.valueOf(location.getSpeed())); ((TextView)activity.findViewById(R.id.time)).setText("Time: " + String.valueOf(location.getTime())); ((TextView)activity.findViewById(R.id.address)).setText("Address: " + getAddress((Context)activity, location.getLatitude(), location.getLongitude())); } private String getAddress(Context context, double latitude, double longitude){ String addressString = null; Geocoder gCoder = new Geocoder(context, Locale.getDefault()); List<Address> addresses = new ArrayList<Address>(); try { //Geocoder#getFromLocation()はNetworkにaccessするので本来ならUI threadとは別threadで処理をした方がよい addresses = gCoder.getFromLocation(latitude, longitude, 1); } catch (IOException e) { e.printStackTrace(); } for(Address address: addresses){ address.setLatitude(latitude); address.setLongitude(longitude); final int maxIndex = address.getMaxAddressLineIndex(); for(int i = 0; i < maxIndex; i++){ final String element = address.getAddressLine(i); if(element != null){ if(addressString != null){ addressString += element; }else{ addressString = element; } } } } return addressString; } } }
と、まあ、こんな感じです。前回のAlarmManagerと使用方法は一緒ですね。
Google Map等と連携して手軽にUser Location情報を利用したapplicationを作成出来ますね。
HashTag #Java, #Android, #LocationManager, #BroadcastReceiver, #Geocoder, #Address