在googleAPI里提供了基站信息的获取类TelephonyManager,通过其方法getCellLocation得到CellLocation即可获取到基站相关信息
但CellLocation是个抽象类,所以在具体使用时需要判断接入的网络制式来用其子类CdmaCellLocation或GsmCellLocation 来强转
CdmaCellLocation对应CDMA网,GsmCellLocation对应GSM网
三大网络运营商的网络制式对应如下:
移动2G 网 --> GSM
移动3G 网 --> TD-SCDMA
电信2G 网 --> CDMA
电信3G 网 --> CDMA2000
联通2G 网 --> GSM
联通3G 网 --> WCDMA
由此可见移动,联通2G 网都可使用GsmCellLocation
电信2G,3G网则使用CdmaCellLocation
那么移动3G和联通3G又当如何
其实经本人亲测,移动3G网也可使用GsmCellLocation,听说是TD-SCDMA衍生于GSM,具体原因咱也不用纠结了,反正能用就是了
而联通的WCDMA据说也可使用GsmCellLocation,那姑且就是这样吧,有条件的童鞋试一试吧。
对于网络制式的判断调用TelephonyManager.getNetworkType()可有多种情况,如下:
NETWORK_TYPE_UNKNOWN
NETWORK_TYPE_GPRS
NETWORK_TYPE_EDGE
NETWORK_TYPE_UMTS
NETWORK_TYPE_HSDPA
NETWORK_TYPE_HSUPA
NETWORK_TYPE_HSPA
NETWORK_TYPE_CDMA
NETWORK_TYPE_EVDO_0
NETWORK_TYPE_EVDO_A
NETWORK_TYPE_EVDO_B
NETWORK_TYPE_1xRTT
NETWORK_TYPE_IDEN
NETWORK_TYPE_LTE
NETWORK_TYPE_EHRPD
通过对网络类型判断后获取对应基站信息代码片段如下:
- public
static <CellIDInfo>ArrayList getCellIDInfo(Context context) throws Exception{ -
-
TelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); -
-
ArrayList CellID = newArrayList <CellIDInfo>(); -
CellIDInfo = newCellIDInfo(); -
-
int = manager.getNetworkType(); -
Log.d(TAG, "getCellIDInfo-- = " + type); -
int = manager.getPhoneType(); -
Log.d(TAG, "getCellIDInfo-- = " + phoneType); -
-
if ( == TelephonyManager.NETWORK_TYPE_GPRS // GSM网 -
|| == TelephonyManager.NETWORK_TYPE_EDGE -
|| == TelephonyManager.NETWORK_TYPE_HSDPA) -
{ -
GsmCellLocation = ((GsmCellLocation) manager.getCellLocation()); -
if ( == null) -
{ -
Log.e(TAG, "GsmCellLocation is null!!!"); -
return null; -
} -
-
-
int = gsm.getLac(); -
String = manager.getNetworkOperator().substring(0,3); -
String = manager.getNetworkOperator().substring(3,5); -
int = gsm.getCid(); -
-
= gsm.getCid(); -
= mcc; -
= mnc; -
= lac; -
-
= "gsm"; -
-
CellID.add(currentCell); -
-
// 获得邻近基站信息 -
List list = manager.getNeighboringCellInfo(); -
int = list.size(); -
for (int = 0;i <size; i++) { -
-
CellIDInfo = newCellIDInfo(); -
= list.get(i).getCid(); -
= mcc; -
= mnc; -
= lac; -
-
CellID.add(info); -
} -
-
}else if ( == TelephonyManager.NETWORK_TYPE_CDMA // 电信cdma网 -
|| == TelephonyManager.NETWORK_TYPE_1xRTT -
|| == TelephonyManager.NETWORK_TYPE_EVDO_0 -
|| == TelephonyManager.NETWORK_TYPE_EVDO_A) -
{ -
-
CdmaCellLocation = (CdmaCellLocation) manager.getCellLocation(); -
if ( == null) -
{ -
Log.e(TAG, "CdmaCellLocation is null!!!"); -
return null; -
} -
-
int = cdma.getNetworkId(); -
String = manager.getNetworkOperator().substring(0,3); -
String = String.valueOf(cdma.getSystemId()); -
int = cdma.getBaseStationId(); -
-
= cid; -
= mcc; -
= mnc; -
= lac; -
-
= "cdma"; -
-
CellID.add(currentCell); -
-
// 获得邻近基站信息 -
List list = manager.getNeighboringCellInfo(); -
int = list.size(); -
for (int = 0;i <size; i++) { -
-
CellIDInfo = newCellIDInfo(); -
= list.get(i).getCid(); -
= mcc; -
= mnc; -
= lac; -
-
CellID.add(info); -
} -
} -
-
return CellID; -
-
}
从GOOGLE的API文档里总共有14钟网络类型,这里只罗列了其中7种,其他的主要是本人也不太清楚其对应到的网络制式是怎样的
所以部分童鞋的SIM卡网络制式不在这7种之内,自己根据实际情况看看它是归类于GSM还是CDMA在添进去就可以了
网络上多数教程是讲GSM网获取基站的,而忽略了C网的基站
这里我们可以比较一下GSM 和 CDMA 在获取基站信息时的不同之处
GSM:
int lac = gsm.getLac();
String mcc = manager.getNetworkOperator().substring(0, 3);
String mnc = manager.getNetworkOperator().substring(3, 5);
int cid = gsm.getCid();
CDMA:
int lac = cdma.getNetworkId();
String mcc = manager.getNetworkOperator().substring(0, 3);
String mnc = String.valueOf(cdma.getSystemId());
int cid = cdma.getBaseStationId();
在获取区域码LAC时GSM使用的是GsmCellLocation.getLac(),CDMA则用CdmaCellLocation.getNetworkId()来代替
在获取基站ID时GSM使用的是GsmCellLocation.getCid(),CDMA则用CdmaCellLocation.getBaseStationId()来代替
前面获取到的都是单个基站的信息,后面再获取周围邻近基站信息以辅助通过基站定位的精准性
TelephonyManager.getNeighboringCellInfo(),将其也放入基站信息LIST表中
最后通过google提供的gear接口获取经纬度,代码如下:
- public
static <CellIDInfo>Location callGear(List cellID) { -
if ( == null || cellID.size() == 0) -
return null; -
-
DefaultHttpClient = newDefaultHttpClient(); -
HttpPost = newHttpPost("http://www.google.com/loc/json"); -
JSONObject = newJSONObject(); -
-
try { -
holder.put("version", "1.1.0"); -
holder.put("host", "maps.google.com"); -
holder.put("home_mobile_country_code", cellID.get(0).mobileCountryCode); -
holder.put("home_mobile_network_code", cellID.get(0).mobileNetworkCode); -
holder.put("radio_type", cellID.get(0).radioType); -
holder.put("request_address", true); -
if ("460".equals(cellID.get(0).mobileCountryCode)) -
holder.put("address_language", "zh_CN"); -
else -
holder.put("address_language", "en_US"); -
-
JSONObject data,current_data; -
-
JSONArray = newJSONArray(); -
-
= newJSONObject(); -
current_data.put("cell_id", cellID.get(0).cellId); -
current_data.put("location_area_code", cellID.get(0).locationAreaCode); -
current_data.put("mobile_country_code", cellID.get(0).mobileCountryCode); -
current_data.put("mobile_network_code", cellID.get(0).mobileNetworkCode); -
current_data.put("age", 0); -
current_data.put("signal_strength", -60); -
current_data.put("timing_advance", 5555); -
array.put(current_data); -
-
if (cellID.size() 2) { -
for (int = 1;i <cellID.size(); i++) { -
= newJSONObject(); -
data.put("cell_id", cellID.get(i).cellId); -
data.put("location_area_code", cellID.get(i).locationAreaCode); -
data.put("mobile_country_code", cellID.get(i).mobileCountryCode); -
data.put("mobile_network_code", cellID.get(i).mobileNetworkCode); -
data.put("age", 0); -
array.put(data); -
} -
} -
-
-
-
-
holder.put("cell_towers", array); -
-
StringEntity = newStringEntity(holder.toString()); -
Log.e("Location send", holder.toString()); -
post.setEntity(se); -
HttpResponse = client.execute(post); -
-
HttpEntity = resp.getEntity(); -
-
BufferedReader = newBufferedReader( -
new InputStreamReader(entity.getContent())); -
StringBuffer = newStringBuffer(); -
String = br.readLine(); -
while (result != null) { -
Log.e("Locaiton reseive-- result); -
sb.append(result); -
= br.readLine(); -
} -
-
= newJSONObject(sb.toString()); -
-
= (JSONObject) data.get("location"); -
-
Location = newLocation(LocationManager.NETWORK_PROVIDER); -
loc.setLatitude((Double) data.get("latitude")); -
loc.setLongitude((Double) data.get("longitude")); -
loc.setAccuracy(Float.parseFloat(data.get("accuracy").toString())); -
loc.setTime( System.currentTimeMillis());//AppUtil.getUTCTime()); -
return loc; -
} catch (JSONException e) { -
e.printStackTrace(); -
return null; -
} catch (UnsupportedEncodingExcep tion e) { -
e.printStackTrace(); -
} catch (ClientProtocolException e) { -
e.printStackTrace(); -
} catch (IOException e) { -
e.printStackTrace(); -
} -
-
return null; -
}
大家注意看这行holder.put("radio_type", cellID.get(0).radioType);
GSM就用"gsm",CDMA就用"cdma"
这个千万别搞混了,不然就获取不到信息了
值得一提的是C网获取基站再定位那偏差不是一般的大,是恨大,将近1千米了,大概是C网基站较少的缘故吧
最后通过经纬度获取地理位置信息,代码如下:
- public
static String getAddress(Location itude) Exception { -
String resultString = -
-
-
String urlString = String.format( itude.getLatitude(), itude.getLongitude()); -
Log.i( urlString); -
-
-
HttpClient client = DefaultHttpClient(); -
-
HttpGet get = HttpGet(urlString); -
{ -
-
HttpResponse response = client.execute(get); -
HttpEntity entity = response.getEntity(); -
BufferedReader buffReader = BufferedReader( newInputStreamReader(entity.getContent())); -
StringBuffer strBuff = StringBuffer(); -
String result = -
((result null)= buffReader.readLine()) != { -
strBuff.append(result); -
} -
resultString = strBuff.toString(); -
-
Log.e( resultString); -
-
-
(resultString null!= && 0)resultString.length() > { -
JSONObject jsonobject = JSONObject(resultString); -
JSONArray jsonArray = JSONArray(jsonobject.get( "Placemark").toString()); -
resultString = -
( inti 0;= i < jsonArray.length(); i++) { -
resultString = jsonArray.getJSONObject(i).getString( -
} -
} -
} (Exception e) { -
new Exception( "获取物理位置出现错误:"+ e.getMessage()); -
} { -
get.abort(); -
client = -
} -
-
resultString; -
}
在获取地理位置的这个location事实上应该传入纠偏后的location,本文暂不做此处理,所以得到的地理信息位置是偶偏差的,大家注意
最后附上截图:
工程下载链接:http://download.csdn.net/detail/geniuseoe2012/4340303