在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 ArrayList<CellIDInfo> getCellIDInfo(Context context) throws Exception{
- TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- ArrayList<CellIDInfo> CellID = new ArrayList<CellIDInfo>();
- CellIDInfo currentCell = new CellIDInfo();
- int type = manager.getNetworkType();
- Log.d(TAG, "getCellIDInfo--> NetworkType = " + type);
- int phoneType = manager.getPhoneType();
- Log.d(TAG, "getCellIDInfo--> phoneType = " + phoneType);
- if (type == TelephonyManager.NETWORK_TYPE_GPRS // GSM网
- || type == TelephonyManager.NETWORK_TYPE_EDGE
- || type == TelephonyManager.NETWORK_TYPE_HSDPA)
- {
- GsmCellLocation gsm = ((GsmCellLocation) manager.getCellLocation());
- if (gsm == null)
- {
- Log.e(TAG, "GsmCellLocation is null!!!");
- return null;
- }
- int lac = gsm.getLac();
- String mcc = manager.getNetworkOperator().substring(0, 3);
- String mnc = manager.getNetworkOperator().substring(3, 5);
- int cid = gsm.getCid();
- currentCell.cellId = gsm.getCid();
- currentCell.mobileCountryCode = mcc;
- currentCell.mobileNetworkCode = mnc;
- currentCell.locationAreaCode = lac;
- currentCell.radioType = "gsm";
- CellID.add(currentCell);
- // 获得邻近基站信息
- List<NeighboringCellInfo> list = manager.getNeighboringCellInfo();
- int size = list.size();
- for (int i = 0; i < size; i++) {
- CellIDInfo info = new CellIDInfo();
- info.cellId = list.get(i).getCid();
- info.mobileCountryCode = mcc;
- info.mobileNetworkCode = mnc;
- info.locationAreaCode = lac;
- CellID.add(info);
- }
- }else if (type == TelephonyManager.NETWORK_TYPE_CDMA // 电信cdma网
- || type == TelephonyManager.NETWORK_TYPE_1xRTT
- || type == TelephonyManager.NETWORK_TYPE_EVDO_0
- || type == TelephonyManager.NETWORK_TYPE_EVDO_A)
- {
- CdmaCellLocation cdma = (CdmaCellLocation) manager.getCellLocation();
- if (cdma == null)
- {
- Log.e(TAG, "CdmaCellLocation is null!!!");
- return null;
- }
- int lac = cdma.getNetworkId();
- String mcc = manager.getNetworkOperator().substring(0, 3);
- String mnc = String.valueOf(cdma.getSystemId());
- int cid = cdma.getBaseStationId();
- currentCell.cellId = cid;
- currentCell.mobileCountryCode = mcc;
- currentCell.mobileNetworkCode = mnc;
- currentCell.locationAreaCode = lac;
- currentCell.radioType = "cdma";
- CellID.add(currentCell);
- // 获得邻近基站信息
- List<NeighboringCellInfo> list = manager.getNeighboringCellInfo();
- int size = list.size();
- for (int i = 0; i < size; i++) {
- CellIDInfo info = new CellIDInfo();
- info.cellId = list.get(i).getCid();
- info.mobileCountryCode = mcc;
- info.mobileNetworkCode = mnc;
- info.locationAreaCode = lac;
- CellID.add(info);
- }
- }
- return CellID;
- }
public static ArrayList<CellIDInfo> getCellIDInfo(Context context) throws Exception{ TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); ArrayList<CellIDInfo> CellID = new ArrayList<CellIDInfo>(); CellIDInfo currentCell = new CellIDInfo(); int type = manager.getNetworkType(); Log.d(TAG, "getCellIDInfo--> NetworkType = " + type); int phoneType = manager.getPhoneType(); Log.d(TAG, "getCellIDInfo--> phoneType = " + phoneType); if (type == TelephonyManager.NETWORK_TYPE_GPRS // GSM网 || type == TelephonyManager.NETWORK_TYPE_EDGE || type == TelephonyManager.NETWORK_TYPE_HSDPA) { GsmCellLocation gsm = ((GsmCellLocation) manager.getCellLocation()); if (gsm == null) { Log.e(TAG, "GsmCellLocation is null!!!"); return null; } int lac = gsm.getLac(); String mcc = manager.getNetworkOperator().substring(0, 3); String mnc = manager.getNetworkOperator().substring(3, 5); int cid = gsm.getCid(); currentCell.cellId = gsm.getCid(); currentCell.mobileCountryCode = mcc; currentCell.mobileNetworkCode = mnc; currentCell.locationAreaCode = lac; currentCell.radioType = "gsm"; CellID.add(currentCell); // 获得邻近基站信息 List<NeighboringCellInfo> list = manager.getNeighboringCellInfo(); int size = list.size(); for (int i = 0; i < size; i++) { CellIDInfo info = new CellIDInfo(); info.cellId = list.get(i).getCid(); info.mobileCountryCode = mcc; info.mobileNetworkCode = mnc; info.locationAreaCode = lac; CellID.add(info); } }else if (type == TelephonyManager.NETWORK_TYPE_CDMA // 电信cdma网 || type == TelephonyManager.NETWORK_TYPE_1xRTT || type == TelephonyManager.NETWORK_TYPE_EVDO_0 || type == TelephonyManager.NETWORK_TYPE_EVDO_A) { CdmaCellLocation cdma = (CdmaCellLocation) manager.getCellLocation(); if (cdma == null) { Log.e(TAG, "CdmaCellLocation is null!!!"); return null; } int lac = cdma.getNetworkId(); String mcc = manager.getNetworkOperator().substring(0, 3); String mnc = String.valueOf(cdma.getSystemId()); int cid = cdma.getBaseStationId(); currentCell.cellId = cid; currentCell.mobileCountryCode = mcc; currentCell.mobileNetworkCode = mnc; currentCell.locationAreaCode = lac; currentCell.radioType = "cdma"; CellID.add(currentCell); // 获得邻近基站信息 List<NeighboringCellInfo> list = manager.getNeighboringCellInfo(); int size = list.size(); for (int i = 0; i < size; i++) { CellIDInfo info = new CellIDInfo(); info.cellId = list.get(i).getCid(); info.mobileCountryCode = mcc; info.mobileNetworkCode = mnc; info.locationAreaCode = 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 Location callGear(List<CellIDInfo> cellID) {
- if (cellID == null || cellID.size() == 0)
- return null;
- DefaultHttpClient client = new DefaultHttpClient();
- HttpPost post = new HttpPost("http://www.google.com/loc/json");
- JSONObject holder = new JSONObject();
- 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 array = new JSONArray();
- current_data = new JSONObject();
- 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 i = 1; i < cellID.size(); i++) {
- data = new JSONObject();
- 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 se = new StringEntity(holder.toString());
- Log.e("Location send", holder.toString());
- post.setEntity(se);
- HttpResponse resp = client.execute(post);
- HttpEntity entity = resp.getEntity();
- BufferedReader br = new BufferedReader(
- new InputStreamReader(entity.getContent()));
- StringBuffer sb = new StringBuffer();
- String result = br.readLine();
- while (result != null) {
- Log.e("Locaiton reseive-->", result);
- sb.append(result);
- result = br.readLine();
- }
- data = new JSONObject(sb.toString());
- data = (JSONObject) data.get("location");
- Location loc = new Location(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 (UnsupportedEncodingException e) {
- e.printStackTrace();
- } catch (ClientProtocolException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
public static Location callGear(List<CellIDInfo> cellID) { if (cellID == null || cellID.size() == 0) return null; DefaultHttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost("http://www.google.com/loc/json"); JSONObject holder = new JSONObject(); 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 array = new JSONArray(); current_data = new JSONObject(); 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 i = 1; i < cellID.size(); i++) { data = new JSONObject(); 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 se = new StringEntity(holder.toString()); Log.e("Location send", holder.toString()); post.setEntity(se); HttpResponse resp = client.execute(post); HttpEntity entity = resp.getEntity(); BufferedReader br = new BufferedReader( new InputStreamReader(entity.getContent())); StringBuffer sb = new StringBuffer(); String result = br.readLine(); while (result != null) { Log.e("Locaiton reseive-->", result); sb.append(result); result = br.readLine(); } data = new JSONObject(sb.toString()); data = (JSONObject) data.get("location"); Location loc = new Location(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 (UnsupportedEncodingException 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) throws Exception {
- String resultString = "";
- /** 这里采用get方法,直接将参数加到URL上 */
- String urlString = String.format("http://maps.google.cn/maps/geo?key=abcdefg&q=%s,%s", itude.getLatitude(), itude.getLongitude());
- Log.i("URL", urlString);
- /** 新建HttpClient */
- HttpClient client = new DefaultHttpClient();
- /** 采用GET方法 */
- HttpGet get = new HttpGet(urlString);
- try {
- /** 发起GET请求并获得返回数据 */
- HttpResponse response = client.execute(get);
- HttpEntity entity = response.getEntity();
- BufferedReader buffReader = new BufferedReader(new InputStreamReader(entity.getContent()));
- StringBuffer strBuff = new StringBuffer();
- String result = null;
- while ((result = buffReader.readLine()) != null) {
- strBuff.append(result);
- }
- resultString = strBuff.toString();
- Log.e("resultAdress--->", resultString);
- /** 解析JSON数据,获得物理地址 */
- if (resultString != null && resultString.length() > 0) {
- JSONObject jsonobject = new JSONObject(resultString);
- JSONArray jsonArray = new JSONArray(jsonobject.get("Placemark").toString());
- resultString = "";
- for (int i = 0; i < jsonArray.length(); i++) {
- resultString = jsonArray.getJSONObject(i).getString("address");
- }
- }
- } catch (Exception e) {
- throw new Exception("获取物理位置出现错误:" + e.getMessage());
- } finally {
- get.abort();
- client = null;
- }
- return resultString;
- }
public static String getAddress(Location itude) throws Exception { String resultString = ""; /** 这里采用get方法,直接将参数加到URL上 */ String urlString = String.format("http://maps.google.cn/maps/geo?key=abcdefg&q=%s,%s", itude.getLatitude(), itude.getLongitude()); Log.i("URL", urlString); /** 新建HttpClient */ HttpClient client = new DefaultHttpClient(); /** 采用GET方法 */ HttpGet get = new HttpGet(urlString); try { /** 发起GET请求并获得返回数据 */ HttpResponse response = client.execute(get); HttpEntity entity = response.getEntity(); BufferedReader buffReader = new BufferedReader(new InputStreamReader(entity.getContent())); StringBuffer strBuff = new StringBuffer(); String result = null; while ((result = buffReader.readLine()) != null) { strBuff.append(result); } resultString = strBuff.toString(); Log.e("resultAdress--->", resultString); /** 解析JSON数据,获得物理地址 */ if (resultString != null && resultString.length() > 0) { JSONObject jsonobject = new JSONObject(resultString); JSONArray jsonArray = new JSONArray(jsonobject.get("Placemark").toString()); resultString = ""; for (int i = 0; i < jsonArray.length(); i++) { resultString = jsonArray.getJSONObject(i).getString("address"); } } } catch (Exception e) { throw new Exception("获取物理位置出现错误:" + e.getMessage()); } finally { get.abort(); client = null; } return resultString; }
在获取地理位置的这个location事实上应该传入纠偏后的location,本文暂不做此处理,所以得到的地理信息位置是偶偏差的,大家注意
最后附上截图:
工程下载链接: