建議更新20130522的ADT版本,無論是Linux下還是Windows下,我覺得速度快了很多。而且将Android SDK Tool更新到ver 22版本後,原來的ADT有很多不明原因問題,加載App到模拟器上出現連接配接不上的情況。
允許應用具備定位功能
Location是手機功能的一大特色,衛星導航除了GPS外,還有歐洲的伽利略和我國的北鬥,此外還有營運商移動基站的三角定位、第三方提供WiFi熱點定位等方式。相關推薦可以閱讀CDMA的定位方式。利用基站信号的強弱進行三角特定的方式(在市區内受到建築阻擋和反射等影響),利用上網的AP所出的地理位置來進行定位,都屬于粗定位coarse location,利用衛星的精确定位為fine location。應用要具備定位功能,首先必須進行權限許可。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
在模拟器中設定位置
我們可以通過DDMS在模拟器中設定經緯度,并在程式運作是修改經緯度。Window -> Open perspective -> DDMS
連續位置擷取小例子
下面的例子很簡單,UI是一個TextView用來顯示資訊。我們進行裝置位置的不斷跟蹤,也就是跟蹤我們的路徑。
public class LocationBase extends Activity{
private TextView myText;
private String textStr = "";
private LocationManager mgr=null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pure_text_view);
myText = (TextView) findViewById(R.id.pure_text);
addText("Location Based-Services Demo...");
//步驟 1: 擷取系統的定位管理器
mgr = (LocationManager)getSystemService(LOCATION_SERVICE);
addText("get system Location Manager " + mgr);
}
//步驟2.2 持續跟蹤中的停止update:在本例中,我們要求不斷獲得位置更新,我們必須在人工進行removeUpdates(),否則即使應用中所有的Activity都關閉,App仍繼續在不斷更新位置資訊,導緻應用資源無法被回收
protected void onPause() {
super.onPause();
mgr.removeUpdates(onLocationChange);
addText("Remove Updates...");
}
//步驟2:設定持續跟蹤
//步驟 2.1(1) :我們在onResume()中持續跟蹤,相應的在onPause()中關閉出現跟蹤。我們隻在Activity運作時進行跟蹤。具體見Activity的生命周期
protected void onResume() {
super.onResume();
//步驟2.1 (2):由于人的位置是不斷變化,我要設定一個位置變化的範圍,包括同時滿足最小的時間間隔和最小的位移變化,如果兩個條件要同時滿足,将位置監聽器将被觸發。實際上該方法有多個參數格式,特别是requestLocationUpdates (long minTime, float minDistance, Criteria criteria,PendingIntent intent),當位置變化時可調用其他的Activity。 在本例中,我們制定用GPS,則在權限中必須要求精确定位許可。
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 1000, onLocationChange);
addText("Request Updates automatically ...");
}
//步驟3:位置監聽器LocationListener 的設定,當位置發生變化是觸發onLocationChanged( )
LocationListener onLocationChange = new LocationListener(){
public void onLocationChanged(Location location) {
addText("Location Changed : (" + location.getLongitude()+","+location.getLatitude()+")");
}
public void onProviderDisabled(String arg0) {
addText("onProviderDisabled");
}
public void onProviderEnabled(String arg0) {
addText("onProviderEnabled");
}
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
addText("onStatusChanged");
}
};
private void addText(String s){
textStr = textStr.concat(s + "\n\n");
myText.setText(textStr);
}
}
我們可能會發現一開始并沒有出發到位置監控器的onLocationChanged(),在實際中,可能由于GPS沒有打開,或者剛打開,不能馬上得到位置資訊。在模拟器中,我們在DDMS中将按“send”按鈕即可。更改位置資訊,同樣需按“send”。
關于定位的標明
在例子中,我們指定了采用GPS,實際上位置擷取可以通過衛星,營運商,以及第三方服務擷取,即有多個資訊來源。我們可以想系統查詢可用的位置資訊源,如下:
List<String> list = mgr.getAllProviders(); //mgr即LocationManager
for(Iterator<String> i = list.iterator();i.hasNext();){
System.out.println("\t" + i.next());
}
我們可以重中進行選擇,或者讓使用者選擇,但是更好的方式是讓系統幫忙選擇。如下:
Criteria criteria = new Criteria();
String providerName = mgr.getBestProvider(criteria, true ); //criteria不能填null,否則出現異常
LocationProvider provider = mgr.getProvider(providerName);
我們可以在criteria中加入一些條件,例如一些精度setAccuracy(),和一些位置資訊setAltitudeRequired( ),是否收費setCostAllowed( )等。不是随有的條件都必須滿足,将為你比對最好的一個,當然如果你設定了免費,不會選擇收費給你的。我們根據provider的名字獲得LocationProvider的對象,但一般不需要,我們知道provider的名字,就可以向系統請求位置資訊。
Location location = mgr.getLastKnownLocation(providerName);
if(location != null)
System.out.println("Get Location from " + providerName + " : " + location.getLatitude()+ "," + location.getLongitude());
Android采用getLastKnownLocation( )來查詢,而不是目前的實時資訊。有可能由于某種情況無法擷取,例如GPS沒有打開,或正在啟動過程中,有可能傳回null。傳回的資訊可能不僅有經緯度,是否有具有海拔資訊,用location.hasAltitude()詢問,是否具有速度資訊,用hasSpeed()詢問。
到達某個位置的提醒觸發
當使用者位置到達某個目标附近 ,觸發提醒,這可以用在很多使用場景,LocationManager中可以通過addProximityAlert(),當在某位置附近可以調起pendingIntent。
public void addProximityAlert (double latitude ,
double longitude,
float radius,
long expiration,
PendingIntent intent )
對比兩個location資料
對于前後擷取的location(可能來自不同的provider,也可能擷取位置資訊的條件發生變化,例如尋找多一顆衛星或少了一顆衛星,導緻前後的精度有明顯差異),我們可以判斷哪個location更好地代表目前的地點。我們可以用location.getTime()來獲得定位資訊的更新時間,用location.getAccruacy()來擷取精度,用location.getProvider()反過來擷取providerName,用于進行提供者的比對。通過這些比較我們可以選取我們仍未最好的資料。在Android的開發者網站中給出 了選擇哪個location的例子。
相關連結: 我的Android開發相關文章