自从 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);
好了,暂时小结如下吧,感谢啸天兄前人植树。