如果你的活動想要訪問地理位置信息,但是沒有包含MapView,那會發生什麼情況呢?當使用MapView時,在MyLocationOverlay的實現中,一切都很簡單,但是如果你不使用地圖,獲取地理位置信息也不難。本節所提供的代碼不是MJAndroid的一部分,但是它說明了如何不通過MapView獲取地理位置信息。
我們一起來看一個簡單的、單活動應用,它在TextView中顯示了當前的地理位置。
Manifest文件和Layout文件
以下是常見的AndroidManifest.xml文件。我們使用Android SDK及Android Manifest Editor創建了這個文件。唯一需要使用編輯器進行修改的是為android.permission.ACCESS_FINE_LOCATION增加uses-permission標籤(在文件的倒數第二行)。我們一直需要這個權限,從而能夠從GPS地理位置提供者中獲取地理位置信息:
<?xml version=\"1.0\" encoding=\"utf-8\"?> <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" package=\"com.microjobsinc.dloc\" android:versionCode=\"1\" android:versionName=\"1.0.0\"> <application android:icon=\"@drawable/icon\" android:label=\"@string/app_name\"> <activity android:name=\".Main\" android:label=\"@string/app_name\"> <intent-filter> <action android:name=\"android.intent.action.MAIN\" /> <category android:name=\"android.intent.category.LAUNCHER\" /> </intent-filter> </activity> </application> <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"> </uses-permission> </manifest>
這裡將使用簡單的layout文件,它包含4個TextView:每個維度和經度包含一個標籤和一個文本框:
<?xml version=\"1.0\" encoding=\"utf-8\"?> <LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" android:orientation=\"vertical\" android:layout_ android:layout_ > <TextView android:id=\"@+id/lblLatitude\" android:layout_ android:layout_ android:text=\"Latitude:\" /> <TextView android:id=\"@+id/tvLatitude\" android:layout_ android:layout_ /> <TextView android:id=\"@+id/lblLongitude\" android:layout_ android:layout_ android:text=\"Longitude:\" /> <TextView android:id=\"@+id/tvLongitude\" android:layout_ android:layout_ /> </LinearLayout>
連接到LocationProvider,更新地理位置信息
我們一起實現一個活動,它連接到GPS LocationProvider,獲取並顯示當前地理位置(沒有更新):
package com.oreilly.demo.pa.microJobs; import android.app.Activity; import android.content.Context; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.widget.TextView; public class Main extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // find the TextViews TextView tvLatitude = (TextView)findViewById(R.id.tvLatitude); TextView tvLongitude = (TextView)findViewById(R.id.tvLongitude); // get handle for LocationManager LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 1 // connect to the GPS location service Location loc = lm.getLastKnownLocation(\"gps\"); 2 // fill in the TextViews tvLatitude.setText(Double.toString(loc.getLatitude)); 3 tvLongitude.setText(Double.toString(loc.getLongitude)); } }
這個過程相當簡單。以下是對上述關鍵代碼的分析:
1 通過getSystemService(Context.LOCATION_SERVICE)方法連接到LocationManager。
2 通過getLastKnownLocation(\"provider\")方法,向LocationManager查詢當前的地理位置。
3 從返回的Location中獲取維度和經度,並依據需要使用這些信息。
我們還要從LocationManager中週期性地更新位置信息,這樣在移動時可以追蹤自己的位置。為此,需要增加一個listener,當有更新時,要求LocationManager調用該listener。
應用可以通過DispLocListener類訪問LocationManager更新過來的地理位置信息,因此,在主活動中,可以在onCreate方法中創建該類的實例。需要在DispLocListener中重寫很多方法來滿足LocationListener接口定義,但是在這個應用中不需要實現這些方法,因此保留空定義。完整的實現如下所示:
package com.oreilly.demo.pa.MicroJobs; import android.app.Activity; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.widget.TextView; public class Main extends Activity { private LocationManager lm; private LocationListener locListenD; public TextView tvLatitude; public TextView tvLongitude; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // find the TextViews tvLatitude = (TextView)findViewById(R.id.tvLatitude); tvLongitude = (TextView)findViewById(R.id.tvLongitude); // get handle for LocationManager LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); // connect to the GPS location service Location loc = lm.getLastKnownLocation(\"gps\"); // fill in the TextViews tvLatitude.setText(Double.toString(loc.getLatitude)); tvLongitude.setText(Double.toString(loc.getLongitude)); // ask the Location Manager to send us location updates locListenD = new DispLocListener; lm.requestLocationUpdates(\"gps\", 30000L, 10.0f, locListenD); } private class DispLocListener implements LocationListener { @Override public void onLocationChanged(Location location) { // update TextViews tvLatitude.setText(Double.toString(location.getLatitude)); tvLongitude.setText(Double.toString(location.getLongitude)); } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } } }
onCreate方法會創建一個DispLocListener實例,請求LocationManager通過requestLocationUpdates方法更新它。該方法包含4個參數:
String provider
指定要使用的地理位置提供者。在這個例子中,假定是GPS。
long minTime
指定最小更新時間,單位是ms。LocationManager在兩次更新之間會至少等待minTime。這是為了省電。更新越頻繁,電池消耗越多。
float minDistance
觸發更新的最小距離,單位是m。只有當用戶至少移動了這麼遠的距離,LocationManager才會執行更新。
LocationListener listener
當存在更新時會調用的listener名稱,在這個例子中,即剛創建的DispLocListener實例。
最後,增加了onPause方法和onResume方法,當啟用不在用戶屏幕上顯示時,可以關閉地理位置更新,並且當再次顯示時,重新啟用地理位置更新:
/** * Turn off location updates if we\'re paused */ @Override public void onPause { super.onPause; lm.removeUpdates(locListenD); } /** * Resume location updates when we\'re resumed */ @Override public void onResume { super.onResume; lm.requestLocationUpdates(\"gps\", 30000L, 10.0f, locListenD); }
更新模擬的地理位置
在開發和調試前文所示的應用時,一般都是在模擬器上運行。在模擬器上運行代碼時,如果能夠更新當前位置將是比較理想的(甚至是比較基礎的)。這種模擬地理位置提供者可能功能很完善,但是Android提供了一些內建方式來更新模擬的地理位置:
·Android shell中提供的geo程序
·通過DDMS的一次性更新
·通過DDMS序列化更新的追蹤信息
下面將逐個解釋這些方式。
使用geo工具更新地理位置信息
geo工具構建在Android圖像中,它運行在模擬器上。geo工具包含很多功能,其中有兩個功能很有用:
geo fix
可以在模擬的Android的console上執行telnet,使用geo fix命令為Android發送地理位置信息。LocationProvider會使用該信息作為當前的地理位置:
telnet localhost 5554 Android Console: type \'help\' for a list of commands OK geo fix -122.842232 38.411908 0 OK
geo fix接受3個參數:
longitude
以十進制形式表示。
latitude
也是以十進制形式表示。
altitude
單位是米。
通過DDMS更新地理位置
第1章介紹了Dalvik Debug Monitor Server(DDMS)。這裡將探討該工具提供的和地理位置更新相關的兩個功能。DDMS屏幕的Emulator Control窗口提供了控制運行的模擬器的一些方式。當切換為DDMS方式時(單擊Eclipse窗口右上角的DDMS),在DDMS窗口的左側中間,可以看到Emulator Control窗口(如圖15-1所示)。可能需要在該窗口中使用滾動條往下拉,查看和Location Controls相關的控件。
要給該模擬器發送一次地理位置更新,只需要在相應的窗口中輸入經維度,並單擊Send按鈕。
圖15-1:DDMS Emulator Control窗口
如果單擊GPX或KML選項卡,還可以加載描述路徑的GPX文件或KML文件,如圖15-2所示。這裡,加載了文件OR.kml,在本書的網站中提供了該文件。它跟蹤位於加利福尼亞州塞巴斯玻市的O』Reilly總部附近的一條路徑。
圖15-2:包含KML地理位置更新的DDMS模擬器
可以使用GPS導航軟件工具生成GPX追蹤信息,使用Google Earth或其他導航程序生成KML追蹤信息。OR.kml文件是使用Google Earth繪製了一系列地標並把它們連接起來後生成的一個文件。以下是OR.kml文件的一個片段: