`
longgangbai
  • 浏览: 7307981 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

GIS的学习(四十一)osmdroid基于微软bing整合实现地图

阅读更多

                  在研究Osmdroid和Google整合的过程中,发现使用mapforget有一些问题,于是采用扩展图层源的方式
  扩展osmdroid的图源支持 Bing地图的 具体的实现参考BingMapTileSource类:

在osmdroid的第三方lib中,有支持微软地图的图层源的代码具体实现如下:

package com.etrip.osmdroid.tilesource.bing.imagerymetadata;

import org.json.JSONArray;
import org.json.JSONObject;

/**
 * ImageryMetaData storage. Class used to decode valid ImageryMetaData.
 *
 */
public class ImageryMetaData {

	// Useful fields found in ImageryMetaData response
	private final static String STATUS_CODE="statusCode";
	private final static String AUTH_RESULT_CODE="authenticationResultCode";
	private final static String AUTH_RESULT_CODE_VALID="ValidCredentials";
	private final static String RESOURCE_SETS="resourceSets";
	private final static String ESTIMATED_TOTAL="estimatedTotal";
	private final static String RESOURCE = "resources";

	/**
	 * Parse a JSON string containing ImageryMetaData response
	 * @param a_jsonContent	the JSON content string
	 * @return	ImageryMetaDataResource object containing parsed information
	 * @throws Exception
	 */
	static public ImageryMetaDataResource getInstanceFromJSON(final String a_jsonContent) throws Exception
	{

		if(a_jsonContent==null) {
			throw new Exception("JSON to parse is null");
		}

		/// response code should be 200 and authorization should be valid (valid BingMap key)
		final JSONObject jsonResult = new JSONObject(a_jsonContent);
		final int statusCode = jsonResult.getInt(STATUS_CODE);
		if(statusCode!=200) {
			throw new Exception("Status code = "+statusCode);
		}

		if(AUTH_RESULT_CODE_VALID.compareToIgnoreCase(jsonResult.getString(AUTH_RESULT_CODE))!=0) {
			throw new Exception("authentication result code = "+jsonResult.getString(AUTH_RESULT_CODE));
		}

		// get first valid resource information
		final JSONArray resultsSet = jsonResult.getJSONArray(RESOURCE_SETS);
		if(resultsSet==null || resultsSet.length()<1) {
			throw new Exception("No results set found in json response");
		}

		if(resultsSet.getJSONObject(0).getInt(ESTIMATED_TOTAL)<=0) {
			throw new Exception("No resource found in json response");
		}

		final JSONObject resource = resultsSet.getJSONObject(0).getJSONArray(RESOURCE).getJSONObject(0);

		return ImageryMetaDataResource.getInstanceFromJSON(resource);
	}

}

 

 

package com.etrip.osmdroid.tilesource.bing.imagerymetadata;

import org.json.JSONArray;
import org.json.JSONObject;

/**
 * ImageryMetaData storage. Class used to parse and store useful ImageryMetaData fields.
 *
 */
public class ImageryMetaDataResource {

	// Useful fields
	private final static String IMAGE_WIDTH = "imageWidth";
	private final static String IMAGE_HEIGHT = "imageHeight";
	private final static String IMAGE_URL = "imageUrl";
	private final static String IMAGE_URL_SUBDOMAINS = "imageUrlSubdomains";
	private final static String ZOOM_MIN = "ZoomMin";
	private final static String ZOOM_MAX = "ZoomMax";

	/** image height in pixels (256 as default value) **/
	public int m_imageHeight=256;
	/** image width in pixels (256 as default value) **/
	public int m_imageWidth=256;
	/** image url pattern **/
	public String m_imageUrl;
	/** list of available sub domains. Can be null. **/
	public String[] m_imageUrlSubdomains;
	/** maximum zoom level (22 as default value for BingMap) **/
	public int m_zoomMax=22;
	/** minimum zoom level (1 as default value for BingMap) **/
	public int m_zoomMin=1;
	/** whether this imagery has been initialised */
	public boolean m_isInitialised = false;

	// counter used to manage next available sub domain
	private int m_subdomainsCounter = 0;

	/**
	 * Get an instance with default values.
	 * @return
	 */
	static public ImageryMetaDataResource getDefaultInstance() {
		return new ImageryMetaDataResource();
	}

	/**
	 * Parse a JSON string containing resource field of a ImageryMetaData response
	 * @param a_jsonObject	the JSON content string
	 * @return	ImageryMetaDataResource object containing parsed information
	 * @throws Exception
	 */
	static public ImageryMetaDataResource getInstanceFromJSON(final JSONObject a_jsonObject) throws Exception
	{
		final ImageryMetaDataResource result = new ImageryMetaDataResource();

		if(a_jsonObject==null) {
			throw new Exception("JSON to parse is null");
		}

		if(a_jsonObject.has(IMAGE_HEIGHT)) {
			result.m_imageHeight = a_jsonObject.getInt(IMAGE_HEIGHT);
		}
		if(a_jsonObject.has(IMAGE_WIDTH)) {
			result.m_imageWidth = a_jsonObject.getInt(IMAGE_WIDTH);
		}
		if(a_jsonObject.has(ZOOM_MIN)) {
			result.m_zoomMin = a_jsonObject.getInt(ZOOM_MIN);
		}
		if(a_jsonObject.has(ZOOM_MAX)) {
			result.m_zoomMax = a_jsonObject.getInt(ZOOM_MAX);
		}
		result.m_imageUrl = a_jsonObject.getString(IMAGE_URL);
		if(result.m_imageUrl!=null && result.m_imageUrl.matches(".*?\\{.*?\\}.*?")) {
			result.m_imageUrl = result.m_imageUrl.replaceAll("\\{.*?\\}", "%s");
		}

		final JSONArray subdomains = a_jsonObject.getJSONArray(IMAGE_URL_SUBDOMAINS);
		if(subdomains!=null && subdomains.length()>=1)
		{
			result.m_imageUrlSubdomains = new String[subdomains.length()];
			for(int i=0;i<subdomains.length();i++)
			{
				result.m_imageUrlSubdomains[i] = subdomains.getString(i);
			}

		}

		result.m_isInitialised = true;

		return result;
	}

	/**
	 * When several subdomains are available, get subdomain pointed by internal cycle counter on subdomains and increment this counter
	 * @return	the subdomain string associated to current counter value.
	 */
	public synchronized String getSubDomain()
	{
		if(m_imageUrlSubdomains==null || m_imageUrlSubdomains.length<=0) {
			return null;
		}

		final String result = m_imageUrlSubdomains[m_subdomainsCounter];
		if(m_subdomainsCounter<m_imageUrlSubdomains.length-1) {
			m_subdomainsCounter++;
		} else {
			m_subdomainsCounter=0;
		}

		return result;
	}
}

 

 

package com.etrip.osmdroid.tilesource.bing;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Locale;

import microsoft.mappoint.TileSystem;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.osmdroid.ResourceProxy;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.tilesource.IStyledTileSource;
import org.osmdroid.tileprovider.tilesource.QuadTreeTileSource;
import org.osmdroid.tileprovider.util.StreamUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;

import com.etrip.osmdroid.tilesource.bing.imagerymetadata.ImageryMetaData;
import com.etrip.osmdroid.tilesource.bing.imagerymetadata.ImageryMetaDataResource;

/**
 * BingMap tile source used with OSMDroid<br>
 *
 * This class builds the Bing REST services url to be requested to get a tile image.<br>
 *
 * Before to be used, the static method {@link retrieveBingKey} must be invoked.<br>
 *
 * See {@link http://msdn.microsoft.com/en-us/library/ff701721.aspx} for details on the Bing API.
 */
public class BingMapTileSource extends QuadTreeTileSource implements IStyledTileSource<String> {

	private static final Logger logger = LoggerFactory.getLogger(BingMapTileSource.class);

	/** the meta data key in the manifest */
	private static final String BING_KEY = "BING_KEY";

	//Constant used for imagerySet parameter
	/** Aerial imagery mode **/
	public static final String IMAGERYSET_AERIAL = "Aerial";
	/** Aerial imagery with road overlay mode **/
	public static final String IMAGERYSET_AERIALWITHLABELS = "AerialWithLabels";
	/** Roads imagery mode **/
	public static final String IMAGERYSET_ROAD = "Road";

	// Bing Map REST services return jpeg images
	private static final String FILENAME_ENDING =".jpeg";

	// URL used to get imageryData. It is requested in order to get tiles url patterns
	private static final String BASE_URL_PATTERN = "http://dev.virtualearth.net/REST/V1/Imagery/Metadata/%s?mapVersion=v1&output=json&key=%s";

	/** Bing Map key set by user.
	 * See {@link http://msdn.microsoft.com/en-us/library/ff428642.aspx}
	 */
	private static String mBingMapKey = "";

	private String mStyle = IMAGERYSET_ROAD;

	// object storing imagery meta data
	private ImageryMetaDataResource mImageryData = ImageryMetaDataResource.getDefaultInstance();

	// local used for set BingMap REST culture parameter
	private String mLocale;
	// baseURl used for OnlineTileSourceBase override
	private String mBaseUrl;
	// tile's image resolved url pattern
	private String mUrl;

	/**
	 * Constructor.<br> <b>Warning, the static method {@link retrieveBingKey} should have been invoked once before constructor invocation</b>
	 * @param aLocale	The language used with BingMap REST service to retrieve tiles.<br> If null, the system default locale is used.
	 */
	public BingMapTileSource(final String aLocale) {
		super("BingMap", ResourceProxy.string.bing, -1, -1, -1, FILENAME_ENDING, (String)null);
		mLocale = aLocale;
		if(mLocale==null) {
			mLocale=Locale.getDefault().getLanguage()+"-"+Locale.getDefault().getCountry();
		}
	}

	/**
	 * Read the API key from the manifest.<br>
	 * This method should be invoked before class instantiation.<br>
	 */
	public static void retrieveBingKey(final Context aContext) {

		// get the key from the manifest
		final PackageManager pm = aContext.getPackageManager();
		try {
			final ApplicationInfo info = pm.getApplicationInfo(aContext.getPackageName(),
					PackageManager.GET_META_DATA);
			if (info.metaData == null) {
				logger.info("Bing key not found in manifest");
			} else {
				final String key = info.metaData.getString(BING_KEY);
				if (key == null) {
					logger.info("Bing key not found in manifest");
				} else {
					if (DEBUGMODE) {
						logger.debug("Bing key: " + key);
					}
					mBingMapKey = key.trim();
				}
			}
		} catch (final NameNotFoundException e) {
			logger.info("Bing key not found in manifest", e);
		}
	}

	public static String getBingKey() {
		return mBingMapKey;
	}

	/*-------------- overrides OnlineTileSourceBase ---------------------*/

	@Override
	protected String getBaseUrl() {
		if (!mImageryData.m_isInitialised) {
			initMetaData();
		}
		return mBaseUrl;
	}

	@Override
	public String getTileURLString(final MapTile pTile)
	{
		if (!mImageryData.m_isInitialised) {
			initMetaData();
		}
		return String.format(mUrl,quadTree(pTile));
	}

	/**
	 * get minimum zoom level
	 * @return minimum zoom level supported by Bing Map for current map view mode
	 */
	@Override
	public int getMinimumZoomLevel() {
		return mImageryData.m_zoomMin;
	}
	/**
	 * get maximum zoom level
	 * @return maximum zoom level supported by Bing Map for current map view mode
	 */
	@Override
	public int getMaximumZoomLevel() {
		return mImageryData.m_zoomMax;
	}
	/**
	 * get tile size in pixel
	 * @return tile size in pixel supported by Bing Map for current map view mode
	 */
	@Override
	public int getTileSizePixels() {
		return mImageryData.m_imageHeight;
	}

	/**
	 * get the base path used for caching purpose
	 * @return a base path built on name given as constructor parameter and current style name
	 */
	@Override
	public String pathBase() {
		return mName + mStyle;
	}

	/*--------------- IStyledTileSource --------------------*/

	@Override
	/**
	 * Set the map style.
	 * @param aStyle The map style.<br>
	 * Should be one of {@link IMAGERYSET_AERIAL}, {@link IMAGERYSET_AERIALWITHLABELS} or {@link IMAGERYSET_ROAD}
	 */
	public void setStyle(final String pStyle) {
		if(!pStyle.equals(mStyle)) {
			// flag to re-read imagery data
			synchronized (mStyle) {
				mUrl = null;
				mBaseUrl = null;
				mImageryData.m_isInitialised = false;
			}
		}
		mStyle = pStyle;
	}

	@Override
	public String getStyle() {
		return mStyle;
	}

	private ImageryMetaDataResource initMetaData() {
		if (!mImageryData.m_isInitialised) {
			synchronized (this) {
				if (!mImageryData.m_isInitialised) {
					final ImageryMetaDataResource imageryData = getMetaData();
					if (imageryData != null) {
						mImageryData = imageryData;
						TileSystem.setTileSize(getTileSizePixels());
						updateBaseUrl();
					}
				}
			}
		}
		return mImageryData;
	}

	/**
	 * Gets the imagery meta from the REST service, or null if it fails
	 */
	private ImageryMetaDataResource getMetaData()
	{
		logger.trace("getMetaData");

		final HttpClient client = new DefaultHttpClient();
		final HttpUriRequest head = new HttpGet(String.format(BASE_URL_PATTERN, mStyle, mBingMapKey));
		logger.debug("make request "+head.getURI().toString());
		try {
		    final HttpResponse response = client.execute(head);

		    final HttpEntity entity = response.getEntity();

		    if (entity == null) {
				logger.error("Cannot get response for url "+head.getURI().toString());
				return null;
			}

		    final InputStream in = entity.getContent();
		    final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
		    final BufferedOutputStream out = new BufferedOutputStream(dataStream, StreamUtils.IO_BUFFER_SIZE);
			StreamUtils.copy(in, out);
			out.flush();

			return ImageryMetaData.getInstanceFromJSON(dataStream.toString());

		} catch(final Exception e) {
			logger.error("Error getting imagery meta data", e);
		} finally {
			client.getConnectionManager().shutdown();
			logger.trace("end getMetaData");
		}
		return null;
	}

	/**
	 * Resolves url patterns to update urls with current map view mode and available sub domain.<br>
	 * When several subdomains are available, change current sub domain in a cycle manner
	 */
	protected void updateBaseUrl()
	{
		logger.trace("updateBaseUrl");
		final String subDomain = mImageryData.getSubDomain();
		final int idx = mImageryData.m_imageUrl.lastIndexOf("/");
		if(idx>0) {
			mBaseUrl = mImageryData.m_imageUrl.substring(0,idx);
		} else {
			mBaseUrl = mImageryData.m_imageUrl;
		}

		mUrl = mImageryData.m_imageUrl;
		if(subDomain!=null)
		{
			mBaseUrl = String.format(mBaseUrl, subDomain);
			mUrl = String.format(mUrl, subDomain,"%s",mLocale);
		}
		logger.debug("updated url = "+mUrl);
		logger.trace("end updateBaseUrl");
	}

}

 

 

具体使用调用如下:

package com.etrip.osmdroid;

import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapController;
import org.osmdroid.views.MapView;

import android.app.Activity;
import android.os.Bundle;

import com.etrip.osmdroid.tilesource.bing.BingMapTileSource;

/**
 * 
 *       在研究Osmdroid和Google整合的过程中,发现使用mapforget有一些问题,于是采用扩展图层源的方式
 * 扩展osmdroid的图源支持
 * Bing地图的
 * 具体的实现参考BingMapTileSource类:
 * 
 * 
 * 
 * 
 * @author longgangbai
 */
public class MainActivity extends Activity {

	private MapController mapController;
	private MapView mapView;
	/** Called when the activity is first created. */
	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mapView = (MapView) findViewById(R.id.map);
		mapView.setBuiltInZoomControls(true);
		mapController = mapView.getController();
		mapController.setZoom(15);
		GeoPoint geopoint=new GeoPoint(39.92605, 116.42616); 
		ITileSource tileSource=new BingMapTileSource(null);
		//mapView.setTileSource(new BingMapTileSource("Baidu Maps", null, 1, 20, 256, ".png", new String[]{"http://api.map.baidu.com/staticimage?"},39.92605,116.42616)); 
		mapController.setCenter(geopoint);	
	}
}

 

分享到:
评论

相关推荐

    GIS的学习(九)应用osmdroid制作android离线地图app实现

    在本篇【GIS的学习(九)应用osmdroid制作android离线地图app实现】中,我们将探讨如何使用开源库osmdroid为Android平台构建一个离线地图应用程序。osmdroid是一个强大的工具,它允许开发者集成多种地图源,包括Open...

    基于GIS的校园电子地图研究与实现

    基于GIS的校园电子地图研究与实现,主要关注如何利用GIS(地理信息系统)技术和组件开发技术,构建一个面向校外用户的动态交互式电子地图系统。该系统旨在提供信息浏览、查询服务,以及辅助用户进行决策,尤其针对...

    基于Java的gis地图应用 .zip

    总之,这个“基于Java的GIS地图应用”项目涵盖了从基础的Java编程到高级的GIS特性的多个方面,对于想深入学习Java GIS开发的程序员来说,这是一个很好的学习和实践平台。通过研究源码,你可以了解如何将这些知识应用...

    基于Javascript实现的3D GIS,支持谷歌地图+必应地图+OpenStreetMap+搜索地图+天地图+源码+界面展示

    基于Javascript实现的3D GIS,支持谷歌地图+必应地图+OpenStreetMap+搜索地图+天地图+源码+界面展示,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于...

    【GIS源码学习】基于web 电子地图的照片服务系统-SuperMap 杯第十二届全国高校GIS 大赛作品

    【GIS源码学习】基于Web电子地图的照片服务系统-SuperMap杯第十二届全国高校GIS大赛作品 在当今数字化时代,地理信息系统(GIS)已成为数据分析和决策制定的重要工具。本项目是SuperMap杯第十二届全国高校GIS大赛的...

    一种基于GIS的专题地图制作模式.pdf

    四、基于GIS的专题地图制作模式的应用前景 * 环境监测和资源管理:基于GIS的专题地图制作模式可以应用于环境监测和资源管理领域,例如土地利用、土壤污染、气候变化等。 * 城市规划和管理:基于GIS的专题地图制作...

    14基于J2EE平台的GIS地图中间件

    基于J2EE平台的GIS地图中间件的研究旨在实现地理信息系统(GIS)的分布式Web计算,从而提升WebGIS应用研究的层次。这一研究领域强调使用J2EE框架作为核心技术,结合GIS应用的需求,来设计和实现GIS地图中间件。J2EE...

    用BingMap Control 加载 google 混合地图

    首先,Bing Maps Control是由微软开发的一款地图API,它允许开发者在Web应用或Windows应用程序中集成地图功能。Bing Maps Control提供了丰富的地图服务,包括卫星视图、地形图、交通状况以及自定义图层等功能。它...

    基于arcgis平台二次开发的小型GIS系统

    本篇文章将深入探讨基于ArcGIS平台的二次开发,特别是如何利用C#语言和Visual Studio 2005创建一个小型GIS系统。 首先,我们要理解二次开发的概念。二次开发是指在已有的软件基础上,根据特定需求进行定制化的开发...

    基于GIS的最优路径算法研究与实现

    下使用C撑开发语言,设计并实现了基于ArcGISEngine平台的动态交 通最优路径算法。 本文研究的算法能够较准确地找到交通路网中两点之间的最优 路径,并能根据路网的交通状态和转弯限制等调整搜索,提供合理的 路径...

    最新基于GIS数据库的地图制图技术研究.pdf

    本研究还讨论了基于GIS数据库的地图制图技术的发展方向,包括基于GIS数据库的地图制图的自动化和智能化、基于GIS数据库的地图制图的科学化和高效化、基于GIS数据库的地图制图的信息化和可视化等。 本研究旨在讨论...

    论文研究-基于J2EE平台的GIS地图中间件.pdf

    J2EE平台和GIS地图中间件的研究是当今信息技术领域的一个重要课题,它涉及到如何在分布式计算环境中实现高效的地理信息系统(GIS)应用。这篇论文详细探讨了如何在J2EE框架的基础上,结合商业中间件的核心与GIS应用...

    基于Python的离线Google地图操作实现

    同时,本文也提供了一种基于Python的离线Google地图操作实现方法,可以为GIS系统开发提供便利。 关键词:Google地图;离线;地图瓦片;地图操作 一、引言 互联网技术和地图测绘技术的发展推动了一系列与地图相关...

    看漫画学习GIS(gis学习漫画版)

    《看漫画学习GIS》是一本独特且创新的学习资料,它通过漫画的形式,使GIS学习变得更加生动有趣,尤其适合初学者和对GIS感兴趣的人群。 GIS的历史可以追溯到20世纪60年代,当时的主要应用集中在土地规划和资源管理...

    gis数据地图模块.rar_Delphi GIS_delphi-gis_gis_gis 地图_地图

    "gis数据地图模块"可能是一个包含源代码、库文件或其他资源的文件,用于实现GIS地图功能。 综上所述,这个压缩包可能提供了使用Delphi开发GIS应用的示例代码或库,帮助开发者理解和构建GIS地图模块。开发者可以通过...

    GIS.rar_gis_gis管网_百度地图_管网图形_管网地图

    GIS(Geographic Information System,地理信息系统)是一种集成了计算机硬件、软件和地理数据的系统,用于获取、...通过研究这个案例,可以了解如何整合不同的GIS技术和地图服务,实现特定的地理信息展示和管理需求。

    基于GIS控件的电子地图制作

    ### 基于GIS控件的电子地图制作 #### 一、引言 电子地图作为矢量化、数字化的地图,是在计算机硬件与软件的支持下,对有关地理分布数据进行信息处理的管理系统。随着计算机技术的发展,电子地图应运而生,极大地...

    vue+三维GIS地图

    此实例为vue版本三维GIS地图,其中包含底图切换、图层控制、图上量算、空间分析、坐标定位、图上标绘、地图打印等功能

Global site tag (gtag.js) - Google Analytics