首页 > 代码库 > Android 百度地图 SDK v3.0.0 (四) 引入离线地图功能

Android 百度地图 SDK v3.0.0 (四) 引入离线地图功能

Android 百度地图 SDK v3.0.0 (四) 引入离线地图功能

 

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37758097

一直觉得地图应用支持离线地图很重要啊,我等移动2G屌丝,流量不易,且用且珍惜。

 

对于官方开发指南对于离线地图的教程,提供了两种方案:

第一,手动导入,先将从官网下载的离线包解压,把vmp文件夹拷入SD卡根目录下的BaiduMapSDK文件夹内。好吧,我表示不能接受,无视了。

第二,接口下载方法如下:mOffline.start(cityid);还比较靠谱,就是没详细介绍。

今天,我们主要对第二种方式进行详细介绍,然后集成到我们的已经集成了定位方向传感器的地图中,如果你还不了解:Android百度地图 SDK v3.0.0 (三) 添加覆盖物Marker与InfoWindow的使用

效果图:
为了方便,我又添加了个菜单按钮~可以看到能够对下载位置的保存,支持多个等待下载,已经取消下载等。最主要当然是,下载过后,只需要定位的流量(甚至不用)就能很好的使用咱们的地图拉~
顺便提一下:本来想搞个线程池,支持多个同时下载,这块可能很多不注意会有一些问题,但是百度地图公开出来的start(cityCode)不管我怎么尝试(尝试了多个离线地图实例都不行),每次同时都只能下载一个。
1、百度地图离线相关API介绍
a 、类 MKOfflineMap 提供地图的下载,离线地图列表的获取,已下载地图的查询等
java.util.ArrayList<MKOLUpdateElement> getAllUpdateInfo() 返回各城市离线地图更新信息
java.util.ArrayList<MKOLSearchRecord> getHotCityList() 返回热门城市列表
java.util.ArrayList<MKOLSearchRecord> getOfflineCityList() 返回支持离线地图城市列表
MKOLUpdateElement getUpdateInfo(int cityID) 返回指定城市ID离线地图更新信息
java.util.ArrayList<MKOLSearchRecord> searchCity(java.lang.String cityName) 根据城市名搜索该城市离线地图记录
boolean init(MKOfflineMapListener listener) 初使化
boolean pause(int cityID) 暂停下载指定城市ID的离线地图
boolean remove(int cityID) 删除指定城市ID的离线地图
boolean start(int cityID) 启动下载指定城市ID的离线地图
void destroy()  销毁离线地图管理模块,不用时调用 

接口 MKOfflineMapListener 离线地图事件通知接口。
void onGetOfflineMapState(int type, int state)
 
类 MKOLUpdateElement 和 类 MKOLSearchRecord
基本就是包含一些cityName , cityId, size 等等
 
API在百度的帮助文档中也很详细,下面会在代码中使用这些API。
 
2、离线地图城市信息的实体Bean
[java] view plaincopyprint?
  1. package com.zhy.zhy_baidu_ditu_demo00;  
  2.   
  3. public class OfflineMapCityBean  
  4. {  
  5.     private String cityName;  
  6.     private int cityCode;  
  7.     /** 
  8.      * 下载的进度 
  9.      */  
  10.     private int progress;  
  11.       
  12.     private Flag flag = Flag.NO_STATUS;  
  13.     /** 
  14.      * 下载的状态:无状态,暂停,正在下载 
  15.      * @author zhy 
  16.      * 
  17.      */  
  18.     public enum Flag  
  19.     {  
  20.         NO_STATUS,PAUSE,DOWNLOADING  
  21.     }  
  22.   
  23.     public Flag getFlag()  
  24.     {  
  25.         return flag;  
  26.     }  
  27.   
  28.     public void setFlag(Flag flag)  
  29.     {  
  30.         this.flag = flag;  
  31.     }  
  32.   
  33.     public OfflineMapCityBean()  
  34.     {  
  35.     }  
  36.   
  37.     public OfflineMapCityBean(String cityName, int cityCode, int progress)  
  38.     {  
  39.         this.cityName = cityName;  
  40.         this.cityCode = cityCode;  
  41.         this.progress = progress;  
  42.     }  
  43.   
  44.     public String getCityName()  
  45.     {  
  46.         return cityName;  
  47.     }  
  48.   
  49.     public void setCityName(String cityName)  
  50.     {  
  51.         this.cityName = cityName;  
  52.     }  
  53.   
  54.     public int getCityCode()  
  55.     {  
  56.         return cityCode;  
  57.     }  
  58.   
  59.     public void setCityCode(int cityCode)  
  60.     {  
  61.         this.cityCode = cityCode;  
  62.     }  
  63.   
  64.     public int getProgress()  
  65.     {  
  66.         return progress;  
  67.     }  
  68.   
  69.     public void setProgress(int progress)  
  70.     {  
  71.         this.progress = progress;  
  72.     }  
  73.   
  74. }  
