本文转自:http://yunlonglove.iteye.com/blog/1560342


在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

通过对网络类型判断后获取对应基站信息代码片段如下:

Html代码
  1. publicstaticArrayList<CellIDInfo>getCellIDInfo(Contextcontext)throwsException{
  2. TelephonyManagermanager=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
  3. ArrayList<CellIDInfo>CellID=newArrayList<CellIDInfo>();
  4. CellIDInfocurrentCell=newCellIDInfo();
  5. inttype=manager.getNetworkType();
  6. Log.d(TAG,"getCellIDInfo-->NetworkType="+type);
  7. intphoneType=manager.getPhoneType();
  8. Log.d(TAG,"getCellIDInfo-->phoneType="+phoneType);
  9. if(type==TelephonyManager.NETWORK_TYPE_GPRS//GSM网
  10. ||type==TelephonyManager.NETWORK_TYPE_EDGE
  11. ||type==TelephonyManager.NETWORK_TYPE_HSDPA)
  12. {
  13. GsmCellLocationgsm=((GsmCellLocation)manager.getCellLocation());
  14. if(gsm==null)
  15. {
  16. Log.e(TAG,"GsmCellLocationisnull!!!");
  17. returnnull;
  18. }
  19. intlac=gsm.getLac();
  20. Stringmcc=manager.getNetworkOperator().substring(0,3);
  21. Stringmnc=manager.getNetworkOperator().substring(3,5);
  22. intcid=gsm.getCid();
  23. currentCell.cellId=gsm.getCid();
  24. currentCell.mobileCountryCode=mcc;
  25. currentCell.mobileNetworkCode=mnc;
  26. currentCell.locationAreaCode=lac;
  27. currentCell.radioType="gsm";
  28. CellID.add(currentCell);
  29. //获得邻近基站信息
  30. List<NeighboringCellInfo>list=manager.getNeighboringCellInfo();
  31. intsize=list.size();
  32. for(inti=0;i<size;i++){
  33. CellIDInfoinfo=newCellIDInfo();
  34. info.cellId=list.get(i).getCid();
  35. info.mobileCountryCode=mcc;
  36. info.mobileNetworkCode=mnc;
  37. info.locationAreaCode=lac;
  38. CellID.add(info);
  39. }
  40. }elseif(type==TelephonyManager.NETWORK_TYPE_CDMA//电信cdma网
  41. ||type==TelephonyManager.NETWORK_TYPE_1xRTT
  42. ||type==TelephonyManager.NETWORK_TYPE_EVDO_0
  43. ||type==TelephonyManager.NETWORK_TYPE_EVDO_A)
  44. {
  45. CdmaCellLocationcdma=(CdmaCellLocation)manager.getCellLocation();
  46. if(cdma==null)
  47. {
  48. Log.e(TAG,"CdmaCellLocationisnull!!!");
  49. returnnull;
  50. }
  51. intlac=cdma.getNetworkId();
  52. Stringmcc=manager.getNetworkOperator().substring(0,3);
  53. Stringmnc=String.valueOf(cdma.getSystemId());
  54. intcid=cdma.getBaseStationId();
  55. currentCell.cellId=cid;
  56. currentCell.mobileCountryCode=mcc;
  57. currentCell.mobileNetworkCode=mnc;
  58. currentCell.locationAreaCode=lac;
  59. currentCell.radioType="cdma";
  60. CellID.add(currentCell);
  61. //获得邻近基站信息
  62. List<NeighboringCellInfo>list=manager.getNeighboringCellInfo();
  63. intsize=list.size();
  64. for(inti=0;i<size;i++){
  65. CellIDInfoinfo=newCellIDInfo();
  66. info.cellId=list.get(i).getCid();
  67. info.mobileCountryCode=mcc;
  68. info.mobileNetworkCode=mnc;
  69. info.locationAreaCode=lac;
  70. CellID.add(info);
  71. }
  72. }
  73. returnCellID;
  74. }


从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接口获取经纬度,代码如下:

