概述:

本篇主要介绍Android获取基站信息的方式,除此之外,还有SIM卡相关字段获取,先介绍一些缩写的概念,后续更新代码的写法。

前言:之前有碰到一个需求,需要获取SIM卡的相关属性:IMSI号、SIM卡序号、通话号码、SIM运营商国家代码、运营商名称、网络运营商等参数,然后是基站信息:mcc#mnc#lac#cellid#rss。也按照网上的方法踩过一些坑,这边就记录一下自己可行的方案。

基站信息的缩写概念:

LAC:Location Area Code,定位区域编码,2个字节长的十六进制BCD码(不包括0000和FFFE)

TAC:Tracking Area Code,追踪区域编码,

CID:Cell Identity,信元标识,2个字节

MCC:Mobile Country Code,移动国家代码,三位数,中国:460

MNC:Mobile Network Code,移动网络号,两位数(中国移动0,中国联通1,中国电信2)

BSSS:Base station signal strength,基站信号强度

网络类型:

1)NETOWRK_TYPE_GPRS 1-移动联通 2.5G

2)NETOWRK_TYPE_EDGE 2-移动 2.75G

3)NETOWRK_TYPE_UMTS 3-联通 WCDMA 46006

UMTS定义是一种3G移动电话技术,使用WCDMA作为底层标准,WCDMA向下兼容GSM网络。

4)NETOWRK_TYPE_CDMA 4-电信

5)NETOWRK_TYPE_1xRTT 7-电信

6)NETOWRK_TYPE_EVD0_0、NETOWRK_TYPE_EVD0_A、NETOWRK_TYPE_EVD0_B

5-6-12 - 电信

7)NETOWRK_TYPE_HSDPA 8-联通 46006 3.5G

8)NETOWRK_TYPE_LTE 13-移动、联通、电信 —— 4G 各个运营商都可能使用。

9)NETOWRK_TYPE_GSM 16

10)NETOWRK_TYPE_TD_SCDMA 17-移动 3G 的时候 使用

运营商代码460开头的整理:

46000 中国移动 (GSM)

46001 中国联通 (GSM)

46002 中国移动 (TD-S)

46003 中国电信(CDMA)

46004 空(似乎是专门用来做测试的)

46005 中国电信 (CDMA)

46006 中国联通 (WCDMA)

46007 中国移动 (TD-S)

46008

46009

46010

46011 中国电信 (FDD-LTE)

LTE CDMA GSM WCDMA

手机网络设置里面有个优先网络,里面有中国移动46000,46002,41004,是什么意思,有什么功能?

答案:46000,46002,41004是移动网络的ID号(PLMN标识),它们所支持的接入技术分别为:

46000是中国移动GSM网络的标识号(PLMN标识),所支持的接入技术为 GSM/TD-SCDMA。

46001是中国联通GSM网络的标识号(PLMN标识),所支持的接入技术为 GSM。

46002 是中国移动134/159的SIM卡的PLMN标识,所支持的接入技术为 GSM/TD-SCDMA。

46007是中国移动TD-SCDMA网的PLMN标识,所支持的接入技术为 TD-SCDMA。

41004是中国移动香港的PLMN标识

说明:

IMSI由三部分组成:

移动国家号码MCC: 由3个数字组成,唯一地识别移动用户所属的国家.中国为460.

移动网号MNC: 识别移动用户所归属的移动网.

移动用户识别码MSIN: 唯一地识别国内数字蜂窝移动通信网中的移动用户.

SIM卡信息(示例是一张电信卡信息):

(呃…基站信息的日志没拿到,尴尬,下次补上)

