概述
本篇主要介绍android基站定位的基本思路,解释了下用到的TelephonyManager的一些方法。最后介绍了google定位服务与android提供参数之间的联系。
基站定位原理:
通过手机信号获取基站信息,然后调用第三方服务的根据基站信息查找基站的经纬度值。
尽管根据基站网络制式不同(cdma或gsm)所获取的基站信息也不一样,但一般用谷歌等这样的第三方定位服务需要获得这些基站信息:
- MCC,Mobile Country Code,移动国家代码(中国的为460)。
- MNC,Mobile Network Code,移动网络号码(中国移动为0,中国联通为1,中国电信为2)。
- LAC,Location Area Code,位置区域码。
- CID,Cell Identity,基站编号。
- BSSS,Base station signal strength,基站信号强度。
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。
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)。