关于Symbian识别移动、联通和其它运营商网络的方法
自从Symbian OS在EKA2提供了强大的CTelephony,这之后很多跟网络相关的参数都通过这个获取,像识别目前手机是注册的是移动还是联通等信息网络上传的比较多的也是通过该方法,特别是啸天兄在nokia论坛分享了代码之后,网络上大多采用其代码,当然也包括我这样的懒人在内,而且往往很多人都没有注意最关键的原理即“国际移动用户识别码(IMSI:International Mobile Subscriber Identification Number)是区别移动用户的标志,储存在SIM卡中,可用于区别移动用户的有效信息。IMSI由MCC、MNC、MSIN组成,其中MCC为移动国家号码,由3位数字组成,唯一地识别移动客户所属的国家,我国为460;MNC为网络id,由2位数字组成,用于识别移动客户所归属的移动网络,中国移动为00,中国联通为01;MSIN为移动客户识别码,采用等长11位数字构成”。具体详见http://wiki.forum.nokia.com/index.php/%E5%8C%BA%E5%88%86%E5%BD%93%E5%89%8D%E7%94%A8%E6%88%B7SIM%E5%8D%A1%E6%98%AF%E7%A7%BB%E5%8A%A8%E8%BF%98%E6%98%AF%E8%81%94%E9%80%9A
最近在使用该代码时,发现假如当手机处于离线状态下,则不论有无插SIM卡,使用啸天兄的方法,就识别不出来了,这个应该跟CTelephony的实现有关,本人试着通过其源码去了解了,但是貌似跟踪到底层没有完全公开,或者说个人看源码能力还太弱了些。由于采用啸天兄方法实现不了了,所以只能从上面的红头文件(即红体字)寻找解决方法,虽然CTelephony::GetCurrentNetworkInfo在离线模式下失效,但是CTelephony::GetSubscriberId仍然可用,为此我们就可以通过直接分析IMSI来实现对运营商网络的识别,至于MNC的信息,大家可以查询http://en.wikipedia.org/wiki/Mobile_network_code,在国内的情况如下截图:
既然知道了如上信息,我们就可以简单的对IMSI号进行分析了,小可对啸天兄的代码进行简单修改,当然该代码也是使用CTelephony,只能使用在EKA2平台上,EKA1可以采用RMobilePhone::GetSubscriberId的方法来获取IMSI,在这里也就不做展开了,具体代码如下:
头文件
/*
* TelephonyAO.h
*
* Created on: 2010-4-22
* Author: frank
*/
#ifndef TELEPHONYAO_H_
#define TELEPHONYAO_H_
#include <e32base.h>
#include <Etel3rdParty.h>
typedef enum
{
ENetWorkUnKnow,
ENetWorkCM,
ENetWorkUN,
ENetWorkTC,
ENetWorkTT,
}TNetWorkType;
class CTelephonyAO : public CActive
{
public:
static CTelephonyAO* NewL();
TNetWorkType GetNetWorkId();
public:
~CTelephonyAO();
protected:
void DoCancel();
void RunL();
private:
CTelephonyAO();
void ConstructL();
void GetNetWorkInfo();
private:
CActiveSchedulerWait* iActiveSchedulerWait;
CTelephony* pTelephony_;
CTelephony::TSubscriberIdV1 iSubscribId;
CTelephony::TSubscriberIdV1Pckg iSubscriberIdPckg;
};
#endif /* TELEPHONYAO_H_ */
实现文件
/*
* TelephonyAO.cpp
*
* Created on: 2010-4-22
* Author: frank
*/
#include "TelephonyAO.h"
CTelephonyAO::CTelephonyAO() : CActive(EPriorityStandard), iSubscriberIdPckg(iSubscribId)
{
}
CTelephonyAO::~CTelephonyAO()
{
delete pTelephony_;
pTelephony_ = NULL;
delete iActiveSchedulerWait;
iActiveSchedulerWait = NULL;
}
void CTelephonyAO::ConstructL()
{
pTelephony_ = CTelephony::NewL();
iActiveSchedulerWait = new (ELeave)CActiveSchedulerWait;
CActiveScheduler::Add(this);
}
CTelephonyAO* CTelephonyAO::NewL()
{
CTelephonyAO* pSelf = new(ELeave) CTelephonyAO;
CleanupStack::PushL(pSelf);
pSelf->ConstructL();
CleanupStack::Pop();
return pSelf;
}
void CTelephonyAO::RunL()
{
if (iActiveSchedulerWait->IsStarted())
{
iActiveSchedulerWait->AsyncStop();
}
}
void CTelephonyAO::DoCancel()
{
pTelephony_->CancelAsync(CTelephony::EGetSubscriberIdCancel);
if (iActiveSchedulerWait->IsStarted())
{
iActiveSchedulerWait->AsyncStop();
}
}
void CTelephonyAO::GetNetWorkInfo()
{
Cancel();
pTelephony_->GetSubscriberId(iStatus, iSubscriberIdPckg);
SetActive();
iActiveSchedulerWait->Start();
}
TNetWorkType CTelephonyAO::GetNetWorkId()
{
GetNetWorkInfo();
TNetWorkType vNetWorkType = ENetWorkUnKnow;
if(iSubscribId.iSubscriberId.Length() < 15)
{
vNetWorkType = ENetWorkUnKnow;
}
else
{
TBuf<6> vHeader;
vHeader.Copy(iSubscribId.iSubscriberId.Left(5));
TBuf<3> vPtrTemp;
vPtrTemp.Copy(vHeader.Right(2));
TInt vNetWorkId = 0;
TLex vLex(vPtrTemp);
vLex.Val(vNetWorkId);
if((vNetWorkId == 1) ||(vNetWorkId == 6))
{
vNetWorkType = ENetWorkUN;
}
else if((vNetWorkId == 0) ||(vNetWorkId == 2))
{
vNetWorkType = ENetWorkCM;
}
else if((vNetWorkId == 3) ||(vNetWorkId == 5))
{
vNetWorkType = ENetWorkTC;
}
else if(vNetWorkId == 20)
{
vNetWorkType = ENetWorkTT;
}
else
{
vNetWorkType = ENetWorkUnKnow;
}
}
return vNetWorkType;
}
至于如何调用,就可以通过如下简单获取了,不用再自己去比较了。
CTelephonyAO* pTelephony = CTelephonyAO::NewL();
CleanupStack::PushL(pTelephony);
TNetWorkType vNetWorkType = pTelephony->GetNetWorkId();
CleanupStack::PopAndDestroy(pTelephony);
好了,暂时小结如下吧,感谢啸天兄前人植树。