sim info[

simValue = -----,//这个字段客户自己订制还没给我,暂且为空

imsi = 460110421969346,

serialNumber = 89860315007690441866,

lineNumber = ,//现在手机号码不一定会存在SIM卡中,有的是在通信过程中才能拿到

countryIso = cn,

operatorName = 中国电信, 

networkOperatorName = CHN-CT,

networkCountryIso = cn

先介绍几个简单的SIM卡属性字段获取方式,包括:

IMSI、SimSerialNumber、Line1Number、NetworkCountryIso、SimOperatorName、NetworkOperatorName、NetworkCountryIso

public static String getImsi(Context context, String imsi) {
    String ret = null;
    try {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        ret = telephonyManager.getSubscriberId();
    } catch (Exception e) {
        LoggerUtils.e("---------" + e.getMessage());
    }
    if (!TextUtils.isEmpty(ret)){
        return ret;
    } else {
        return imsi;
    }
}

先拿到系统服务,然后取到Context.TELEPHONY_SERVICE,然后通过telephonyManager取到相关属性。

这部分介绍基站信息的获取

拿到所有的基站信息List<CellInfo>,遍历之后,每一项分别判断实例比如info instanceof CellInfoCdma,然后分别拿到基站信息单位的各条属性。代码不难,只是要看过知道怎么玩就OK。

//获取基站信息
public static List<String> getTowerInfo(Context context) {
    int mcc = -1;
    int mnc = -1;
    int lac = -1;
    int cellId = -1;
    int rssi = -1;
    TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    String operator = tm.getNetworkOperator();
    mcc = Integer.parseInt(operator.substring(0, 3));
    List<String> list = new ArrayList<String>();
    List<CellInfo> infos = tm.getAllCellInfo();
    for (CellInfo info : infos){
        if (info instanceof CellInfoCdma){
            CellInfoCdma cellInfoCdma = (CellInfoCdma) info;
            CellIdentityCdma cellIdentityCdma = cellInfoCdma.getCellIdentity();
            mnc = cellIdentityCdma.getSystemId();
            lac = cellIdentityCdma.getNetworkId();
            cellId = cellIdentityCdma.getBasestationId();
            CellSignalStrengthCdma cellSignalStrengthCdma = cellInfoCdma.getCellSignalStrength();
            rssi = cellSignalStrengthCdma.getCdmaDbm();
        }else if (info instanceof CellInfoGsm){
            CellInfoGsm cellInfoGsm = (CellInfoGsm) info;
            CellIdentityGsm cellIdentityGsm = cellInfoGsm.getCellIdentity();
            mnc = cellIdentityGsm.getMnc();
            lac = cellIdentityGsm.getLac();
            cellId = cellIdentityGsm.getCid();
            CellSignalStrengthGsm cellSignalStrengthGsm = cellInfoGsm.getCellSignalStrength();
            rssi = cellSignalStrengthGsm.getDbm();
        }else if (info instanceof CellInfoLte){
            CellInfoLte cellInfoLte = (CellInfoLte) info;
            CellIdentityLte cellIdentityLte = cellInfoLte.getCellIdentity();
            mnc = cellIdentityLte.getMnc();
            lac = cellIdentityLte.getTac();
            cellId = cellIdentityLte.getCi();
            CellSignalStrengthLte cellSignalStrengthLte = cellInfoLte.getCellSignalStrength();
            rssi = cellSignalStrengthLte.getDbm();
        }else if (info instanceof CellInfoWcdma){
            CellInfoWcdma cellInfoWcdma = (CellInfoWcdma) info;
            CellIdentityWcdma cellIdentityWcdma = null;
            CellSignalStrengthWcdma cellSignalStrengthWcdma = null;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
                cellIdentityWcdma = cellInfoWcdma.getCellIdentity();
                mnc = cellIdentityWcdma.getMnc();
                lac = cellIdentityWcdma.getLac();
                cellId = cellIdentityWcdma.getCid();
                cellSignalStrengthWcdma = cellInfoWcdma.getCellSignalStrength();
                rssi = cellSignalStrengthWcdma.getDbm();
            }
        }else {
            LoggerUtils.e("get CellInfo error");
            return null;
        }
        String tower = String.valueOf(mcc) + "#" + String.valueOf(mnc) + "#" + String.valueOf(lac)
                + "#" + String.valueOf(cellId) + "#" + String.valueOf(rssi);
        list.add(tower);
    }
    if (list.size() > 6){
        list = list.subList(0, 5);
    }else if (list.size() < 3){
        int need = 3 - list.size();
        for (int i = 0; i < need; i++) {
            list.add("");
        }
    }
    return list;

}

虽然代码不难,但是之前由于网上的方法实在是……不太好用,不知道是方法老了还是什么原因。不过东扯西扯,算是这个方法最好用了,也比较全面。