package com.zhy.zhy_baidu_ditu_demo00;public class OfflineMapCityBean{	private String cityName;	private int cityCode;	/**	 * 下载的进度	 */	private int progress;		private Flag flag = Flag.NO_STATUS;	/**	 * 下载的状态:无状态,暂停,正在下载	 * @author zhy	 *	 */	public enum Flag	{		NO_STATUS,PAUSE,DOWNLOADING	}	public Flag getFlag()	{		return flag;	}	public void setFlag(Flag flag)	{		this.flag = flag;	}	public OfflineMapCityBean()	{	}	public OfflineMapCityBean(String cityName, int cityCode, int progress)	{		this.cityName = cityName;		this.cityCode = cityCode;		this.progress = progress;	}	public String getCityName()	{		return cityName;	}	public void setCityName(String cityName)	{		this.cityName = cityName;	}	public int getCityCode()	{		return cityCode;	}	public void setCityCode(int cityCode)	{		this.cityCode = cityCode;	}	public int getProgress()	{		return progress;	}	public void setProgress(int progress)	{		this.progress = progress;	}}

包含了,城市名称:用于listview上的显示,城市id:用于查询下载情况,进度:更新listview下载时的显示,标志:用户开启或者取消下载时的标志。
 
3、离线地图的使用
在Actvity启动时,首先初始化离线地图
[java] view plaincopyprint?
  1. /** 
  2.      * 初始化离线地图 
  3.      */  
  4.     private void initOfflineMap()  
  5.     {  
  6.         mOfflineMap = new MKOfflineMap();  
  7.         // 设置监听   
  8.         mOfflineMap.init(new MKOfflineMapListener()  
  9.         {  
  10.             @Override  
  11.             public void onGetOfflineMapState(int type, int state)  
  12.             {  
  13.                 switch (type)  
  14.                 {  
  15.                 case MKOfflineMap.TYPE_DOWNLOAD_UPDATE:  
  16.                     // 离线地图下载更新事件类型   
  17.                     MKOLUpdateElement update = mOfflineMap.getUpdateInfo(state);  
  18.                     Log.e(TAG, update.cityName + " ," + update.ratio);  
  19.                     for (OfflineMapCityBean bean : mDatas)  
  20.                     {  
  21.                         if (bean.getCityCode() == state)  
  22.                         {  
  23.                             bean.setProgress(update.ratio);  
  24.                             bean.setFlag(Flag.DOWNLOADING);  
  25.                             break;  
  26.                         }  
  27.                     }  
  28.                     mAdapter.notifyDataSetChanged();  
  29.                     Log.e(TAG, "TYPE_DOWNLOAD_UPDATE");  
  30.                     break;  
  31.                 case MKOfflineMap.TYPE_NEW_OFFLINE:  
  32.                     // 有新离线地图安装   
  33.                     Log.e(TAG, "TYPE_NEW_OFFLINE");  
  34.                     break;  
  35.                 case MKOfflineMap.TYPE_VER_UPDATE:  
  36.                     // 版本更新提示   
  37.                     break;  
  38.                 }  
  39.   
  40.             }  
  41.         });  
  42.     }  
