android地圖應用的開發,相信大家在網上都看過不少例子
不過基本上都是基于google地圖的,有一點不好的是基于google地圖開發的應用
不是每部手機都能夠裝的上去,要求裝置系統本身支援google地圖庫才行
而如果采用高德公司的mapabc地圖則擺脫了這種限制
下面本人就以基于mapabc的地圖應用來闡述如何在地圖上顯示自身位置
為了讓廣大開發者友善将原有的google地圖應用移植到mapabc上來
高德公司開發了與google map API相同的類與方法,基本上隻要改變導入的包即可完成移植
稍後我會将mapabc的API相關文檔同工程一并上傳
廢話不多說,先上幾張效果圖:
本例主要是擷取自身經緯度,糾偏後在地圖上顯示圖示
同時通過相應接口擷取地理位置資訊,點選位置圖示彈出氣泡顯示地理位置資訊
在擷取自身經緯度有多種方式,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