通过Web页面获取基站位置(Web端,源码下载)
源代码地址:https://files.cnblogs.com/psunny/SafetyNetMobileHttpService.rar
我在使用Windows Mobile向http://www.google.com/loc/json请求基站信息时,发现第一次发送基站信息能够获取到一个经纬度,第二次却失败,直接导致异常退出应用程序。由于基站信息只能在真机上才能获取,无法进行调试,我就以一个中间web页面来向手机发送位置信息,再者拼接Json和解析的Json都放在web上进行处理,也减少Windows Mobile应用程序的负担,Windows Mobile只单纯的负责接收一个经纬度字符串。
1. 具体思路
首先要清楚一点的是,每一个基站都能够通过请求http://www.google.com/loc/json获取到一个经纬度。如果用户能够在短时间内获取到较多的基站信息,比如4个或5个,可以通过这几个基站的经纬度计算出比较准确的用户位置。
举个例子,比如我在WM上取到4个基站信息:
50554,9513,460,1
50325,9513,460,1
50584,9513,460,1
50041,9513,460,1
每一行的4个数值分别对应:CID, LAC, MCC, MNC
![]() |
---|
CID——CellID,表示基站号 MCC——Mobile Country Code,表示国家编号,中国是460 MNC——Mobile Network Code,表示移动网络编号,移动是0,联通是1 更详细的MCC, MNC信息可以查看:http://en.wikipedia.org/wiki/Mobile_Network_Code |
然后向Google发送基站信息是通过JSON串以Post的形式发送到http://www.google.com/loc/json,然后它会返回一个包含经纬度信息的JSON串。
RequestJson范例
{
"version": "1.1.0",
"host": "maps.google.com",
"cell_towers": [
{
"cell_id": 42,
"location_area_code": 415,
"mobile_country_code": 310,
"mobile_network_code": 410,
"age": 0,
"signal_strength": -60,
"timing_advance": 5555
},
{
"cell_id": 88,
"location_area_code": 415,
"mobile_country_code": 310,
"mobile_network_code": 580,
"age": 0,
"signal_strength": -70,
"timing_advance": 7777
}
],
"wifi_towers": [
{
"mac_address": "01-23-45-67-89-ab",
"signal_strength": 8,
"age": 0
},
{
"mac_address": "01-23-45-67-89-ac",
"signal_strength": 4,
"age": 0
}
]
}
然后从google那边返回来的位置信息如下:
ResponseJson样例
{
"location": {
"latitude": 51.0,
"longitude": -0.1,
"altitude": 30.1,
"accuracy": 1200.4,
"altitude_accuracy": 10.6,
"address": {
"street_number": "100",
"street": "Amphibian Walkway",
"postal_code": "94043",
"city": "Mountain View",
"county": "Mountain View County",
"region": "California",
"country": "United States of America",
"country_code": "US"
}
},
"access_token": "2:k7j3G6LaL6u_lafw:4iXOeOpTh1glSXe"
}
![]() |
---|
即使只发送一个基站信息,也能够获取到一个经纬度。以上的RequestJson和ResponseJson只是样例,在实际Windows Mobile运用中,有可能取不到timing_adavance和singal_strength这两个参数,结合这两个参数定位会更准确一些。在我的代码例子中,我只取了CID, LAC, MCC, MNC参数。 关于JSON串中的属性各代表什么意思,详细请看:http://code.google.com/intl/zh-CN/apis/gears/geolocation_network_protocol.html |
从上面的两端代码中我们可以大致了解到如何向Google发送基站请求,获取经纬度,下面我就以简单的代码来实现获取经纬度的方法。其实了解了上面的代码后,我们主要的工作就是拼接RequestJson串和解析
ResponseJson串,解析Json串我使用的是JSON.NET。
2.实现
using System;
/// <summary>
/// CellInfocs 的摘要说明
/// </summary>
public class CellInfo
{
public string cid;
public string lac;
public string mcc;
public string mnc;
public string CID
{
get { return cid; }
set { cid = value; }
}
public string LAC
{
get { return lac; }
set { lac = value; }
}
public string MCC
{
get { return mcc; }
set { mcc = value; }
}
public string MNC
{
get { return mnc; }
set { mnc = value; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using Newtonsoft.Json.Linq;
/// <summary>
/// LocationService 的摘要说明
/// </summary>
public class LocationService
{
public static string ErrorMessage;
public LocationService(string postData)
{
GetLocationInfomation(postData);
}
/// <summary>
/// 返回经纬度信息
/// 格式如下:
/// 22.506421,113.918245|22.497636,113.912647|22.496063,113.91121
/// </summary>
/// <param name="postData"></param>
/// <returns></returns>
public string GetLocationInfomation(string postData)
{
List<CellInfo> list = GetCellInfos(postData);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.Count; i++)
{
CellInfo info = list[i];
//基本步骤
//1. 生成发往google的json串
//2. 接收google返回的json串
//3. 解析json串,只取得经纬度
//4. 拼接经纬度
string json = GenerateRequestJson(info);
string content = GetResponseJson(json);
string latLon = ParseResponseJson(content);
sb.Append(latLon);
sb.Append("|");
}
return sb.ToString().Substring(0, sb.Length - 1);
//return sb.ToString();
}
/// <summary>
/// 接收从手机端发送过来的数据
/// '|'分割对象,','分割属性
/// </summary>
/// <param name="postData"></param>
/// <returns></returns>
private List<CellInfo> GetCellInfos(string postData)
{
string[] strInfos = postData.Split('|');
List<CellInfo> list = new List<CellInfo>();
for (int i = 0; i < strInfos.Length; i++)
{
string[] properties = strInfos[i].Split(',');
CellInfo info = new CellInfo();
info.CID = properties[0];
info.LAC = properties[1];
info.MCC = properties[2];
info.MNC = properties[3];
list.Add(info);
}
return list;
}
/// <summary>
/// 发送一个基站信息,并返回一个位置信息
/// 位置信息是以json串的形式存在
/// 需要对json串进行解析
/// </summary>
/// <param name="requestJson"></param>
private string GetResponseJson(string requestJson)
{
string responseJson = string.Empty;
try
{
ServicePointManager.Expect100Continue = false;
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] data = encoding.GetBytes(requestJson);
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(@"http://www.google.com/loc/json");
myRequest.Method = "POST";
myRequest.ContentType = "application/requestJson";
myRequest.ContentLength = data.Length;
Stream newStream = myRequest.GetRequestStream();
// Send the data.
newStream.Write(data, 0, data.Length);
newStream.Close();
// Get response JSON string
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
StreamReader reader = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.Default);
responseJson = reader.ReadToEnd();
}
catch (Exception ex)
{
ErrorMessage = ex.Message;
}
return responseJson;
}
/// <summary>
/// 解析从google Response的JSON串,获取经纬度
/// </summary>
/// <param name="responseJson"></param>
/// <returns></returns>
private string ParseResponseJson(string responseJson)
{
StringBuilder latLon = new StringBuilder();
JObject obj = JObject.Parse(responseJson);
string lat = obj["location"]["latitude"].ToString();
string lon = obj["location"]["longitude"].ToString();
latLon.Append(lat);
latLon.Append(",");
latLon.Append(lon);
return latLon.ToString();
}
/// <summary>
/// 生成发往http://www.google.com/loc/json的json串
/// 仅仅只有一个基站
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
private string GenerateRequestJson(CellInfo info)
{
string json = "";
json += "{";
json += "\"version\":\"1.1.0\"" + ",";
json += "\"host\":\"maps.google.com\"" + ",";
json += "\"cell_towers\":[";
json += "{";
json += "\"cell_id\":" + info.CID + ",";
json += "\"location_area_code\":" + info.LAC + ",";
json += "\"mobile_country_code\":" + info.MCC + ",";
json += "\"mobile_network_code\":" + info.MNC;
json += "}";
json += "],";
json += "\"wifi_towers\": [{}]";
json += "}";
return json;
}
}
中间的web页面:Default.aspx(发送请求时,就请求这个页面)
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
using System;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string postData = Request.Form["POST_DATA"];
ResponseLocation(postData);
}
/// <summary>
/// 向手机端返回位置信息
/// </summary>
/// <param name="postData"></param>
public void ResponseLocation(string postData)
{
LocationService service = new LocationService(postData);
string location = service.GetLocationInfomation(postData);
Response.Write(location);
}
}
测试页面:index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Index Page</title>
</head>
<body>
<form id="form1" method="post" action="Default.aspx">
<input name="POST_DATA"
value=" 50554,9513,460,1|50325,9513,460,1|50584,9513,460,1|50041,9513,460,1"/>
<input type="submit"/>
</form>
</body>
</html>
![](https://img2024.cnblogs.com/blog/35695/202408/35695-20240826070647288-243310440.jpg)