/**	 * 初始化离线地图	 */	private void initOfflineMap()	{		mOfflineMap = new MKOfflineMap();		// 设置监听		mOfflineMap.init(new MKOfflineMapListener()		{			@Override			public void onGetOfflineMapState(int type, int state)			{				switch (type)				{				case MKOfflineMap.TYPE_DOWNLOAD_UPDATE:					// 离线地图下载更新事件类型					MKOLUpdateElement update = mOfflineMap.getUpdateInfo(state);					Log.e(TAG, update.cityName + " ," + update.ratio);					for (OfflineMapCityBean bean : mDatas)					{						if (bean.getCityCode() == state)						{							bean.setProgress(update.ratio);							bean.setFlag(Flag.DOWNLOADING);							break;						}					}					mAdapter.notifyDataSetChanged();					Log.e(TAG, "TYPE_DOWNLOAD_UPDATE");					break;				case MKOfflineMap.TYPE_NEW_OFFLINE:					// 有新离线地图安装					Log.e(TAG, "TYPE_NEW_OFFLINE");					break;				case MKOfflineMap.TYPE_VER_UPDATE:					// 版本更新提示					break;				}			}		});	}
设置离线地图的下载监听接口,目前我们只关注type为MKOfflineMap.TYPE_DOWNLOAD_UPDATE , 此时传入的state为cityId, 然后我们通过mOfflineMap.getUpdateInfo(state);可以获得该城市的下载数据,接下来更新我们listview的数据集,最后刷新界面。

初始化数据:
[java] view plaincopyprint?
  1. private void initData()  
  2. {  
  3.   
  4.     // 获得所有热门城市   
  5.     ArrayList<MKOLSearchRecord> offlineCityList = mOfflineMap  
  6.             .getHotCityList();  
  7.     // 手动添加了西安   
  8.     MKOLSearchRecord xian = new MKOLSearchRecord();  
  9.     xian.cityID = 233;  
  10.     xian.cityName = "西安市";  
  11.     offlineCityList.add(xian);  
  12.     // 获得所有已经下载的城市列表   
  13.     ArrayList<MKOLUpdateElement> allUpdateInfo = mOfflineMap  
  14.             .getAllUpdateInfo();  
  15.     // 设置所有数据的状态   
  16.     for (MKOLSearchRecord record : offlineCityList)  
  17.     {  
  18.         OfflineMapCityBean cityBean = new OfflineMapCityBean();  
  19.         cityBean.setCityName(record.cityName);  
  20.         cityBean.setCityCode(record.cityID);  
  21.   
  22.         if (allUpdateInfo != null)//没有任何下载记录,返回null,为啥不返回空列表~~   
  23.         {  
  24.             for (MKOLUpdateElement ele : allUpdateInfo)  
  25.             {  
  26.                 if (ele.cityID == record.cityID)  
  27.                 {  
  28.                     cityBean.setProgress(ele.ratio);  
  29.                 }  
  30.             }  
  31.   
  32.         }  
  33.         mDatas.add(cityBean);  
  34.     }  
  35.   
  36. }  
	private void initData()	{		// 获得所有热门城市		ArrayList<MKOLSearchRecord> offlineCityList = mOfflineMap				.getHotCityList();		// 手动添加了西安		MKOLSearchRecord xian = new MKOLSearchRecord();		xian.cityID = 233;		xian.cityName = "西安市";		offlineCityList.add(xian);		// 获得所有已经下载的城市列表		ArrayList<MKOLUpdateElement> allUpdateInfo = mOfflineMap				.getAllUpdateInfo();		// 设置所有数据的状态		for (MKOLSearchRecord record : offlineCityList)		{			OfflineMapCityBean cityBean = new OfflineMapCityBean();			cityBean.setCityName(record.cityName);			cityBean.setCityCode(record.cityID);			if (allUpdateInfo != null)//没有任何下载记录,返回null,为啥不返回空列表~~			{				for (MKOLUpdateElement ele : allUpdateInfo)				{					if (ele.cityID == record.cityID)					{						cityBean.setProgress(ele.ratio);					}				}			}			mDatas.add(cityBean);		}	}

进入Activity先通过mOfflineMap.getHotCityList();获得热门城市列表,不过热门里面竟然没有西安,我手动增加了一个西安。(这里我是为了方便,有兴趣的可以列出全国支持的城市);接下来mOfflineMap.getAllUpdateInfo();获得已经下载城市的数据信息;然后就行交叉对比,设置数据源数据。
 
初始化listview
[java] view plaincopyprint?
  1. private void initListView()  
  2.     {  
  3.         mListView = (ListView) findViewById(R.id.id_offline_map_lv);  
  4.         mAdapter = new MyOfflineCityBeanAdapter();  
  5.         mListView.setAdapter(mAdapter);  
  6.   
  7.         mListView.setOnItemClickListener(new OnItemClickListener()  
  8.         {  
  9.             @Override  
  10.             public void onItemClick(AdapterView<?> parent, View view,  
  11.                     int position, long id)  
  12.             {  
  13.                 int cityId = mDatas.get(position).getCityCode();  
  14.                 if (mCityCodes.contains(cityId))  
  15.                 {  
  16.                     removeTaskFromQueue(position, cityId);  
  17.                 } else  
  18.                 {  
  19.                     addToDownloadQueue(position, cityId);  
  20.                 }  
  21.   
  22.             }  
  23.         });  
  24.     }  
private void initListView()	{		mListView = (ListView) findViewById(R.id.id_offline_map_lv);		mAdapter = new MyOfflineCityBeanAdapter();		mListView.setAdapter(mAdapter);		mListView.setOnItemClickListener(new OnItemClickListener()		{			@Override			public void onItemClick(AdapterView<?> parent, View view,					int position, long id)			{				int cityId = mDatas.get(position).getCityCode();				if (mCityCodes.contains(cityId))				{					removeTaskFromQueue(position, cityId);				} else				{					addToDownloadQueue(position, cityId);				}			}		});	}

为listview的item设置点击事件,第一次点击时加入下载队列,第二次点击时取消下载。
listview的适配器
[java] view plaincopyprint?
  1. /** 
  2.      * 热门城市地图列表的Adapter 
  3.      *  
  4.      * @author zhy 
  5.      *  
  6.      */  
  7.     class MyOfflineCityBeanAdapter extends BaseAdapter  
  8.     {  
  9.   
  10.         @Override  
  11.         public boolean isEnabled(int position)  
  12.         {  
  13.             if (mDatas.get(position).getProgress() == 100)  
  14.             {  
  15.                 return false;  
  16.             }  
  17.             return super.isEnabled(position);  
  18.         }  
  19.   
  20.         @Override  
  21.         public int getCount()  
  22.         {  
  23.             return mDatas.size();  
  24.         }  
  25.   
  26.         @Override  
  27.         public Object getItem(int position)  
  28.         {  
  29.             return mDatas.get(position);  
  30.         }  
  31.   
  32.         @Override  
  33.         public long getItemId(int position)  
  34.         {  
  35.             return position;  
  36.         }  
  37.   
  38.         @Override  
  39.         public View getView(int position, View convertView, ViewGroup parent)  
  40.         {  
  41.             OfflineMapCityBean bean = mDatas.get(position);  
  42.             ViewHolder holder = null;  
  43.             if (convertView == null)  
  44.             {  
  45.                 holder = new ViewHolder();  
  46.                 convertView = mInflater.inflate(R.layout.offlinemap_item,  
  47.                         parent, false);  
  48.                 holder.cityName = (TextView) convertView  
  49.                         .findViewById(R.id.id_cityname);  
  50.                 holder.progress = (TextView) convertView  
  51.                         .findViewById(R.id.id_progress);  
  52.                 convertView.setTag(holder);  
  53.             } else  
  54.             {  
  55.                 holder = (ViewHolder) convertView.getTag();  
  56.             }  
  57.   
  58.             holder.cityName.setText(bean.getCityName());  
  59.             int progress = bean.getProgress();  
  60.             String progressMsg = "";  
  61.             // 根据进度情况,设置显示   
  62.             if (progress == 0)  
  63.             {  
  64.                 progressMsg = "未下载";  
  65.             } else if (progress == 100)  
  66.             {  
  67.                 bean.setFlag(Flag.NO_STATUS);  
  68.                 progressMsg = "已下载";  
  69.             } else  
  70.             {  
  71.                 progressMsg = progress + "%";  
  72.             }  
  73.             // 根据当前状态,设置显示   
  74.             switch (bean.getFlag())  
  75.             {  
  76.             case PAUSE:  
  77.                 progressMsg += "【等待下载】";  
  78.                 break;  
  79.             case DOWNLOADING:  
  80.                 progressMsg += "【正在下载】";  
  81.                 break;  
  82.             default:  
  83.                 break;  
  84.             }  
  85.             holder.progress.setText(progressMsg);  
  86.             return convertView;  
  87.         }  
  88.   
  89.         private class ViewHolder  
  90.         {  
  91.             TextView cityName;  
  92.             TextView progress;  
  93.   
  94.         }  
  95.     }  
/**	 * 热门城市地图列表的Adapter	 * 	 * @author zhy	 * 	 */	class MyOfflineCityBeanAdapter extends BaseAdapter	{		@Override		public boolean isEnabled(int position)		{			if (mDatas.get(position).getProgress() == 100)			{				return false;			}			return super.isEnabled(position);		}		@Override		public int getCount()		{			return mDatas.size();		}		@Override		public Object getItem(int position)		{			return mDatas.get(position);		}		@Override		public long getItemId(int position)		{			return position;		}		@Override		public View getView(int position, View convertView, ViewGroup parent)		{			OfflineMapCityBean bean = mDatas.get(position);			ViewHolder holder = null;			if (convertView == null)			{				holder = new ViewHolder();				convertView = mInflater.inflate(R.layout.offlinemap_item,						parent, false);				holder.cityName = (TextView) convertView						.findViewById(R.id.id_cityname);				holder.progress = (TextView) convertView						.findViewById(R.id.id_progress);				convertView.setTag(holder);			} else			{				holder = (ViewHolder) convertView.getTag();			}			holder.cityName.setText(bean.getCityName());			int progress = bean.getProgress();			String progressMsg = "";			// 根据进度情况,设置显示			if (progress == 0)			{				progressMsg = "未下载";			} else if (progress == 100)			{				bean.setFlag(Flag.NO_STATUS);				progressMsg = "已下载";			} else			{				progressMsg = progress + "%";			}			// 根据当前状态,设置显示			switch (bean.getFlag())			{			case PAUSE:				progressMsg += "【等待下载】";				break;			case DOWNLOADING:				progressMsg += "【正在下载】";				break;			default:				break;			}			holder.progress.setText(progressMsg);			return convertView;		}		private class ViewHolder		{			TextView cityName;			TextView progress;		}	}

适配器的代码比较简单,主要就是getView中根本bean的数据设置显示。
最后在我们主Activity增加一个菜单项,打开此Activity就完工了:
[java] view plaincopyprint?
  1. @Override  
  2. public boolean onOptionsItemSelected(MenuItem item)  
  3. {  
  4.   
  5.     switch (item.getItemId())  
  6.     {  
  7.     case R.id.id_menu_map_offline:  
  8.         Intent intent = new Intent(MainActivity.this,  
  9.                     OfflineMapActivity.class);  
  10.         startActivity(intent);  
  11.         break;  
  12.     ...  
  13.     }     
  14. }     
@Overridepublic boolean onOptionsItemSelected(MenuItem item){	switch (item.getItemId())	{	case R.id.id_menu_map_offline:		Intent intent = new Intent(MainActivity.this,					OfflineMapActivity.class);		startActivity(intent);		break;	...	}	}	

好了,关于百度地图,目前就用到这么多~~如果后期有别的需求,还会继续更新~
 
 
源码点击下载

Android 百度地图 SDK v3.0.0 (四) 引入离线地图功能