天天看點

mapabc地圖開發之定位篇(GPS+谷歌基站定位+高德基站定位)

android地圖應用的開發,相信大家在網上都看過不少例子

不過基本上都是基于google地圖的,有一點不好的是基于google地圖開發的應用

不是每部手機都能夠裝的上去,要求裝置系統本身支援google地圖庫才行

而如果采用高德公司的mapabc地圖則擺脫了這種限制

下面本人就以基于mapabc的地圖應用來闡述如何在地圖上顯示自身位置

為了讓廣大開發者友善将原有的google地圖應用移植到mapabc上來

高德公司開發了與google map API相同的類與方法,基本上隻要改變導入的包即可完成移植

稍後我會将mapabc的API相關文檔同工程一并上傳

廢話不多說,先上幾張效果圖:

mapabc地圖開發之定位篇(GPS+谷歌基站定位+高德基站定位)
mapabc地圖開發之定位篇(GPS+谷歌基站定位+高德基站定位)
mapabc地圖開發之定位篇(GPS+谷歌基站定位+高德基站定位)

本例主要是擷取自身經緯度,糾偏後在地圖上顯示圖示

同時通過相應接口擷取地理位置資訊,點選位置圖示彈出氣泡顯示地理位置資訊

在擷取自身經緯度有多種方式,android API裡提供的LocationManager就可以通過GPS 或 網絡 擷取位置

不過使用該類的前提是裝置上相關的設定選項要打開,否則是監聽不到位置資訊的

除此之外我們還可以擷取基站資訊然後通過google提供的基站定位接口來擷取到經緯度

同時使用mapabc的話還可直接通過其提供的LocationManagerProxy類來監聽擷取位置

值得注意的是此時得到的位置已經是糾偏後的位置了

本例分别以以上三種定位方式擷取位置然後在地圖上顯示

同時可通過菜單來比對基站定位與實際GPS定位的誤差(在室外打開GPS選項來測試)

本人親測google基站定位要比高德基站定位準一些,一般誤差在一兩百米以内

google到底是老大,不過糾偏的話當然還是高德準啦,自家的地圖自家的算法

下面貼上部分源碼稍作分析

且看主ACTIVITY有以下成員變量

public class TestMapABCDemoActivity extends MapActivity{

    private final static String TAG = "TestMapABCDemoActivity";

    private MapView mMapView;                                   //地圖VIEW

    private MapController mMapController;                       //控制器

    private List<Overlay> mOverlayList;                           //地圖圖層容器

    private View mPopView;                                      //地圖氣泡

    private MyLocationManager mLocationManager;                     // LocationManager API擷取位置

    private MyLocationListen mListen;                       

    private MyPositionOverlay mGoogleOverlay;

    private MyStationLocationManager mStationLocationManager;       //google基站接口擷取位置

    private MyStationLocationListen mStationLocationListen;

    private MyPositionOverlay mStationOverlay;

    private MyGaodeLocationManager mGaodeLocationManager;           //高德基站接口擷取位置

    private MyGaodeListen mGaodeLocationListen;

    private MyPositionOverlay mGaoDeOverlay;

    private Handler mHandler;

初始化調以下兩個方法

    public void initView()

    {

        mMapView = (MapView) findViewById(R.id.main_mapView);

        mMapView.setBuiltInZoomControls(true);              // 設定啟用内置的縮放控件

        mMapController = mMapView.getController();          // 得到mMapView的控制權,可以用它控制和驅動平移和縮放

        mOverlayList = mMapView.getOverlays();              // 得到圖層容器

        // 設定氣泡位置

        mPopView = getLayoutInflater().inflate(R.layout.map_popup, null);

        mMapView.addView(mPopView,new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, 

                                                            MapView.LayoutParams.WRAP_CONTENT,

                                                            null,

                                                            MapView.LayoutParams.BOTTOM_CENTER));  

        mPopView.setVisibility(View.GONE);

        // android API定位自身位置圖示

        mGoogleOverlay = new MyPositionOverlay(this, getResources().getDrawable(R.drawable.marker_google), mPopView, mMapView); 

        mGoogleOverlay.setColor(Color.argb(50, 0, 119, 192));

        mOverlayList.add(mGoogleOverlay);

        // google基站定位自身位置圖示

        mStationOverlay = new MyPositionOverlay(this, getResources().getDrawable(R.drawable.marker_station) , mPopView, mMapView);  

        mStationOverlay.setColor(Color.argb(50, 255, 100, 55));

        mOverlayList.add(mStationOverlay);

