百度地圖API之MyLocationOverlay的使用(Android)


     http://www.linuxidc.com/Linux/2011-07/38867p2.htm

    本篇文章主要講解Baidu Map API中MyLocationOverlay的使用。故名思義,MyLocation中文釋義為“我的位置”,而Overlay則是“圖層”或“覆蓋物”的意思,MyLocationOverlay的作用正是用於在地圖上標注自己所處的位置。它跟使用ItemizedOverlay非常相似,只不過MyLocationOverlay標記的只有一個點。

      在地圖上標記用戶當前所處位置其實是一個GPS定位應用。首先通過GPS定位獲取到用戶當前所在位置的經緯度,再將該經緯度所代表的點在地圖上標出來。其實除了在地圖上標注自己所處的位置外,我們通常還有這樣的需求:“如果我的位置發生改變,要能夠實時在地圖上體現出來”。
      下面我們就來一步步實現上面想要的功能,主要是通過MyLocationOverlay結合LocationListener來實現的。
1)創建布局文件res/layout/main.xml 

<?xml version="1.0" encoding="utf-8"?>   
<LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"   
    Android:orientation="vertical"   
    Android:layout_width="fill_parent"   
    Android:layout_height="fill_parent"   
    >   
    <com.baidu.mapapi.MapView Android:id="@+id/map_View"   
        Android:layout_width="fill_parent"   
        Android:layout_height="fill_parent"   
        Android:clickable="true"   
    />   
</LinearLayout>

2)創建Activity繼承com.baidu.mapapi.MapActivity

package com.liufeng.baidumap;   
   
import Android.location.Location;   
import Android.os.Bundle;   
   
import com.baidu.mapapi.BMapManager;   
import com.baidu.mapapi.GeoPoint;   
import com.baidu.mapapi.LocationListener;   
import com.baidu.mapapi.MKLocationManager;   
import com.baidu.mapapi.MapActivity;   
import com.baidu.mapapi.MapController;   
import com.baidu.mapapi.MapView;   
import com.baidu.mapapi.MyLocationOverlay;   
   
/**  
 * 創建Activity(繼承com.baidu.mapapi.MapActivity)  
 *   
 * @author liufeng  
 * @date 2011-05-02  
 */   
public class MyLocationActivity extends MapActivity implements LocationListener {   
    private BMapManager mapManager;   
    private MKLocationManager mLocationManager = null;   
    private MyLocationOverlay myLocationOverlay;   
   
    private MapView mapView;   
    private MapController mapController;   
   
    @Override   
    public void onCreate(Bundle savedInstanceState) {   
        super.onCreate(savedInstanceState);   
        setContentView(R.layout.main);   
   
        // 初始化MapActivity    
        mapManager = new BMapManager(getApplication());   
        // init方法的第一個參數需填入申請的API Key    
        mapManager.init("285B415EBAB2A92293E85502150ADA7F03C777C4", null);   
        super.initMapActivity(mapManager);   
   
        mLocationManager = mapManager.getLocationManager();   
        // 注冊位置更新事件    
        mLocationManager.requestLocationUpdates(this);   
        // 使用GPS定位    
        mLocationManager.enableProvider((int) MKLocationManager.MK_GPS_PROVIDER);   
   
        mapView = (MapView) findViewById(R.id.map_View);   
        // 設置地圖模式為交通地圖    
        mapView.setTraffic(true);   
        // 設置啟用內置的縮放控件    
        mapView.setBuiltInZoomControls(true);   
   
        // 構造一個經緯度點    
        GeoPoint point = new GeoPoint((int) (26.597239 * 1E6), (int) (106.720397 * 1E6));   
   
        // 取得地圖控制器對象,用於控制MapView    
        mapController = mapView.getController();   
        // 設置地圖的中心    
        mapController.setCenter(point);   
        // 設置地圖默認的縮放級別    
        mapController.setZoom(7);   
   
        // 添加定位圖層    
        myLocationOverlay = new MyLocationOverlay(this, mapView);   
        // 注冊GPS位置更新的事件,讓地圖能實時顯示當前位置    
        myLocationOverlay.enableMyLocation();   
        // 開啟磁場感應傳感器    
        myLocationOverlay.enableCompass();   
        mapView.getOverlays().add(myLocationOverlay);   
    }   
   
    @Override   
    protected boolean isRouteDisplayed() {   
        return false;   
    }   
   
    @Override   
    protected void onDestroy() {   
        if (mapManager != null) {   
            mapManager.destroy();   
            mapManager = null;   
        }   
        mLocationManager = null;   
        super.onDestroy();   
    }   
   
    @Override   
    protected void onPause() {   
        if (mapManager != null) {   
            mapManager.stop();   
        }   
        super.onPause();   
    }   
   
    @Override   
    protected void onResume() {   
        if (mapManager != null) {   
            mapManager.start();   
        }   
        super.onResume();   
    }   
   
    /**  
     * 根據MyLocationOverlay配置的屬性確定是否在地圖上顯示當前位置  
     */   
    @Override   
    protected boolean isLocationDisplayed() {   
        return myLocationOverlay.isMyLocationEnabled();   
    }   
       
