• android GSM+CDMA基站定位


    在googleAPI里提供了基站信息的获取类TelephonyManager,通过其方法getCellLocation得到CellLocation即可获取到基站相关信息

    但CellLocation是个抽象类,所以在具体使用时需要判断接入的网络制式来用其子类CdmaCellLocationGsmCellLocation 来强转

    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()可有多种情况,如下:

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

    Html代码 复制代码
    1. public static ArrayList<CellIDInfo> getCellIDInfo(Context context) throws Exception{   
    2.            
    3.         TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);   
    4.            
    5.         ArrayList<CellIDInfo> CellID = new ArrayList<CellIDInfo>();   
    6.         CellIDInfo currentCell = new CellIDInfo();   
    7.   
    8.         int type = manager.getNetworkType();   
    9.         Log.d(TAG, "getCellIDInfo-->         NetworkType = " + type);   
    10.         int phoneType = manager.getPhoneType();   
    11.         Log.d(TAG, "getCellIDInfo-->         phoneType = " + phoneType);   
    12.            
    13.         if (type == TelephonyManager.NETWORK_TYPE_GPRS              // GSM网   
    14.                 || type == TelephonyManager.NETWORK_TYPE_EDGE   
    15.                 || type == TelephonyManager.NETWORK_TYPE_HSDPA)   
    16.         {   
    17.             GsmCellLocation gsm = ((GsmCellLocation) manager.getCellLocation());   
    18.             if (gsm == null)   
    19.             {   
    20.                 Log.e(TAG, "GsmCellLocation is null!!!");   
    21.                 return null;   
    22.             }   
    23.                    
    24.   
    25.             int lac = gsm.getLac();   
    26.             String mcc = manager.getNetworkOperator().substring(0, 3);   
    27.             String mnc = manager.getNetworkOperator().substring(3, 5);   
    28.             int cid = gsm.getCid();   
    29.                
    30.             currentCell.cellId = gsm.getCid();   
    31.             currentCell.mobileCountryCode = mcc;   
    32.             currentCell.mobileNetworkCode = mnc;   
    33.             currentCell.locationAreaCode = lac;   
    34.                
    35.             currentCell.radioType = "gsm";   
    36.                
    37.             CellID.add(currentCell);   
    38.                
    39.             // 获得邻近基站信息   
    40.             List<NeighboringCellInfo> list = manager.getNeighboringCellInfo();   
    41.             int size = list.size();   
    42.             for (int i = 0; i < size; i++) {   
    43.   
    44.                 CellIDInfo info = new CellIDInfo();   
    45.                 info.cellId = list.get(i).getCid();   
    46.                 info.mobileCountryCode = mcc;   
    47.                 info.mobileNetworkCode = mnc;   
    48.                 info.locationAreaCode = lac;   
    49.                
    50.                 CellID.add(info);   
    51.             }   
    52.                
    53.         }else if (type == TelephonyManager.NETWORK_TYPE_CDMA        // 电信cdma网   
    54.                 || type == TelephonyManager.NETWORK_TYPE_1xRTT   
    55.                 || type == TelephonyManager.NETWORK_TYPE_EVDO_0   
    56.                 || type == TelephonyManager.NETWORK_TYPE_EVDO_A)   
    57.         {   
    58.                
    59.             CdmaCellLocation cdma = (CdmaCellLocation) manager.getCellLocation();      
    60.             if (cdma == null)   
    61.             {   
    62.                 Log.e(TAG, "CdmaCellLocation is null!!!");   
    63.                 return null;   
    64.             }   
    65.                
    66.             int lac = cdma.getNetworkId();   
    67.             String mcc = manager.getNetworkOperator().substring(0, 3);   
    68.             String mnc = String.valueOf(cdma.getSystemId());   
    69.             int cid = cdma.getBaseStationId();   
    70.                
    71.             currentCell.cellId = cid;   
    72.             currentCell.mobileCountryCode = mcc;   
    73.             currentCell.mobileNetworkCode = mnc;   
    74.             currentCell.locationAreaCode = lac;   
    75.        
    76.             currentCell.radioType = "cdma";   
    77.                
    78.             CellID.add(currentCell);   
    79.                
    80.             // 获得邻近基站信息   
    81.             List<NeighboringCellInfo> list = manager.getNeighboringCellInfo();   
    82.             int size = list.size();   
    83.             for (int i = 0; i < size; i++) {   
    84.   
    85.                 CellIDInfo info = new CellIDInfo();   
    86.                 info.cellId = list.get(i).getCid();   
    87.                 info.mobileCountryCode = mcc;   
    88.                 info.mobileNetworkCode = mnc;   
    89.                 info.locationAreaCode = lac;   
    90.                
    91.                 CellID.add(info);   
    92.             }   
    93.         }   
    94.            
    95.         return CellID;   
    96.                
    97.     }  


    从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. public static Location callGear(List<CellIDInfo> cellID) {   
    2.             if (cellID == null || cellID.size() == 0)    
    3.                     return null;   
    4.                
    5.             DefaultHttpClient client = new DefaultHttpClient();   
    6.                 HttpPost post = new HttpPost("http://www.google.com/loc/json");   
    7.                 JSONObject holder = new JSONObject();   
    8.   
    9.                 try {   
    10.                         holder.put("version", "1.1.0");   
    11.                         holder.put("host", "maps.google.com");   
    12.                         holder.put("home_mobile_country_code", cellID.get(0).mobileCountryCode);   
    13.                         holder.put("home_mobile_network_code", cellID.get(0).mobileNetworkCode);   
    14.                         holder.put("radio_type", cellID.get(0).radioType);   
    15.                         holder.put("request_address", true);   
    16.                         if ("460".equals(cellID.get(0).mobileCountryCode))    
    17.                                 holder.put("address_language", "zh_CN");   
    18.                         else   
    19.                                 holder.put("address_language", "en_US");   
    20.                            
    21.                         JSONObject data,current_data;   
    22.   
    23.                         JSONArray array = new JSONArray();   
    24.                            
    25.                         current_data = new JSONObject();   
    26.                         current_data.put("cell_id", cellID.get(0).cellId);   
    27.                         current_data.put("location_area_code", cellID.get(0).locationAreaCode);   
    28.                         current_data.put("mobile_country_code", cellID.get(0).mobileCountryCode);   
    29.                         current_data.put("mobile_network_code", cellID.get(0).mobileNetworkCode);   
    30.                         current_data.put("age", 0);   
    31.                         current_data.put("signal_strength", -60);   
    32.                         current_data.put("timing_advance", 5555);   
    33.                         array.put(current_data);   
    34.                            
    35.                         if (cellID.size() > 2) {   
    36.                             for (int i = 1; i < cellID.size(); i++) {   
    37.                              data = new JSONObject();   
    38.                              data.put("cell_id", cellID.get(i).cellId);   
    39.                              data.put("location_area_code", cellID.get(i).locationAreaCode);   
    40.                              data.put("mobile_country_code", cellID.get(i).mobileCountryCode);   
    41.                              data.put("mobile_network_code", cellID.get(i).mobileNetworkCode);   
    42.                              data.put("age", 0);   
    43.                              array.put(data);   
    44.                             }   
    45.                            }   
    46.   
    47.                            
    48.                            
    49.                            
    50.                         holder.put("cell_towers", array);   
    51.                                                    
    52.                         StringEntity se = new StringEntity(holder.toString());   
    53.                         Log.e("Location send", holder.toString());   
    54.                         post.setEntity(se);   
    55.                         HttpResponse resp = client.execute(post);   
    56.   
    57.                         HttpEntity entity = resp.getEntity();   
    58.   
    59.                         BufferedReader br = new BufferedReader(   
    60.                                         new InputStreamReader(entity.getContent()));   
    61.                         StringBuffer sb = new StringBuffer();   
    62.                         String result = br.readLine();   
    63.                         while (result != null) {   
    64.                                 Log.e("Locaiton reseive-->", result);   
    65.                                 sb.append(result);   
    66.                                 result = br.readLine();   
    67.                         }   
    68.                            
    69.                         data = new JSONObject(sb.toString());   
    70.                          
    71.                         data = (JSONObject) data.get("location");   
    72.   
    73.                         Location loc = new Location(LocationManager.NETWORK_PROVIDER);   
    74.                         loc.setLatitude((Double) data.get("latitude"));   
    75.                         loc.setLongitude((Double) data.get("longitude"));   
    76.                         loc.setAccuracy(Float.parseFloat(data.get("accuracy").toString()));   
    77.                         loc.setTime( System.currentTimeMillis());//AppUtil.getUTCTime());   
    78.                         return loc;   
    79.                 } catch (JSONException e) {   
    80.                         e.printStackTrace();   
    81.                         return null;   
    82.                 } catch (UnsupportedEncodingException e) {   
    83.                         e.printStackTrace();   
    84.                 } catch (ClientProtocolException e) {   
    85.                         e.printStackTrace();   
    86.                 } catch (IOException e) {   
    87.                         e.printStackTrace();   
    88.                 }   
    89.   
    90.                 return null;   
    91.         }  


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

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

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

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

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

    Java代码 复制代码
    1. public static  String getAddress(Location itude) throws Exception {   
    2.         String resultString = "";   
    3.     
    4.         /** 这里采用get方法,直接将参数加到URL上 */  
    5.         String urlString = String.format("http://maps.google.cn/maps/geo?key=abcdefg&q=%s,%s", itude.getLatitude(), itude.getLongitude());   
    6.         Log.i("URL", urlString);   
    7.     
    8.         /** 新建HttpClient */  
    9.         HttpClient client = new DefaultHttpClient();   
    10.         /** 采用GET方法 */  
    11.         HttpGet get = new HttpGet(urlString);   
    12.         try {   
    13.             /** 发起GET请求并获得返回数据 */  
    14.             HttpResponse response = client.execute(get);   
    15.             HttpEntity entity = response.getEntity();   
    16.             BufferedReader buffReader = new BufferedReader(new InputStreamReader(entity.getContent()));   
    17.             StringBuffer strBuff = new StringBuffer();   
    18.             String result = null;   
    19.             while ((result = buffReader.readLine()) != null) {   
    20.                 strBuff.append(result);   
    21.             }   
    22.             resultString = strBuff.toString();   
    23.     
    24.             Log.e("resultAdress--->", resultString);   
    25.                
    26.             /** 解析JSON数据,获得物理地址 */  
    27.             if (resultString != null && resultString.length() > 0) {   
    28.                 JSONObject jsonobject = new JSONObject(resultString);   
    29.                 JSONArray jsonArray = new JSONArray(jsonobject.get("Placemark").toString());   
    30.                 resultString = "";   
    31.                 for (int i = 0; i < jsonArray.length(); i++) {   
    32.                     resultString = jsonArray.getJSONObject(i).getString("address");   
    33.                 }   
    34.             }   
    35.         } catch (Exception e) {   
    36.             throw new Exception("获取物理位置出现错误:" + e.getMessage());   
    37.         } finally {   
    38.             get.abort();   
    39.             client = null;   
    40.         }   
    41.     
    42.         return resultString;   
    43.     }  

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

    最后附上截图:

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

  • 相关阅读:
    应用程序框架实战十三:DDD分层架构之我见
    Util应用程序框架公共操作类(三):数据类型转换公共操作类(扩展篇)
    Util应用程序框架公共操作类(二):数据类型转换公共操作类(源码篇)
    不能使用 float 和 double 来表示金额等精确的值
    JVM 字节码指令手册
    MyBatis: Invalid bound statement (not found)错误的可能原因
    Oracle:ORA-01219:database not open:queries allowed on fixed tables/views only
    手写 Spring MVC
    8080 端口被占用的解决方法 netstat -ano;taskkill (命令行)
    Java 工具类 IpUtil
  • 原文地址:https://www.cnblogs.com/qingblog/p/2598853.html
Copyright © 2020-2023  润新知