關于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);
好了,暫時小結如下吧,感謝嘯天兄前人植樹。
posted on 2010-04-22 19:13
frank.sunny 閱讀(2186)
評論(3) 編輯 收藏 引用 所屬分類:
C/C++學習和實踐 、
symbian 開發