        // 高德基站定位自身位置圖示

        mGaoDeOverlay = new MyPositionOverlay(this, getResources().getDrawable(R.drawable.marker_gaode),  mPopView, mMapView);  

        mGaoDeOverlay.setColor(Color.argb(50, 0, 136, 25));

        mOverlayList.add(mGaoDeOverlay);

        GeoPoint point = new GeoPoint((int) (MyConstant.DOUBLE_STUDEN_LAT * 1E6),

                (int) (MyConstant.DOUBLE_STUDEN_LON * 1E6));  //用給定的經緯度構造一個GeoPoint,

        mMapController.setCenter(point);  //設定地圖中心點

        mMapController.setZoom(15);    //設定地圖zoom級别

    }

    public void initLogic()

    {

        mHandler = new Handler()

        {

            @Override

            public void handleMessage(Message msg) {

                // TODO Auto-generated method stub

            }

        };

        mLocationManager = new MyLocationManager(this);

        mListen = new MyLocationListen(this, mHandler, new UpdateLocationRunnable());

        mStationLocationManager = new MyStationLocationManager(this);

        mStationLocationListen = new MyStationLocationListen(this, mHandler, new UpdateStationLocationRunnable());

        mGaodeLocationManager = new MyGaodeLocationManager(this);

        mGaodeLocationListen = new MyGaodeListen(mHandler, new UpdateGaodeLocationRunnable());

    }

一個是地圖相關控件的初始化,一個是三種定位方式的類對象初始化

在resume和pause裡進行注冊監聽和反注冊監聽

@Override

    protected void onPause() {

        // TODO Auto-generated method stub

        super.onPause();

        // 取消監聽

        mLocationManager.unRegisterListen();

        mStationLocationManager.unRegisterListen();

        mGaodeLocationManager.unRegisterListen();

    }

    @Override

    protected void onResume() {

        // TODO Auto-generated method stub

        super.onResume();

        // 注冊監聽

        mLocationManager.registerListen(mListen);

        mStationLocationManager.registerListen(mStationLocationListen);

        mGaodeLocationManager.registerListen(mGaodeLocationListen);

    }

設定以三十秒的頻率更新位置

在重新整理位置後進行糾偏(LocationManagerProxy不用糾偏)和擷取地理位置資訊

由于這兩個都要聯網擷取,是以不能在UI線程裡操作

下面看看這三種定位方式的監聽器實作

android API location監聽器

public class MyLocationListen implements LocationListener

{

    private Handler mHandler;

    private IONSetLocation mRunnable;

    private Context mContext;

    public MyLocationListen(Context context, Handler handler, IONSetLocation runnable)

    {

        mHandler = handler;

        mRunnable = runnable;

        mContext = context;

    }

    @Override

    public void onLocationChanged(Location location) {

        // TODO Auto-generated method stub

        if (mHandler != null)

        {

            Thread thread = new InnerThread(location);

            thread.start();

        }

    }

    class InnerThread extends Thread

    {

        private Location mLocation;

        public InnerThread( Location location)

        {

            mLocation = location;       

        }

        @Override

        public void run() {

            // TODO Auto-generated method stub

            Location newLocation = WebManager.correctPosToMap(mLocation, mContext);

            mRunnable.setLocation(newLocation);

            try {

                mRunnable.setAdress(WebManager.getAddressByGoogle(mLocation));

            } catch (Exception e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            mHandler.post( mRunnable);

        }

    }

    @Override

    public void onProviderDisabled(String provider) {

        // TODO Auto-generated method stub

    }

    @Override

    public void onProviderEnabled(String provider) {

        // TODO Auto-generated method stub

    }

    @Override

    public void onStatusChanged(String provider, int status, Bundle extras) {

        // TODO Auto-generated method stub

    }

}

onLocationChange方法是在UI線程裡執行的,是以需要開子線程進行查詢操作

google基站 位置監聽

public class MyStationLocationListen implements LocationListener

{

    private Handler mHandler;

    private IONSetLocation mRunnable;

    private Context mContext;

    public MyStationLocationListen(Context context, Handler handler, IONSetLocation runnable)

    {

        mHandler = handler;

        mRunnable = runnable;

        mContext = context;

    }

    @Override

