来电过滤 全靠防火墙

技术与开发

模仿功能:来电防火墙

模仿对象:来电通

模仿进度:第三期

开发平台:Windows Mobile平台

有些电话不愿接,有些电话不必接,有些电话不能接……你需要一个“来电防火墙”。

来电防火墙设计思路

提起防火墙,大家可能很快就会想到电脑上常用的网络防火墙。在手机平台,有一种特殊的防火墙,它能将部分来电进行屏蔽。经常收到骚扰电话的用户、经常需要拒听来电的朋友,就需要来电防火墙。

设计一个来电防火墙软件,基本的思路是这样的(图1):

25-f10-1-1.jpg

设置过滤(拦截)规则:一般可以考虑电话号码的黑、白名单,全部/部分拦截,分时段拦截等等。

截获来电:即截获到手机有电话拨入的消息。

获取来电号码:在截获来电后,解析出来电的号码,用于与黑、白名单作对比,看是否需要拒接来电。

拒接/转接来电:程序拒接来电。如果需要对方听到“电话已关机”、“此号码已停机”、“号码不存在”等系统提示音,则可以使用AT指令,将来电转接到特定的电话号码上。

如何监视并截获来电

监视并截获来电,通常有RIL、TAPI、SystemState三种方式。

方式一:RIL

RIL(Radio Interface Layer)是应用处理器与基带处理器之间交互的一组接口。工作在PPP、TCP/IP协议之下,负责数据的可靠传输、AT命令的发送以及response的解析。通过RIL,我们可以实现与GSM/GPRS或者CDMA2000 1X Modem通信,从而能够监视并截获基带处理器中的来电信息。

方式二:TAPI

所谓TAPI,即电话应用程序接口(Telephony Application Program Interface),是一套用来编写与电信业务相关程序的函数。TAPI提供了通用的方法来对付各种各样的硬件,可以监视和截获来电信息。

方式三:SystemState

.NET CF提供了一系列系统状态的notification,包括:SystemProperty.PhoneCallCalling、 SystemProperty.PhoneIncomingCall,SystemProperty.PhoneIncomingCallerNumber、 SystemProperty.PhoneCallTalking等。通过这几个函数的组合,能得到目前电话状态,是正在拨出,还是有来电?是已接通,还是已挂断?

上述三种方式,由于RIL最接近系统底层,所以响应速度最快,TAPI次之,SystemState响应最慢。但是RIL开发难度最大,而且由于各厂商的RIL具体实现有所不同,所以开发的程序可能存在兼容性问题。而.NET CF提供的SystemState方式,兼容性好,容易理解,开发难度小,我们在这里就选用这种方式进行开发。

来电防火墙开发步骤

第一步:创建项目

启动Visual Studio 2008,选择“文件→新建项目”。在弹出的“新建项目”的“项目类型”中选择“Visual C#→智能设备”,“模板”选“智能设备项目”,“名称”设为“CallFirewall”。在弹出的“添加新智能设备项目”对话框中,“目标平台”选择“Windows Mobile 6 Professional SDK”,“.NET Compact Framework 版本”选择“.NET Compact Framework Version 3.5”,“模板”选“设备应用程序”完成项目创建。

第二步:添加程序集

在新创建的项目中,程序集“Microsoft.WindowsMobile.Status”并未默认引用,在这里我们需要手动添加。在“解决方案资源管理器”中,右击“引用”,点击菜单项“添加引用”,在弹出的“添加引用”对话框中,选择“.NET”标签,在组件列表中,选中“Microsoft.WindowsMobile.Status”,点击“确定”。重复上述步骤,添加程序集“Microsoft.WindowsMobile”的引用。

第三步:添加来电监视

在“窗体设计器”里面,双击主窗体,添加窗体的Load事件响应。添加的关键代码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft):

//来电号码事件处理

void phoneIncomingCallerNumber_Changed(object sender, ChangeEventArgs args)

{

throw new NotImplementedException();

}

//呼入状态事件处理

void phoneIncomingCall_Changed(object sender, ChangeEventArgs args)

{

throw new NotImplementedException();

第四步:添加拒接代码

前面提及的RIL与TAPI方式都可以实现来电的拒接,也可以实现来电转接,感兴趣的可以自行试验,这里不作赘述。在这里,我们采用模拟手机“挂机”键按下的方式,来拒接电话。添加的关键代码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft):

//模拟一次挂机按键操作

public static void Drop()

{

keybd_event(VK_F4, 0, 0, 0);

keybd_event(VK_F4, 0, KEYEVENTF_KEYUP, 0);

}

//End键的VK键值 F4

private const int VK_F4 = 0x73;

private const int KEYEVENTF_KEYUP = 0x0002;

//keybd_event API用于发送按键消息

[DllImport("coredll.dll")]

static extern void keybd_event(

第五步:处理来电

将来电的号码跟列表中的号码进行比对,如果是需要拒接的电话,则进行挂断操作。添加的关键代码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft):

string incomingNumber = string.Empty;//记录来电号码

List BannedList = new List();//拒接电话列表

//呼入状态事件处理

void phoneIncomingCall_Changed(object sender, ChangeEventArgs args)

{

try

{

if (BannedList.Exists((s) => // 判断是否为要过滤的电话

{

s = incomingNumber;

return (from t in BannedList

where t.Equals(s)

select t).Count() == 0 ? false : true;

}))

Drop();// 挂断

第六步:运行程序

在Visual Studio 2008中点击菜单“调试→启动调试”(或者直接按F5键),在弹出的部署对话框中选择“Windows Mobile 6 Professional Device”(如果不是真机与电脑连接,那么选择“Windows Mobile 6 Professional Emulator”,则会启动模拟器),点击“部署”,部署完成之后便会在终端上自动启动程序。如果使用模拟器的话,我们可以使用SDK中提供的“蜂窝模拟器”来模拟电话呼叫(图2)。

25-f10-1-2.jpg

读者反馈

开发QQ群:看了第21期关于开发“模拟来电”的文章,我试了一下,碰到一个问题,特来请教。文章说,在“目标平台”中选择“Windows Mobile 6 Professional SDK”,为什么我的Visual Studio 2008中没有这个选项,只有 PPC SDK?我安装的可是完整版的Visual Studio 2008。

小编:要在VS2008中进行Windows Mobile 6的开发,需要先安装Windows Mobile 6 Professional SDK Refresh.msi、Windows Mobile 6 Professional Images (CHS).msi。前者为SDK包,后者为模拟器映像包。

开发QQ群:第23期文章介绍的拒绝“一声响”的3种模式,我一个都不满意。我觉得最好的方式是来电铃声逐渐增大,这个怎么实现?

小编:可以将注册表项HKEY_CURRENT_USER\Controlpanel\Sounds\RingTone0\Script修改为“c50apw3c150r”,这段脚本的意思是:c50:调整为50%的音量;p:响铃;w3:等3秒;c150r:设音量为150%,再重复执行。还可以参照当期文章中“响铃脚本的妙用”一节里面的脚本指令介绍,自己定义更多精彩的响铃方式。

开发QQ群:我在群里面看到有人说蜂窝模拟器,我没有接触过这个东东,它是什么?怎么使用?

小编:在许多情况下,应用程序要跟系统的通信功能进行交互,为了解决测试这种应用程序的困难,Windows Mobile 6 SDK 提供了 Cellular Emulator(蜂窝仿真器)。Cellular Emulator能够测试应用程序在各种蜂窝通信中的状况。

用 Cellular Emulator 可以执行一些简单的测试,例如在仿真器中拨打电话,接听来电和挂断电话,发送和接收 SMS 信息等。为了让开发人员可以测试更复杂的功能,Cellular Emulator 还支持对 SIM 配置信息的修改,以及选择2G网络还是3G网络。点击“开始→Windows Mobile 6 SDK→Tools→Cellular Emulator”,便可运行蜂窝模拟器。

读者问题:在指定的时间启动模拟来电,可以使用定时器Timer组件实现。但是如果手机休眠了,或者手机重启了,如何让程序在指定的时间启动?

高手 阿木:可以使用函数BOOL CeRunAppAtTime(TCHAR* pwszAppName,SystemTime lpTime)设定程序在指定的时间运行。需要特别指出的是,第二个参数SystemTime,需要在.NET Compact Framework中进行特殊的转换。函数具体描述可参考MSDN(http://msdn.microsoft.com/en-us/library/ms913957.aspx)。另外,OpneNETCF中提供的LargeIntervalTimer也可以实现该功能。

读者问题:在某些特殊情况下,需要自动拒接所有的来电,但同时自动回复给对方一条短信以示礼貌,比如“现在正在开会,稍后回复您”等等,我想问问这个功能应该怎么设计?

你是手机编程的高手吗?你能解答上面这位读者的疑问吗?不要犹豫,来我们这里展示一下你的风采吧,来信请发到pcw-chendx@vip.sina.com(也可以给我们发送问题)。

第六个QQ群: 86427709,验证码:手机开发。欢迎对手机编程感兴趣的朋友加入。