    /**  
     * 當位置發生變化時觸發此方法  
     *   
     * @param location 當前位置  
     */   
    @Override   
    public void onLocationChanged(Location location) {   
        if (location != null) {   
            // 將當前位置轉換成地理坐標點    
            final GeoPoint pt = new GeoPoint((int) (location.getLatitude() * 1000000), (int) (location.getLongitude() * 1000000));   
            // 將當前位置設置為地圖的中心    
            mapController.setCenter(pt);   
        }   
    }   
}

簡單解釋:代碼中是通過MyLocationOverlay在地圖上標記當前所在位置的,通過實現監聽器接口com.baidu.mapapi.LocationListener並重寫它的onLocationChanged方法來監聽位置的變化。(注意LocationListener是baidu map api里的,而不是Android自帶的)

3)在AndroidManifest.xml中配置 

<?xml version="1.0" encoding="utf-8"?>   
<manifest xmlns:Android="http://schemas.android.com/apk/res/android"   
      package="com.liufeng.baidumap"   
      Android:versionCode="1"   
      Android:versionName="1.0">   
    <application Android:icon="@drawable/icon" android:label="@string/app_name">   
        <activity Android:name=".MyLocationActivity" 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-sdk Android:minSdkVersion="4" />   
   
    <!-- 訪問網絡的權限 -->   
    <uses-permission Android:name="android.permission.INTERNET" />   
    <!-- 訪問精確位置的權限 -->   
    <uses-permission Android:name="android.permission.ACCESS_FINE_LOCATION" />   
    <!-- 訪問網絡狀態的權限 -->   
    <uses-permission Android:name="android.permission.ACCESS_NETWORK_STATE" />   
    <!-- 訪問WIFI網絡狀態的權限 -->   
    <uses-permission Android:name="android.permission.ACCESS_WIFI_STATE" />   
    <!-- 改變WIFI網絡狀態的權限 -->   
    <uses-permission Android:name="android.permission.CHANGE_WIFI_STATE" />   
    <!-- 讀寫存儲卡的權限 -->   
    <uses-permission Android:name="android.permission.WRITE_EXTERNAL_STORAGE" />   
    <!-- 讀取電話狀態的權限 -->   
    <uses-permission Android:name="android.permission.READ_PHONE_STATE" />   
</manifest>

到這里,我們的代碼編寫工作就已經完成了。接下來,再模擬器里運行一下,看看效果,下圖是在模擬器里運行的截圖: 

怎么回事?不是說能夠在地圖上標注出當前位置的,好像並沒有標注。沒錯,的確是沒有標注出當前位置。這是什么原因呢?前面說了,我們要實現的是一個GPS結合Map的簡單定位應用。手機的GPS定位是依賴於手機設備上的一塊GPS物理芯片來實現的,並不是手機上裝個GPS軟件就能實現定位的。問題就很明顯了,因為我們是在模擬器里運行上面的程序,模擬器上可沒有GPS物理芯片,當然也就不能實現定位了。
      好在DDMS為我們提供了模擬GPS信號的功能,它可以通過三種方式來模擬:自定義經緯度、使用GPX文件或KML文件(這些文件是GPS信息記錄的文件格式)。依次點擊Eclipse上的"Window"-"Show View"-"Other"-"Android"-"Emulator Control",就能夠看到如下所示的界面:

這個就是用來模擬GPS信號的。可以看到有三個標簽項:Manual、GPX和KML,分別對應於上面所說的“自定義經緯度”、“使用GPX文件”和“使用KML文件”三種方式來模擬GPS信號。這里我們采用第一種方式,因為它最簡單,也最直觀,好理解。
      我們輸入一個經緯度值(經度:106.720397,緯度:26.597239),然后點擊“Send”按鈕,模擬器將會收到該信號,這意味模擬器設備當前所處的位置正是我們所發送的這個經緯度所代表的位置,這樣就能在地圖上標記出當前所處位置了。真的是這樣嗎?那我們趕緊嘗試一下。輸入經緯度值的截圖如下:

點擊發送按鈕后,再來看下模擬器上顯示的地圖是否發生變化:

可以看到,已經在地圖上標記出了“當前位置”,就是那個藍色的圓點。到這里我們工作還沒有完,請繼續往下看。
      最開始的需求里有這樣一條:“如果我的位置發生改變,要能夠實時在地圖上體現出來”,我們的代碼里是否已實現該功能呢,當然。那如何來模擬演示該功能呢?其實也很簡單,我們再向模擬器發送另外一組不同的經緯度值,這就相當於設備所處的位置發生了改變。比如我們再次發送的經緯度值為“經度:106.720397,緯度:24.597239”,再來看下運行結果的變化:

可以看到,當位置發生變動時,是能夠時時體現在地圖上的。到這里我們的所有工作就算完成了。

備注:建議如果有條件的朋友,盡量買部Android真機來做開發測試,因為模擬器並不能真實地模擬手機上的所有功能。有很多時候很可能你的程序一點問題也沒有,但是由於模擬器不支持或者你不清楚如何通過模擬器來模擬某種功能而導致你反復的調試修改代碼,造成不必要的時間浪費。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM