如何在Windows store app中使用百度地图
目前提供Windows store app API接口的地图只有两个,自带的Bing地图和高德地图。Bing地图对国外的支持很好,可是对国内的支持就不那么给力了,如果是要写一个针对国内的应用,这是显然不行的。而高德地图虽然对国内支持的很好,他的API却一直没有更新,以至于现在已经通不过WACK(Windows app certificate kit)测试了,作为一个需要能够提交到app store的应用,这条路也走不通。所以要想在Windows store app项目中使用地图,就只有另辟蹊径,采用曲线救国的办法了。
首先我查阅了国内主流的地图接口,感觉百度地图的接口还是做的比较好的,地图数据也足够丰富,那么就选定它了。
由于目前百度地图还没有针对Windows Store App的SDK,于是我就想到使用WebView控件,结合百度地图JavaScript API来使用地图。在Window Store App中,我们可以使用WebView控件在应用程序内加载地图。同时调用百度地图的JavaScript API完成与地图的互操作。
首先介绍一下我的开发环境:
操作系统: Windows 8.1 RTM
开发工具: Microsoft Visual Studio 2013(RC)
API: 百度地图JavaScript API
接下来是具体步骤:
1. 创建百度账户,并申请Key
第一步当然是获得Baidu地图的开发许可。从百度网站可知,Baidu地图API免费对外开放,对于非商业应用可以直接使用,对于商业应用需要得到Baidu的协议许可。自v1.5版本起,需先申请密钥才可使用,接口(除发送短信功能外)无使用次数限制。你可以通过登录https://developer.baidu.com/map/jshome.htm,
按照提示申请开发者密钥,当然,你首先需要有一个百度账号,百度会让你首先注册为开发者账号,然后再创建密钥。
2. 创建Window store应用,并在应用中加载百度地图
第二步就是创建你的Windows store 应用,然后在您的应用中加入WebView控件:
<WebView x:Name="MyWebview" Source="ms-appx-web:///MapDemo.html/>
WebView加载的页面是个html网页,该网页的代码你可以参考百度地图开发者网站的示例:
https://developer.baidu.com/map/jsdemo.htm
下面就是一个最简单的网页示例代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=您的密钥"></script>
<title>百度地图的Hello, World</title>
<style type="text/css">
body, html, #allmap {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
}
</style>
</head>
<body>
<div id="allmap"></div>
</body>
</html>
<script type="text/javascript">
// 百度地图API功能
var map = new BMap.Map("allmap"); // 创建Map实例
var point = new BMap.Point(116.404, 39.915); // 创建点坐标
map.centerAndZoom(point, 15); // 初始化地图,设置中心点坐标和地图级别。
map.enableScrollWheelZoom(); //启用滚轮放大缩小
</script>
这里你需要将“您的密钥”换成第一步获得的实际的开发者密钥。经过简单的两步,您的Windows Store应用就可以加载地图了。
3. 在地图中进行浏览器定位
光能够加载地图是远远不够的,通常我们都希望地图加载的时候能够根据当前的位置进行定位。IE本身提供了浏览器定位的功能,不幸的是Webview不支持这个功能,也就是说我们没有办法在html网页中得到地理位置的信息。当时,我们知道Windows runtime提供的Geolocator API可以得到地理位置信息。那么我们就可以通过WebView的InvokeScriptAsync方法来将定位信息传给html网页。
首先,在在XAML文件中增加对页面加载完成事件的消息响应:
<WebView x:Name="MyWebview" Source="ms-appx-web:///html/MapDemo.html" NavigationCompleted="MyWebview_NavigationCompleted"/>
然后在响应的消息响应函数中实现定位:
private async void MyWebview_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
Geolocator geolocator = new Geolocator();
Geoposition pos = await geolocator.GetGeopositionAsync();
Geopoint poi = pos.Coordinate.Point;
var lat = poi.Position.Latitude; // 纬度
var lon = poi.Position.Longitude; // 经度
…
}
最后,我们需要将地理位置信息传递到html代码中,这可以使用InvokeScriptAsync方法调用html中得script函数来实现:
private async void MyWebview_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
Geolocator geolocator = new Geolocator();
Geoposition pos = await geolocator.GetGeopositionAsync();
Geopoint poi = pos.Coordinate.Point;
var lat = poi.Position.Latitude; // 纬度
var lon = poi.Position.Longitude; // 经度
…
//调用并传递地理位置信息给html中的getloc函数
String[] loc = { lon.ToString(),lat.ToString() };
await MyWebview.InvokeScriptAsync("getloc", loc);
}
MapDemo.html中定义getloc(x)函数如下:
function getloc(lon,lat)
{
var point = new BMap.Point(lon, lat); //根据经纬度新建一个point
map.centerAndZoom(point, 15); //缩放视图至定位得到的城市
}
这样,我们就可以根据当前的地理位置信息在地图中进行定位了。同样的方法,我们也可以实现对地图的搜索功能:
private async void Button_Click(object sender, RoutedEventArgs e)
{
String[] str = { tbxSearch.Text };
await MyWebView.InvokeScriptAsync("search", str);
}
function search(str) {
map.clearOverlays();
var options = {
onSearchComplete: function (results) {
// 判断状态是否正确
if (local.getStatus() == BMAP_STATUS_SUCCESS) {
var defnotify=null; //搜索完成返回所有兴趣点的地址
if (results.getCurrentNumPois() != 0) {
for (var i = 0; i < results.getCurrentNumPois() ; i++)
{
//在地图上添加标注
var marker = addMarker(results.getPoi(i).point, i);
}
}
}
}
};
var local = new BMap.LocalSearch(map, options);
local.search(str);
}
function addMarker(point, index) {
var myIcon = new BMap.Icon("https://api.map.baidu.com/img/markers.png",new BMap.Size(23, 25), {
offset: new BMap.Size(10, 25),
imageOffset: new BMap.Size(0, 0 - index * 25)
});
var marker = new BMap.Marker(point, { icon: myIcon });
map.addOverlay(marker);
return marker;
}
4. 将地图中获得的地图信息传递给应用
当然,如果仅仅是从应用传递数据给地图是远远不够的,我们还需要随时能够拿到地图上的数据。这就需要依靠ScriptNotify事件了。ScriptNotify能够使 HTML 页面在页面调用 window.external.notify的时候激发此事件并传递字符串到 XAML 应用程序。在这里,如果应用程序想拿到搜索的结果,则需要这样实现:
首先在XAML和cs文件中增加一个ScriptNotify的消息触发函数,在这个事件响应函数中显示所有得到的搜索结果:
<WebView x:Name="MyWebview" Source="ms-appx-web:///html/MapPage.html" ScriptNotify="MyWebview_ScriptNotify" NavigationCompleted="MyWebview_NavigationCompleted"/>
private void MyWebView_ScriptNotify(object sender, NotifyEventArgs e)
{
if (e.Value != "")
{
string[] splits = e.Value.Split('|');
for (int i = 0; i < splits.Length-1;i++)
lbxResult.Items.Add(splits[i]); //添加地址
}
}
}
然后改写script中的search函数,让它能够触发ScriptNotify消息并返回想要的值,这里我们返回搜索得到的所有地址:
function search(str) {
map.clearOverlays();
var options = {
onSearchComplete: function (results) {
// 判断状态是否正确
var defnotify="";
if (local.getStatus() == BMAP_STATUS_SUCCESS) {
if (results.getCurrentNumPois() != 0) {
for (var i = 0; i < results.getCurrentNumPois() ; i++)
{
//添加标注
var marker = addMarker(results.getPoi(i).point, i);
defnotify += results.getPoi(i).title + "-" +
results.getPoi(i).address +"|";
}
}
window.external.notify(defnotify);
}
}
};
var local = new BMap.LocalSearch(map, options);
local.search(str);
}
最终的运行效果如下图所示:
这样,我们就在Windows Store 应用中实现了地图的定位搜索功能,我这里附上相应的示例代码供大家参考。
我这里只是完成了一个基本的功能,通过灵活使用InvokeScriptAsync和ScriptNotify,你可以不断完善,实现你想要的各种功能。我这里仅作为抛砖引玉,如果各位有其他更好的做法,欢迎与我一起探讨。
Comments
Anonymous
September 30, 2013
Thanks for the sharing! The content is very useful and I will follow the detailed steps to try my own app.Anonymous
September 30, 2013
Second floor! UpAnonymous
October 02, 2013
实用,好文!Anonymous
October 02, 2013
Thanks for the valuable sharing.Anonymous
October 07, 2013
很有用Anonymous
October 08, 2013
很实用的文章,step by step 并配有sample,希望更多好文!Anonymous
October 08, 2013
A good choice for map application. Thanks for sharing!Anonymous
October 08, 2013
好文!Anonymous
October 08, 2013
Very useful! Thanks for sharing.Anonymous
October 08, 2013
Thanks for sharing~It's very useful for application developers.