Android百度地圖 - 在地圖上標注已知GPS緯度經度值的一個或一組覆蓋物

jopen 11年前發布 | 110K 次閱讀 Android Android開發 移動開發

闡述一個概念,地圖覆蓋物:所有疊加或覆蓋到地圖的內容,我們統稱為地圖覆蓋物。如標注、矢量圖形元素(包括:折線和多邊形和圓)、定位圖標等。覆蓋物擁有自己的地理坐標,當您拖動或縮放地圖時,它們會相應的移動。

要實現的需求:假如我們知道北京天安門(建筑物)的GPS緯度經度值:39.915,116.404,想要把它在百度地圖上標注出來。

實現上述需求的步驟:

一、準備工作:

         1、創建android工程,并導入百度地圖需要用到的jar包和so文件。

         2、在AndroidManifest文件中添加使用百度地圖SDK所需的權限及屏幕配置。

         3、在布局文件layout中添加顯示百度地圖的MapView。

         4、在繼承了Activity類的子類中:

                a. 創建并初始化地圖引擎管理對象;

                b. 通過組件ID獲取代表地圖顯示View的MapView對象,并設置相應屬性。

                  (比如:啟用內置的縮放控件、設置允許的地圖縮放級別等)

                c. 重寫Activity的生命周期回調方法onResume()、onPause()和onDestroy(),管理地圖引擎管理類對象和顯示對象生命周期。

二、在地圖上標注出北京天安門:

         1、想要在地圖上標注一個建筑物,總得有一個標識吧?

               獲取在地圖上標識建筑物的圖標對象:

       // 獲取用于在地圖上標注一個地理坐標點的圖標
        Drawable drawable = this.getResources().getDrawable(R.drawable.icon_marka);

             2、在基礎圖上添加覆蓋物(添加圖層)

                a. 編寫覆蓋物類,自己定義一個類,繼承自ItemizedOverlay類,需要重寫父類的構造函數、createItem(int index)和size()方法。

                注:從2.0.0開始,SDK不支持直接繼承Overlay , 用戶可通過繼承ItemizedOverlay來添加覆蓋物。

                b. 在自定義的覆蓋物類繼承自ItemizedOverlay)中, 聲明一個用于存放覆蓋物的集合:

/**覆蓋物列表集合*/
        private ArrayList mOverlayList = new ArrayList();

                     聲明double類型的變量存儲北京天安門的緯度、經度值:

 // 聲明double類型的變量存儲北京天安門的緯度、經度值
        private double mLat1 = 39.915; // point1緯度

        private double mLon1 = 116.404; // point1經度

                   c. 在構造函數中,將GPS緯度經度值轉換成以微度的整數形式存儲的地理坐標點

  /*  注:GeoPoint對象構造方法的參數列表:第一個是參數表示緯度,第二個是經度
                                    (我們平時都是經緯度這么叫的,想著應該是經度在前的,呵呵。)
                                      在網上查了下,GPS的值官方給的就是緯度經度,也就是說緯度是在前的,以前一直沒太注意。*/
            GeoPoint geoPoint1 = new GeoPoint((int) (mLat1 * 1E6), (int) (mLon1 * 1E6));

                       構造OverlayItem對象并添加到mOverlayList集合里

