Android基站定位详解

来源:互联网 发布:sql 查询列重复的数据 编辑:程序博客网 时间:2024/05/21 10:30

1.概述

本文主要介绍android基站定位的基本思路,介绍了一些TelephonyManager中用到方法。最后简单说明google定位服务与android提供参数之间的联系。

2. 基站定位原理:

我们可以通过手机信号获取基站信息,然后调用第三方服务,再根据基站信息查找基站的经度纬度值。尽管基站网络制式不同(cdma或gsm)所获取的基站信息也不一样,但用谷歌等一般这样的第三方定位服务都需要获得以下这些基站信息:

  1. MCC,Mobile Country Code,移动国家代码(中国的为460)。
  2. MNC,Mobile Network Code,移动网络号码(中国移动为0,中国联通为1,中国电信为2)。
  3. LAC,Location Area Code,位置区域码。
  4. CID,Cell Identity,基站编号。
  5. BSSS,Base station signal strength,基站信号强度。

3. Android基站信息api

获取网络服务商信息MNC&MCC

从系统服务中获取TelephonyManager:

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

TelephonyManager#getNetworkOperator方法获取目前注册网络MCC+MNC信息,一般是5-6位的字符串,前3位为MCC,后面的是MNC。
用户必须在该网络注册才能获取到信息,对于cdma网络而言可能会不靠谱,因此用TelephonyManager#getPhoneType来判断手机支持的网络制式。

String operator = telephonyManager.getNetworkOperator();String mcc = operator.substring(0, 3);String mnc = operator.substring(3);

TelephonyManager#getSimOperator方法获取Sim卡的MCC+MNC信息
SM卡状态必须处于SIM_STATE_READY,用TelephonyManager#getSimState判断Sim卡状态。

TelephonyManager#getPhoneType 获取手机支持网络制式
一般就GSM、CDMA两种,如果没有获取到则是NONE。

TelephonyManager#getNetWorkType 获取网络类型
用以区分移动2g,电信4g等更具体的网络。

获取当前连接基站信息LAC、CID

由于电信用的是cdma制式网络,移动和联通用的gsm网络,这两种网络基站信息封装类在android中是不同的,cdma要用CdmaCellLocation,gsm要用GsmCellLocation。
从TelephonManager获取基站定位信息CellLocation,其中封装了需要的CID和LAC等信息。

if(telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA){    CdmaCellLocation cdmaCellLocation = (CdmaCellLocation) telephonyManager.getCellLocation();    int cid = cdmaCellLocation.getBaseStationId(); //获取cdma基站识别标号 BID    int lac = cdmaCellLocation.getNetworkId(); //获取cdma网络编号NID    int sid = cdmaCellLocation.getSystemId(); //用谷歌API的话cdma网络的mnc要用这个getSystemId()取得→SID}else{    GsmCellLocation gsmCellLocation = (GsmCellLocation) telephonyManager.getCellLocation();    int cid = gsmCellLocation.getCid(); //获取gsm基站识别标号    int lac = gsmCellLocation.getLac(); //获取gsm网络编号}

获取邻近基站信号强度信息BSSS

每个基站信息封装在具体CellInfo子类中,有CellInfoCdma、CellInfoGsm等。CellInfoGsm中又封装了2个函数,分别用来返回基站识别信息(CellIdentityGsm类)和基站信号强度信息(CellSignalStrengthGsm类)。

TelephonyManager#getAllCellInfo方法返回所有能检测到的基站信息(包括连接的基站信息),而且返回的信息更详细。而TelephonyManager#getNeighboringCellInfo方法不包括连接的基站信息,返回基站信息是经过处理的,不加以cdma或gsm区分。一般用getAllCellInfo方法。

List<CellInfo> infoLists = telephonyManager.getAllCellInfo();    for (CellInfo info : infoLists) {        CellInfoCdma cellInfoCdma = (CellInfoCdma) info;        CellIdentityCdma cellIdentityCdma = cellInfoCdma.getCellIdentity();        CellSignalStrengthCdma cellSignalStrengthCdma = cellInfoCdma.getCellSignalStrength();        int strength = cellSignalStrengthCdma.getCdmaDbm();        int cid = cellIdentityCdma.getBasestationId();        // 处理 strength和id数据    }

CellSignalStrengthCdma类中封装了各种信号处理方法,用来返回不同标准的信号强度。CellIdentityCdma类封装了Cdma基站特有的识别信息,比如能通过CellIdentityCdma#getLongitude()获取Cdma基站的经纬度。CellIdentityGsm类封装Gsm基站信息,能获取MCC、MNC、CID和LAC。

4. Android 基站信息监听器

PhoneStateListener类是一个监听类,重写其中方法实现对基站信息变化的监听。

private PhoneStateListener phoneStateListener; //定义监听器telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CELL_LOCATION); //注册监听器,设定不同的监听类型//设置监听器方法private void setPhoneStateListener(){    phoneStateListener = new PhoneStateListener(){        @Override         public void onCellLocationChanged(CellLocation location){}        @Override        public void onSignalStrengthsChanged(SignalStrength signalStrength) {}        @Override        public void onCellInfoChanged(List<CellInfo> cellInfo) {}    }}

这里主要用到的三个回调函数:

  • onCellLocationChanged 当cellLocation变化时会调用,传入cellLocation类型,需要根据具体的网络制式向下转型(CdmaCellLocation或GsmCellLocation)。

  • onSignalStrengthsChanged 传入的是SignalStrength类型,这个类型和CellStrength类没关系,是一个重新写的类。其中有自定义的一些方法返回信号强度,有getCdmaDbm()、getGsmSignalStrength()。Coma和gsm类型都封装在一起,需要调用额外的方法isGsm()。

  • onCellInfoChanged 传入参数为CellInfo,维护一个CellInfo列表,有检测到的基站变动都会调用。方法跟TelephonyManager#getAllCellInfo()的使用类似。

google定位服务API 说明

移动电话基站Json

google的基站定位服务所需参数:

"homeMobileCountryCode": 310,  //即MCC  "homeMobileNetworkCode": 410,   //即MNC  "radioType": "gsm",  "carrier": "Vodafone",  "considerIp": "true",  "cellTowers": [    // See the Cell Tower Objects section below.  ]

cellTower就是之前说的信号强度BSSS参数,需要一个列表来记录周围基站参数。cellTower并不是必要参数,但是给了可以增加定位精确度。

{  "cellTowers": [    {      "cellId": 42,      "locationAreaCode": 415,      "mobileCountryCode": 310,      "mobileNetworkCode": 410,      "age": 0,      "signalStrength": -60,      "timingAdvance": 15    }  ]}

CellTowers必填字段:

  • cellId(必填): GSM用的是CID,CDMA 网络使用的是基站 ID (BID)。WCDMA 网络使用 UTRAN/GERAN 基站标识 (UC-Id),这是一个 32 位的值,由无线网络控制器 (RNC) 和基站 ID 连接而成。在 WCDMA 网络中,如果只指定 16 位的基站 ID 值,返回的结果可能会不准确。
  • locationAreaCode(必填):GSM 和 WCDMA 网络的位置区域代码 (LAC)。CDMA 网络的网络 ID (NID)。
  • mobileCountryCode(必填):移动电话基站的移动国家代码 (MCC)。
  • mobileNetworkCode(必填):移动电话基站的移动网络代码。对于 GSM 和 WCDMA,这就是 MNC;CDMA 使用的是系统 ID (SID)。