zoukankan      html  css  js  c++  java
  • 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
    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启动时,首先初始化离线地图
    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的数据集,最后刷新界面。

    初始化数据:
    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
    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的适配器
    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就完工了:
    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. }     
    @Override
    public 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;
    	...
    	}	
    }	

    好了,关于百度地图,目前就用到这么多~~如果后期有别的需求,还会继续更新~
     
     
  • 相关阅读:
    【转载】兼容php5,php7的cURL文件上传示例
    解决CURL 请求本地超时
    PHP 二维数组根据某个字段排序
    JS监听输入框值变化兼容 onpropertychange、oninput
    PHP AES的加密解密-----【弃用】
    PHP 开发API接口签名验证
    Python 逐行修改txt每条记录的内容
    Python 修改电脑DNS
    带小数点时间分钟转换
    Python 判断字符串是否为数字
  • 原文地址:https://www.cnblogs.com/qingchen1984/p/4071865.html
Copyright © 2011-2022 走看看