mOverlayList.add(new OverlayItem(geoPoint1, "point1", "point1"));

                      必須調用的方法:

   /* 
             * 官方的解釋:在一個新ItemizedOverlay上執行所有操作的工具方法。
             * 沒搞明白啥意思,但是必須的調用這個方法,否則程序運行報錯*/
            populate();

                   d. 返回的是從指定List集合中,取出的一個OverlayItem對象。

  /*
         * 返回的是從指定List集合中,取出的一個OverlayItem對象。
         * mOverlayList集合里一旦有了數據,在調用其之前,
         * 一定的在MyOverlayItem的構造函數里調用這個方法populate();
         */
        @Override
        protected OverlayItem createItem(int index) {
            return mOverlayList.get(index);
        }

                   e. 獲取當前覆蓋物列表的大小

  @Override
        public int size() {
            return mOverlayList.size();
        }

                  自定義的覆蓋物類的完整代碼:

 /**
     * 包含了一個覆蓋物列表的覆蓋物類
     * @author android_ls
     */
    final class MyOverlayItem extends ItemizedOverlay {

        /**覆蓋物列表集合*/
        private ArrayList mOverlayList = new ArrayList();

        // 聲明double類型的變量存儲北京天安門的緯度、經度值
        private double mLat1 = 39.915; // point1緯度

        private double mLon1 = 116.404; // point1經度

        // 傳進來的Drawable對象用于在地圖上標注一個地理坐標點
        public MyOverlayItem(Drawable drawable) {
            super(drawable);

            // 將GPS緯度經度值轉換成以微度的整數形式存儲的地理坐標點

            /*  注:GeoPoint對象構造方法的參數列表:第一個是參數表示緯度,第二個是經度
                                    (我們平時都是經緯度這么叫的,想著應該是經度在前的,呵呵。)
                                      在網上查了下,GPS的值官方給的就是緯度經度,也就是說緯度是在前的,以前一直沒太注意。*/
            GeoPoint geoPoint1 = new GeoPoint((int) (mLat1 * 1E6), (int) (mLon1 * 1E6));

            // 構造OverlayItem對象并添加到mOverlayList集合里
            mOverlayList.add(new OverlayItem(geoPoint1, "point1", "point1"));

            /* 
             * 官方的解釋:在一個新ItemizedOverlay上執行所有操作的工具方法。
             * 沒搞明白啥意思,但是必須的調用這個方法,否則程序運行報錯*/
            populate();
        }

        /*
         * 返回的是從指定List集合中,取出的一個OverlayItem對象。
         * mOverlayList集合里一旦有了數據,在調用其之前,
         * 一定的在MyOverlayItem的構造函數里調用這個方法populate();
         */
        @Override
        protected OverlayItem createItem(int index) {
            return mOverlayList.get(index);
        }

        @Override
        public int size() {
            return mOverlayList.size();
        }

    }

            創建覆蓋物(MyOverlayItem)對象并添加到覆蓋物列表中:

  mMapView.getOverlays().add(new MyOverlayItem(drawable));

         3、刷新地圖

mMapView.refresh();

運行效果圖如下:

Android百度地圖 - 在地圖上標注已知GPS緯度經度值的一個或一組覆蓋物

完整代碼:

package com.android.baidu.map;

import java.util.ArrayList;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.Toast;

import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.MKGeneralListener;
import com.baidu.mapapi.map.ItemizedOverlay;
import com.baidu.mapapi.map.MKEvent;
import com.baidu.mapapi.map.MapController;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.OverlayItem;
import com.baidu.platform.comapi.basestruct.GeoPoint;

/**
 * 在地圖上標注已知GPS緯度經度值的建筑物
 * 場景:假如我們知道北京天安門(建筑物)的GPS緯度經度值:39.915,116.404,想要把它在地圖上標注出來。
 * @author android_ls
 *
 */
public class BaiduMapOverlayActivity extends Activity {

    /**地圖引擎管理類*/
    private BMapManager mBMapManager = null;

    /**顯示地圖的View*/
    private MapView mMapView = null;