    public void onLocationChanged(Location location) {

        // TODO Auto-generated method stub

        if (mHandler != null)

        {

            Location newLocation = WebManager.correctPosToMap(location, mContext);

            mRunnable.setLocation(newLocation);

            try {

                mRunnable.setAdress(WebManager.getAddressByGoogle(location));

            } catch (Exception e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            mHandler.post( mRunnable);

        }

    }

    @Override

    public void onProviderDisabled(String provider) {

        // TODO Auto-generated method stub

    }

    @Override

    public void onProviderEnabled(String provider) {

        // TODO Auto-generated method stub

    }

    @Override

    public void onStatusChanged(String provider, int status, Bundle extras) {

        // TODO Auto-generated method stub

    }

}

這個所謂的位置監聽是假的,其實就是開了個定時器每隔三十秒擷取基站資訊然後在擷取位置

看它對應的locationmanager實作

public class MyStationLocationManager {

    private final static int CHECK_POSITION_INTERVAL = 30 * 1000;

    private Context mContext;

    private Timer mTimer;

    private MyTimeTask mTimeTask;

    private LocationListener mListener;

    public MyStationLocationManager(Context context)

    {

        mContext = context;

        mTimer = new Timer();

    }

    public void registerListen(LocationListener listener)

    {

        if (mListener == null)

        {

            mListener = listener;

            startTimer();

        }

    }

    public void unRegisterListen()

    {

        stopTimer();

        mListener = null;       

    }

    private void startTimer( )

    {

        if (mTimeTask == null)

        {

            mTimeTask = new MyTimeTask();

            mTimer.schedule(mTimeTask, 0, CHECK_POSITION_INTERVAL);

        }

    }

    private void stopTimer()

    {

        if (mTimeTask != null)

        {

            mTimeTask.cancel();

            mTimeTask = null;

        }

    }

    class MyTimeTask extends TimerTask

    {

        @Override

        public void run() {

            // TODO Auto-generated method stub

            //Toast.makeText(mContext, "run", Toast.LENGTH_SHORT).show();

            List<CellIDInfo> list = null;

            Location location = null;

            try {

                list = CellIDInfoManager.getCellIDInfo(mContext);

                location = WebManager.callGear(list);

            } catch (Exception e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            if (mListener != null)

            {

                mListener.onLocationChanged(location);

            }

        }

    }

}

看到木有

再看高德的

public class MyGaodeListen implements LocationListener 

{

    private Handler mHandler;

    private IONSetLocation mRunnable;

    public MyGaodeListen(Handler handler, IONSetLocation runnable)

    {

        mHandler = handler;

        mRunnable = runnable;

    }

    @Override

    public void onLocationChanged(Location location) {

        // TODO Auto-generated method stub

        if (mHandler != null)

        {

            mRunnable.setLocation(location);

            try {

                mRunnable.setAdress(WebManager.getAddressByGoogle(location));

            } catch (Exception e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            mHandler.post( mRunnable);

        }

    }

    @Override

    public void onProviderDisabled(String provider) {

        // TODO Auto-generated method stub

    }

    @Override

    public void onProviderEnabled(String provider) {

        // TODO Auto-generated method stub

    }

    @Override

    public void onStatusChanged(String provider, int status, Bundle extras) {

        // TODO Auto-generated method stub

    }

}

public class MyGaodeLocationManager {

    private final static int CHECK_POSITION_INTERVAL = 30 * 1000;

    private LocationManagerProxy mLocationManagerProxy;

    private Context mContext;

    private LocationListener mListener;

    public MyGaodeLocationManager(Context context)

    {

        mContext = context;

        mLocationManagerProxy = LocationManagerProxy.getInstance(context, context.getString(R.string.maps_api_key));

    }

    public void clear()

    {

        mLocationManagerProxy.destory();

    }

    public void registerListen(LocationListener listener)

    {

        if (mListener == null)

        {

            mListener = listener;

            mLocationManagerProxy.requestLocationUpdates(LocationProviderProxy.MapABCNetwork, CHECK_POSITION_INTERVAL, 0, listener);

        }

    }

    public void unRegisterListen()

    {

        if (mListener != null)

        {

            mLocationManagerProxy.removeUpdates(mListener);

        }

    }

}

采用自家的LocationManagerProxy 調用 requestLocationUpdates(LocationProviderProxy.MapABCNetwork, CHECK_POSITION_INTERVAL, 0, listener);

器MapABCNetwork的值是lbs,得到的位置無需糾偏即可顯示

地圖氣泡的知識在此就不多做解釋了,網上搜搜吧

代碼分析到此為止,附屬工程連結:

http://download.csdn.net/detail/geniuseoe2012/4345880

還有mapabc官方文檔(很齊全哦)

http://download.csdn.net/detail/geniuseoe2012/4345909