电信Android手机结合Google Maps Geolocation API定位

Google Maps Geolocation API的官方文档在这里:https://developers.google.com/maps/documentation/business/geolocation/?hl=zh-CN

我们可以申请测试key,链接在此:https://code.google.com/apis/console/?noredirect,免费配额是100次API请求/每天,申请前必须新建一个project,并且完善信用卡支付信息。

我一开始没有填写信用卡,导致尝试了各种请求都是失败,报错为:Geolocation API Daily Limit Exceeded,后来重新生成了API key再请求就OK了。

一般而言,服务器返回403 Forbidden表示key有问题或者referer不在允许的列表里;400 Bad Request表示请求的json参数有问题;404 Not Found可能表示要查找的经纬度信息不存在,应该是请求的json参数中的数值有问题。

根据Geolocation API的要求,对于电信CDMA2000制式的手机,查询经纬度主要需要如下信息:

MobileCountryCode(MCC)+MobileNetworkCode(MNC)+cellId+locationAreaCode

MobileCountryCode和MobileNetworkCode的说明在这里:http://en.wikipedia.org/wiki/List_of_mobile_country_codes

cellId在CDMA2000中代表Base Station ID (BID)

locationAreaCode在CDMA2000中代表Network ID (NID)

radioType在CDMA2000中取值cdma

API请求的参数为json格式,示例如下:

{
 "homeMobileCountryCode": 460,
 "homeMobileNetworkCode": 14174,
 "radioType": "cdma",
 "cellTowers": [
  {
   "cellId": 585,
   "locationAreaCode": 10,
   "mobileCountryCode": 460,
   "mobileNetworkCode": 14174
  }
 ]
}

官方示例中使用cURL测试接口和key,命令为:

curl -d @georeqct.json -H "Content-Type: application/json" -i "https://www.googleapis.com/geolocation/v1/geolocate?key=yourkey"

返回数据也是json格式,示例如下:

{
 "location": {
  "lat": 32.1105539,
  "lng": 118.92446569999998
 },
 "accuracy": 1604.0
}

上面的返回值分别代表经纬度以及精确度。

下面贴一下Android中获取请求参数的代码:

package org.bigroom.celltowerinfo;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends Activity {
	
	static final private int MENU_Exit = Menu.FIRST;
	static final private int MENU_CellIdInfo = Menu.FIRST+1;
	TelephonyManager tm;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	menu.add(0, MENU_Exit, 0, "Exit");
    	menu.add(0, MENU_CellIdInfo, 1, "MENU_CellIdInfo");
        return true;
    }
    
    @Override 
    public boolean onOptionsItemSelected(MenuItem item) 
    {
    	switch(item.getItemId()) 
    	{
    		case (MENU_Exit):
    			MainActivity.this.finish();
				android.os.Process.killProcess(android.os.Process.myPid());
				System.exit(0);
    			break;
    		case (MENU_CellIdInfo):
    			CdmaCellLocation ccl = (CdmaCellLocation) tm.getCellLocation();
    			int BSId=ccl.getBaseStationId();
    			int BSSLat = ccl.getBaseStationLatitude();
    			int BSSLon = ccl.getBaseStationLongitude();
    			int Nid=ccl.getNetworkId();
    			int Sid=ccl.getSystemId();
	            int mcc = Integer.valueOf(tm.getNetworkOperator().substring(0, 3));
	            int mnc = Integer.valueOf(tm.getNetworkOperator().substring(3, 5));
	            String CellIdInfo="BSId:"+String.valueOf(BSId)+" "+"BSSLat:"+String.valueOf(BSSLat)+" "+"BSSLon:"+String.valueOf(BSSLon)+" "+"Nid:"+String.valueOf(Nid)+" "+"Sid:"+String.valueOf(Sid)+" "+"mcc:"+String.valueOf(mcc)+" "+"mnc:"+String.valueOf(mnc);
	            Log.d("debug", CellIdInfo);
	            Toast.makeText(getApplicationContext(), CellIdInfo, Toast.LENGTH_LONG).show();
    			break;
    	}
    	return super.onOptionsItemSelected(item);
	} 
}

要注意在AndroidManifest.xml中添加权限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

对于CDMA网络,其实可以直接从SDK中获取经纬度。。。

使用我的手机获取到的数据为:

BSId:585 BSSLat:462444 BSSLon:1712572 Nid:10 Sid:14174 mcc:460 mnc:3

这里的经纬度值的定义在这里:

Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0. (http://www.3gpp2.org/public_html/specs/C.S0005-A_v6.0.pdf) It is represented in units of 0.25 seconds and ranges from -1296000 to 1296000, both values inclusive (corresponding to a range of -90 to +90 degrees). 
Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0. (http://www.3gpp2.org/public_html/specs/C.S0005-A_v6.0.pdf) It is represented in units of 0.25 seconds and ranges from -2592000 to 2592000, both values inclusive (corresponding to a range of -180 to +180 degrees).

根据换算关系可以算出SDK中获取的Longitude为1712572/14400=118.93,Latitude为462444/14400=32.11,通过查找地图发现这一对数值能够正确标识我的实际位置。

回到Geolocation API,除了新建json文本使用cURL模拟Server提交测试之外,我们还可以使用Python模拟Brower测试,代码为:

import json
import urllib2
cellTowersData={'cellId':585,'locationAreaCode':10,'mobileCountryCode':460,'mobileNetworkCode':14174}
geoLocationRequestData = {'radioType':'cdma','cellTowers':[cellTowersData]}
geoLocationRequestJsonData = json.dumps(geoLocationRequestData)
geoLocationRequestUrl = "https://www.googleapis.com/geolocation/v1/geolocate?key=yourkey"
geoLocationRequest = urllib2.Request(geoLocationRequestUrl, geoLocationRequestJsonData, {'Content-Type': 'application/json','Referer': '*.chenxupro.com/*'})
try:
	geoLocationResponse = urllib2.urlopen(geoLocationRequest)
	geoLocationResponseContent = geoLocationResponse.read()
	print geoLocationResponseContent
	geoLocationResponse.close()
except (urllib2.HTTPError,),e:
	print "Load Error,%s" % e

测试结果截图如下:



上图中获取的Lat值和Lon值和SDK里获取的值还是比较接近的。

Google还提供了丰富的Report功能,便于开发者查看API请求情况,示例如下:


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值