    /**
     * 經研究發現在申請KEY時:應用名稱一定要寫成my_app_應用名(也就是說"my_app_"是必須要有的)。
     * 百度地圖SDK提供的服務是免費的,接口無使用次數限制。您需先申請密鑰(key),才可使用該套SDK。
     * */
    public static final String BAIDU_MAP_KEY = "07418AEC69BAAB7104C6230A6120C580DFFAEEBB";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 注意:請在調用setContentView前初始化BMapManager對象,否則會報錯
        mBMapManager = new BMapManager(this.getApplicationContext());
        mBMapManager.init(BAIDU_MAP_KEY, new MKGeneralListener() {

            @Override
            public void onGetNetworkState(int iError) {
                if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
                    Toast.makeText(BaiduMapOverlayActivity.this.getApplicationContext(), 
                            "您的網絡出錯啦!",
                            Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onGetPermissionState(int iError) {
                if (iError == MKEvent.ERROR_PERMISSION_DENIED) {
                    // 授權Key錯誤:
                    Toast.makeText(BaiduMapOverlayActivity.this.getApplicationContext(),
                            "請在 DemoApplication.java文件輸入正確的授權Key!",
                            Toast.LENGTH_LONG).show();
                }
            }
        });

        setContentView(R.layout.main);

        mMapView = (MapView) this.findViewById(R.id.bmapsView);
        // 設置啟用內置的縮放控件
        mMapView.setBuiltInZoomControls(true);

        // 獲取地圖控制器,可以用它控制平移和縮放
        MapController mMapController = mMapView.getController();
        // 設置地圖的縮放級別。 這個值的取值范圍是[3,18]。 
        mMapController.setZoom(13);

        // 獲取用于在地圖上標注一個地理坐標點的圖標
        Drawable drawable = this.getResources().getDrawable(R.drawable.icon_marka);

        // 創建覆蓋物(MyOverlayItem)對象并添加到覆蓋物列表中
        mMapView.getOverlays().add(new MyOverlayItem(drawable));

        // 刷新地圖
        mMapView.refresh();

    }

    /**
     * 包含了一個覆蓋物列表的覆蓋物類
     * @author android_ls
     */
    final class MyOverlayItem extends ItemizedOverlay {

        /**覆蓋物列表集合*/
        private ArrayList mOverlayList = new ArrayList();

        // 聲明double類型的變量存儲北京天安門的緯度、經度值
        private double mLat1 = 39.915; // point1緯度

        private double mLon1 = 116.404; // point1經度

        // 傳進來的Drawable對象用于在地圖上標注一個地理坐標點
        public MyOverlayItem(Drawable drawable) {
            super(drawable);

            // 將GPS緯度經度值轉換成以微度的整數形式存儲的地理坐標點

            /* 注:GeoPoint對象構造方法的參數列表:第一個是參數表示緯度,
             * 第二個是經度(我們平時都是經緯度這么叫的,想著應該是經度在前的,呵呵。)
             * 在網上查了下,GPS的值官方給的就是緯度經度,也就是說緯度是在前的,以前一直沒太注意。*/
            GeoPoint geoPoint1 = new GeoPoint(
                    (int) (mLat1 * 1E6), 
                    (int) (mLon1 * 1E6));

            // 構造OverlayItem對象并添加到mOverlayList集合里
            mOverlayList.add(new OverlayItem(geoPoint1, "point1", "point1"));

            /* 
             * 官方的解釋:在一個新ItemizedOverlay上執行所有操作的工具方法。
             * 沒搞明白啥意思,但是必須的調用這個方法,否則程序運行報錯*/
            populate();
        }

        /*
         * 返回的是從指定List集合中,取出的一個OverlayItem對象。
         * mOverlayList集合里一旦有了數據,在調用其之前,
         * 一定的在MyOverlayItem的構造函數里調用這個方法populate();
         */
        @Override
        protected OverlayItem createItem(int index) {
            return mOverlayList.get(index);
        }

        @Override
        public int size() {
            return mOverlayList.size();
        }

    }

    // 重寫以下方法,管理API
    @Override
    protected void onResume() {
        mMapView.onResume();
        if (mBMapManager != null) {
            mBMapManager.start();
        }
        super.onResume();
    }

    @Override
    protected void onPause() {
        mMapView.onPause();
        if (mBMapManager != null) {
            mBMapManager.stop();
        }
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        mMapView.destroy();
        if (mBMapManager != null) {
            mBMapManager.destroy();
            mBMapManager = null;
        }
        super.onDestroy();
    }
}

三、在地圖上標注出北京天安門附近的幾個點:

從2.0.0開始,SDK不支持直接繼承Overlay 。 在地圖上顯示一個或一組覆蓋物,都可以通過繼承ItemizedOverlay來添加覆蓋物。

在上面講解的基礎上,修改覆蓋物類的部分代碼就可以了。直接上代碼:

  class MyOverlayItem extends ItemizedOverlay {

        /**覆蓋物列表集合*/
        private ArrayList mOverlayList = new ArrayList();

        // 場景:假如我們有一組建筑物的GPS經緯度值,想要把這些建筑物在地圖上標注出來。

        private double mLat1 = 39.90923; // point1緯度

        private double mLon1 = 116.397428; // point1經度

        private double mLat2 = 39.9022;// point2緯度

        private double mLon2 = 116.3922; // point2經度

        private double mLat3 = 39.917723; // point3緯度

        private double mLon3 = 116.3722; // point3緯度

        private double mLat4 = 39.915; // point4緯度