Html代码
  1. publicstaticLocationcallGear(List<CellIDInfo>cellID){
  2. if(cellID==null||cellID.size()==0)
  3. returnnull;
  4. DefaultHttpClientclient=newDefaultHttpClient();
  5. HttpPostpost=newHttpPost("http://www.google.com/loc/json");
  6. JSONObjectholder=newJSONObject();
  7. try{
  8. holder.put("version","1.1.0");
  9. holder.put("host","maps.google.com");
  10. holder.put("home_mobile_country_code",cellID.get(0).mobileCountryCode);
  11. holder.put("home_mobile_network_code",cellID.get(0).mobileNetworkCode);
  12. holder.put("radio_type",cellID.get(0).radioType);
  13. holder.put("request_address",true);
  14. if("460".equals(cellID.get(0).mobileCountryCode))
  15. holder.put("address_language","zh_CN");
  16. else
  17. holder.put("address_language","en_US");
  18. JSONObjectdata,current_data;
  19. JSONArrayarray=newJSONArray();
  20. current_data=newJSONObject();
  21. current_data.put("cell_id",cellID.get(0).cellId);
  22. current_data.put("location_area_code",cellID.get(0).locationAreaCode);
  23. current_data.put("mobile_country_code",cellID.get(0).mobileCountryCode);
  24. current_data.put("mobile_network_code",cellID.get(0).mobileNetworkCode);
  25. current_data.put("age",0);
  26. current_data.put("signal_strength",-60);
  27. current_data.put("timing_advance",5555);
  28. array.put(current_data);
  29. if(cellID.size()>2){
  30. for(inti=1;i<cellID.size();i++){
  31. data=newJSONObject();
  32. data.put("cell_id",cellID.get(i).cellId);
  33. data.put("location_area_code",cellID.get(i).locationAreaCode);
  34. data.put("mobile_country_code",cellID.get(i).mobileCountryCode);
  35. data.put("mobile_network_code",cellID.get(i).mobileNetworkCode);
  36. data.put("age",0);
  37. array.put(data);
  38. }
  39. }
  40. holder.put("cell_towers",array);
  41. StringEntityse=newStringEntity(holder.toString());
  42. Log.e("Locationsend",holder.toString());
  43. post.setEntity(se);
  44. HttpResponseresp=client.execute(post);
  45. HttpEntityentity=resp.getEntity();
  46. BufferedReaderbr=newBufferedReader(
  47. newInputStreamReader(entity.getContent()));
  48. StringBuffersb=newStringBuffer();
  49. Stringresult=br.readLine();
  50. while(result!=null){
  51. Log.e("Locaitonreseive-->",result);
  52. sb.append(result);
  53. result=br.readLine();
  54. }
  55. data=newJSONObject(sb.toString());
  56. data=(JSONObject)data.get("location");
  57. Locationloc=newLocation(LocationManager.NETWORK_PROVIDER);
  58. loc.setLatitude((Double)data.get("latitude"));
  59. loc.setLongitude((Double)data.get("longitude"));
  60. loc.setAccuracy(Float.parseFloat(data.get("accuracy").toString()));
  61. loc.setTime(System.currentTimeMillis());//AppUtil.getUTCTime());
  62. returnloc;
  63. }catch(JSONExceptione){
  64. e.printStackTrace();
  65. returnnull;
  66. }catch(UnsupportedEncodingExceptione){
  67. e.printStackTrace();
  68. }catch(ClientProtocolExceptione){
  69. e.printStackTrace();
  70. }catch(IOExceptione){
  71. e.printStackTrace();
  72. }
  73. returnnull;
  74. }


大家注意看这行holder.put("radio_type", cellID.get(0).radioType);

GSM就用"gsm",CDMA就用"cdma"

这个千万别搞混了,不然就获取不到信息了

值得一提的是C网获取基站再定位那偏差不是一般的大,是恨大,将近1千米了,大概是C网基站较少的缘故吧

最后通过经纬度获取地理位置信息,代码如下:

Java代码
  1. publicstaticStringgetAddress(Locationitude)throwsException{
  2. StringresultString="";
  3. /**这里采用get方法,直接将参数加到URL上*/
  4. StringurlString=String.format("http://maps.google.cn/maps/geo?key=abcdefg&q=%s,%s",itude.getLatitude(),itude.getLongitude());
  5. Log.i("URL",urlString);
  6. /**新建HttpClient*/
  7. HttpClientclient=newDefaultHttpClient();
  8. /**采用GET方法*/
  9. HttpGetget=newHttpGet(urlString);
  10. try{
  11. /**发起GET请求并获得返回数据*/
  12. HttpResponseresponse=client.execute(get);
  13. HttpEntityentity=response.getEntity();
  14. BufferedReaderbuffReader=newBufferedReader(newInputStreamReader(entity.getContent()));
  15. StringBufferstrBuff=newStringBuffer();
  16. Stringresult=null;
  17. while((result=buffReader.readLine())!=null){
  18. strBuff.append(result);
  19. }
  20. resultString=strBuff.toString();
  21. Log.e("resultAdress--->",resultString);
  22. /**解析JSON数据,获得物理地址*/
  23. if(resultString!=null&&resultString.length()>0){
  24. JSONObjectjsonobject=newJSONObject(resultString);
  25. JSONArrayjsonArray=newJSONArray(jsonobject.get("Placemark").toString());
  26. resultString="";
  27. for(inti=0;i<jsonArray.length();i++){
  28. resultString=jsonArray.getJSONObject(i).getString("address");
  29. }
  30. }
  31. }catch(Exceptione){
  32. thrownewException("获取物理位置出现错误:"+e.getMessage());
  33. }finally{
  34. get.abort();
  35. client=null;
  36. }
  37. returnresultString;
  38. }

在获取地理位置的这个location事实上应该传入纠偏后的location,本文暂不做此处理,所以得到的地理信息位置是偶偏差的,大家注意

最后附上截图:

工程下载链接:http://download.csdn.net/detail/geniuseoe2012/4340303

更多相关文章

  1. Android(安卓)ionic工程中调用webrtc获取视频流
  2. Android(安卓)选择文件并获取路径
  3. /mnt/sdcard与Environment.getExternalStorageDirectory()的使用
  4. 几个比较混淆概念,android中的Info类以及PackageManager和Activit
  5. android media server 解析1-media player service 结构部分
  6. android中webview接收favicon总是获取为null解决方案
  7. 【笔记】Android上ROS开发——android_core创建一个android应用
  8. Android(安卓)打印日志封装库
  9. Android(安卓)PendingIntent

随机推荐

  1. 传统通信测试厂商借助云计算发力
  2. SDN实战团分享(十九):OpenDaylight在电信网
  3. 「网络架构」网络代理第二部分:Nginx作为
  4. ODL源码分析之flowmod下发流程
  5. SDN实战团分享(二十一):园区网SDN应用分享
  6. AOM:响应可调的动态力致变色器及其在交互
  7. 【PostgreSQL架构】PostgreSQL的最佳群集
  8. AM:外量子效率超过30%的有机热活化延迟荧
  9. kubernetes环境宿主机异常关机导致重新部
  10. 教你玩转Linux—vi/vim