60第二版提供了etel族方法用于监视线路上的来电,去电,响铃,挂机等动作。可以在第一时间内获得手机线路的状态变化。但是却并不能获取来电和去电的号码。这本是顺理成章的事情,偏偏在S60 2rd上不行。(S60平台有很多这种应该成立却不成立的事情,导致开发门槛很高,我认为这严重影响了S60平台上软件开发的成长速度。相比较之下, WinCE和Win Mobile则有着高度的内洽性,而且Windows平台的很多经验可以类推。)
Nokia Forum上关于这个问题有无数的文章讨论。这其中有两类解决方案被普遍采用:
1. 使用CLogClient族方法,监控手机日志的变化。因为来电去电也会被记入日志,所以可以通过检测最新的通话日志,并提取其中的电话号码解决问题。刨乐最初使用的也是这种方法。不过这种方法有明显的缺陷,那就是从电话拨出/拨入到日志更新有一段明显的时间间隔,常常导致电话已经接通了,还没有获取到电话号码。虽然经过一些努力有所改善,最终还是不能满足需求。
2. 使用etel的秘密版本。这是在论坛上流传的“完整版”的etel库。比公开发行的库多了很多类。对我们有用的是带Mobile一族的类,如RMobileCall。据说这是从 motolora传出来的。(S60联盟的做法真是令人不解,既然做智能手机平台,却藏藏掖掖,这个不提供,那个不提供。难道他们不知道软件越多,他们就会越成功吗?)。使用以下代码,可以非常可靠的获取来电/去电号码(在通话接通前):
iLine是成员变量,事先已经调用Open() 打开了线路. GetPhoneNumber这个函数应该在
得到EStatusDialling和EStatusConnecting或者EStatusRinging的时候调用.
enum CallDirection
{
EIncoming,
EOutgoing,
};
TBuf<64> CMyPhone::GetPhoneNumber(enum CallDirection direction)
{
RLine::TCallInfo callInfo;
TName callName;
const TInt KCallIndex = 0;
RLine::TLineInfo lineInfo;
//一定要调用这一句,否则在一些机型上 GetMobileCallInfo() 会导致panic
//GetMobileCallInfo()可是最要紧的一句呀.网络上提供的代码大多没有提到
//这一点,只有Nokia Wiki上的样例代码包含了.
iLine.GetCallInfo(KCallIndex, callInfo);
iLine.GetInfo(lineInfo);
RMobileCall m_currentCall;
if(direction == EIncoming)
{
callName.Copy(lineInfo.iNameOfCallForAnswering);
}
else
{
callName.Copy(lineInfo.iNameOfLastCallAdded);
}
m_currentCall.OpenExistingCall(iLine, callName);
RMobileCall::TMobileCallInfoV1 mobCallInfo;
RMobileCall::TMobileCallInfoV1Pckg mobCallInfoPckg(mobCallInfo);
User::LeaveIfError(m_currentCall.GetMobileCallInfo(mobCallInfoPckg));
TBuf<64> telNumber;
if(direction == EIncoming)
{
telNumber.Copy(mobCallInfo.iRemoteParty.iRemoteNumber.iTelNumber);
}
else
{
telNumber.Copy(mobCallInfo.iDialledParty.iTelNumber);
}
m_currentCall.Close();
return telNumber;
}
可惜这还不够.如果你的电话第二次想起,这个函数被调用第二次,又会panic,这次是在OpenExistingCall, 死得更早. Nokia没有任何官方的解释,我的办法是在电话终止的
时候把所有的Phone,Line,Call统统关掉,重新打开.不用说,这样是有些浪费的,但是没
有办法,这是目前唯一可行的办法.