        private double mLon4 = 116.404; // point4經度

        // 傳進來的Drawable對象用于在地圖上標注一個地理坐標點
        public MyOverlayItem(Drawable drawable) {
            super(drawable);

            // 將GPS緯度經度值轉換成以微度的整數形式存儲的地理坐標點

            /*  注:GeoPoint對象構造方法的參數列表:第一個是參數表示緯度,第二個是經度
                                    (我們平時都是經緯度這么叫的,想著應該是經度在前的,呵呵。)
                                      在網上查了下,GPS的值官方給的就是緯度經度,也就是說緯度是在前的,以前一直沒太注意。*/
            GeoPoint geoPoint1 = new GeoPoint((int) (mLat1 * 1E6), (int) (mLon1 * 1E6));
            GeoPoint geoPoint2 = new GeoPoint((int) (mLat2 * 1E6), (int) (mLon2 * 1E6));
            GeoPoint geoPoint3 = new GeoPoint((int) (mLat3 * 1E6), (int) (mLon3 * 1E6));
            GeoPoint geoPoint4 = new GeoPoint((int) (mLat4 * 1E6), (int) (mLon4 * 1E6));

            // 構造OverlayItem對象并添加到mOverlayList集合里
            mOverlayList.add(new OverlayItem(geoPoint1, "point1", "point1"));
            mOverlayList.add(new OverlayItem(geoPoint2, "point2", "point2"));
            mOverlayList.add(new OverlayItem(geoPoint3, "point3", "point3"));
            mOverlayList.add(new OverlayItem(geoPoint4, "point4", "point4"));

            // 必須的調用這個方法,否則程序運行報錯
            populate();
        }

        /*
         * 返回的是從指定List集合中,取出的一個OverlayItem對象。
         * mOverlayList集合里一旦有了數據,在調用其之前,
         * 一定的在MyOverlayItem的構造函數里調用這個方法populate();
         */
        @Override
        protected OverlayItem createItem(int index) {
            return mOverlayList.get(index);
        }

        @Override
        public int size() {
            return mOverlayList.size();
        }

    }

對代碼進行優化:

GPSPonit 實體類:

package com.android.baidu.map.entity;

/**  
* 類名: Ponit.java 
* 功能描述:存放GPS緯度、經度值
* @author android_ls
* 創建日期: 2013-2-10 下午07:43:47 
* @version V1.0  
*/
public class GPSPonit {

    private double mLat; // 緯度

    private double mLon; // 經度

    public double getmLat() {
        return mLat;
    }

    public void setmLat(double mLat) {
        this.mLat = mLat;
    }

    public double getmLon() {
        return mLon;
    }

    public void setmLon(double mLon) {
        this.mLon = mLon;
    }

    public GPSPonit(double mLat, double mLon) {
        this.mLat = mLat;
        this.mLon = mLon;
    }

    public GPSPonit() {
    }

    @Override
    public String toString() {
        return "Ponit [mLat=" + mLat + ", mLon=" + mLon + "]";
    }

}

優化后的Activity類:

package com.android.baidu.map;

import java.util.ArrayList;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.Toast;

import com.android.baidu.map.entity.GPSPonit;
import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.MKGeneralListener;
import com.baidu.mapapi.map.ItemizedOverlay;
import com.baidu.mapapi.map.MKEvent;
import com.baidu.mapapi.map.MapController;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.OverlayItem;
import com.baidu.platform.comapi.basestruct.GeoPoint;

/**
 * 在地圖上標注已知GPS緯度經度值的一組建筑物
 * @author android_ls
 *
 */
public class BaiduMapOverlayItemsActivity extends Activity {

    /**地圖引擎管理類*/
    private BMapManager mBMapManager = null;

    /**顯示地圖的View*/
    private MapView mMapView = null;

    /**
     * 經研究發現在申請KEY時:應用名稱一定要寫成my_app_應用名(也就是說"my_app_"是必須要有的)。
     * 百度地圖SDK提供的服務是免費的,接口無使用次數限制。您需先申請密鑰(key),才可使用該套SDK。
     * */
    public static final String BAIDU_MAP_KEY = "07418AEC69BAAB7104C6230A6120C580DFFAEEBB";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 注意:請在調用setContentView前初始化BMapManager對象,否則會報錯
        mBMapManager = new BMapManager(this.getApplicationContext());
        mBMapManager.init(BAIDU_MAP_KEY, new MKGeneralListener() {

            @Override
            public void onGetNetworkState(int iError) {
                if (iError == MKEvent.ERROR_NETWORK_CONNECT) {
                    Toast.makeText(BaiduMapOverlayItemsActivity.this.getApplicationContext(),
                            "您的網絡出錯啦!", 
                            Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onGetPermissionState(int iError) {
                if (iError == MKEvent.ERROR_PERMISSION_DENIED) {
                    // 授權Key錯誤:
                    Toast.makeText(BaiduMapOverlayItemsActivity.this.getApplicationContext(), 
                            "請在 DemoApplication.java文件輸入正確的授權Key!", 
                            Toast.LENGTH_LONG).show();
                }
            }
        });

        setContentView(R.layout.main);

        mMapView = (MapView) this.findViewById(R.id.bmapsView);
        // 設置啟用內置的縮放控件
        mMapView.setBuiltInZoomControls(true);

        // 獲取地圖控制器,可以用它控制平移和縮放
        MapController mMapController = mMapView.getController();
        // 設置地圖的縮放級別。 這個值的取值范圍是[3,18]。 
        mMapController.setZoom(13);

        //TODO 構建一組數據
        GPSPonit gp1 = new GPSPonit(39.90923, 116.397428);
        GPSPonit gp2 = new GPSPonit(39.9022, 116.3922);
        GPSPonit gp3 = new GPSPonit(39.917723, 116.3722);
        GPSPonit gp4 = new GPSPonit(39.915, 116.404);

        /**存放GPS緯度、經度值的數組*/
        GPSPonit[] mGPSPonit = new GPSPonit[4];
        mGPSPonit[0] = gp1;
        mGPSPonit[1] = gp2;
        mGPSPonit[2] = gp3;
        mGPSPonit[3] = gp4;

        Drawable drawable = this.getResources().getDrawable(R.drawable.icon_marka);
        // 創建覆蓋物(MyOverlayItem)對象并添加到覆蓋物列表中
        mMapView.getOverlays().add(new MyOverlayItem(drawable, mGPSPonit));

        // 刷新地圖
        mMapView.refresh();
    }

    final class MyOverlayItem extends ItemizedOverlay {

        /**覆蓋物列表集合*/
        private ArrayList mOverlayList = new ArrayList();

        // 場景:假如我們有一組建筑物的GPS經緯度值,想要把這些建筑物在地圖上標注出來。

        // 傳進來的Drawable對象用于在地圖上標注一個地理坐標點
        public MyOverlayItem(Drawable drawable, GPSPonit[] gPSPonit) {
            super(drawable);

           for(int i = 0; i < gPSPonit.length; i++){
               GPSPonit gpp = gPSPonit[i];

               GeoPoint geoPoint = new GeoPoint(
                       (int) (gpp.getmLat() * 1E6),
                       (int) (gpp.getmLon() * 1E6));

               mOverlayList.add(new OverlayItem(geoPoint, "point"+i, "point1"+i));
           }

            // 必須的調用這個方法,否則程序運行報錯
            populate();
        }

        /*
         * 返回的是從指定List集合中,取出的一個OverlayItem對象。
         * mOverlayList集合里一旦有了數據,在調用其之前,
         * 一定的在MyOverlayItem的構造函數里調用這個方法populate();
         */
        @Override
        protected OverlayItem createItem(int index) {
            return mOverlayList.get(index);
        }

        @Override
        public int size() {
            return mOverlayList.size();
        }

    }

    // 重寫以下方法,管理API
    @Override
    protected void onResume() {
        mMapView.onResume();
        if (mBMapManager != null) {
            mBMapManager.start();
        }
        super.onResume();
    }

    @Override
    protected void onPause() {
        mMapView.onPause();
        if (mBMapManager != null) {
            mBMapManager.stop();
        }
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        mMapView.destroy();
        if (mBMapManager != null) {
            mBMapManager.destroy();
            mBMapManager = null;
        }
        super.onDestroy();
    }
}

運行效果圖如下:

Android百度地圖 - 在地圖上標注已知GPS緯度經度值的一個或一組覆蓋物

來自:http://blog.csdn.net/android_ls/article/details/8578044

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!