天天看點

Android學習筆記(五六):位置Location

建議更新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

Android學習筆記(五六):位置Location

連續位置擷取小例子

下面的例子很簡單,UI是一個TextView用來顯示資訊。我們進行裝置位置的不斷跟蹤,也就是跟蹤我們的路徑。

Android學習筆記(五六):位置Location

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開發相關文章