65.9K
CodeProject 正在变化。 阅读更多。
Home

拥有您的手机 - 重新掌控您的手机

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (13投票s)

2009年1月3日

CPOL

8分钟阅读

viewsIcon

49905

downloadIcon

435

我们将为 Windows Mobile 5.x/6.x 构建一个呼叫管理应用程序,该应用程序可以以编程方式忽略、转接语音信箱或通过短信回复不必要的来电。

CallBouncer

引言

本文将介绍使用状态和通知代理 (State and Notifications Broker) 结合 P/Invoke 技术进行 Windows Mobile 呼叫管理的基础知识。最终,我们将构建一个可以部署到 Windows Mobile 手机上的应用程序,让您能够以编程方式处理您不想自己接听的来电,例如在会议期间、睡觉时、看电影时等。与其接听电话,不如将它们以编程方式转接至语音信箱、忽略或发送短信自动回复消息。

背景

事情开始得很正常——我在工作时接到手机来电。低头一看,我不认识这个号码……是个 866 开头的号码。我犹豫了一下,然后接听了……天哪,怎么会有推销电话打到我的手机上?我挂断了,但后来,又有一个 866 号码打来。我立刻按下了“忽略”软键,麻烦就此打住。快进大约 40 分钟,同一个号码又打来了。我再次忽略,这次我把它保存在了联系人列表中,命名为“烦人的 866 电话”,这让我想起了一个类似的故事,我要讲讲一个俄亥俄州的女人几个月来一直错拨我的号码,但现在,我们还是回到手头的问题。

我开始思考,然后真的觉得很烦人……毕竟这是我的手机,为什么我就不能控制是否要被这种电话打扰呢?嗯,使用 Windows Mobile,我可以!本文中我们将构建的应用程序就是我因这些来电而烦恼的成果。

首先,我们先定几条规则——据我所知,目前还没有一种方法可以(换句话说,以编程方式)在不向用户发出任何通知的情况下自动拒绝来电。我可以接受这一点并设法解决。我设计这个项目的最终目标是让我不再需要处理那些打扰我手机的烦人的免费电话号码……直到我完成了这个项目的第一个迭代,其他想法才悄悄出现,我才意识到,还有很多事情可以做,让我的手机真正为我服务……更多内容稍后讨论。

既然我们无法自动拒绝来电,那还能做什么呢?好吧,看看我平常的操作,我可以这样分解:

  1. 电话响了——看屏幕上显示的来电号码。
  2. 这个号码是 800 号码吗?如果是,按下“忽略”软键,然后确认“未接来电”通知。

由于这是一系列简短的手动步骤,我们可以对其进行自动化,我的生活又会变得轻松 :)

与状态和通知代理 (State and Notifications Broker) 交朋友

如果您正在开发 Windows Mobile 软件,很快就会发现您需要熟悉状态和通知代理 (SNB)。SNB 为您提供了一个强大的机制,用于存储和处理与您的移动设备状态更改相关的信息。我不会重复已经写过的关于 SNB 的内容——相反,您可以在 MSDN 上阅读相关内容以开始。链接如下:http://msdn2.microsoft.com/en-us/library/aa455748.aspx

SNB 在我们的项目中起着关键作用,因为它将检测到有来电并检索来电号码。一旦我们有了号码,我们只需对其进行分析,然后允许它通过,这样我就可以接听它,或者以编程方式按下“忽略”软键,这样我就不必处理它了。那么,让我们看看我们将为此使用的代码。

我设置了一个名为 `MonitorNotifications` 的小型函数,它在窗体加载时被调用。此函数将我的 `phoneStatus` 系统状态通知添加到我创建的 ArrayList 中(以防我以后想在此项目中添加更多系统状态通知)。

您会注意到,在这种情况下,我们正在监视的 `SystemProperty` 是 `PhoneIncommingCall`,并且我们为该状态更改添加了一个处理程序。

Private Sub MonitorNotifications()
     Dim s As SystemState
     s = New SystemState(SystemProperty.PhoneIncomingCall)
     AddHandler s.Changed, AddressOf ChangeOccurred
     StateNotificationList.Add(s)
End Sub

那么,在 `ChangeOccured` 的事件处理程序中会发生什么呢?看看下面

Private Sub ChangeOccurred(ByVal sender As Object, ByVal args As ChangeEventArgs)
    If SystemState.PhoneIncomingCall = True And chkIgnoreAllCalls.Checked = True Then
        BounceCall()
    End If
    If SystemState.PhoneIncomingCall = True And _
       SystemState.PhoneIncomingCallerNumber = txtIgnoreThisNumber.Text Then
          BounceCall()
    End If
End Sub

基本上,这只是处理电话管理逻辑。首先,我们检查是否要忽略所有来电(通过窗体上的复选框),然后检查来电号码是否在我简单的“阻止号码”(屏幕上的文本框)中。如果这两个条件之一为真,则使用 `BounceCall` 函数拒绝来电。

`BounceCall` 函数利用 P/Invoke 以编程方式按下设备上出现来电时显示的“忽略”软键。P/Invoke 的完整介绍超出了本文的范围,所以请将其作为起点并从中学习……我将在以后的文章中介绍更多关于 P/Invoke 的内容。这是我们正在处理的代码

Const KEYEVENTF_KEYUP = &H2
Const KEYEVENTF_KEYDOWN = &H0
<dllimport("coredll.dll", charset:=""Runtime.InteropServices.CharSet.Unicode)"" /> _
Private Shared Sub keybd_event(ByVal bVk As Byte, ByVal bScan As Byte, _
        ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
End Sub

Public Shared Sub BounceCall()
    keybd_event(115, 0, KEYEVENTF_KEYDOWN, 0)
    keybd_event(115, 0, KEYEVENTF_KEYUP, 0)
End Sub
</dllimport("coredll.dll", />

首先,我们定义了两个用于键盘事件的常量。然后,我们使用 P/Invoke 来处理实际的键盘事件。 `BounceCall` 只是对相应的软键执行编程的“按下”和“抬起”操作。

现在我们已经回顾了代码的基础知识,让我们来看看应用程序的实际运行情况。

CallBouncer

在这里,我们在模拟器中看到了基本窗体的运行情况。注意我那个很酷的小“拦截器”——我认为它是一个适合该项目的图形!

接下来,启动“蜂窝网络模拟器”工具(如果您不确定如何配置它以与模拟器一起使用,请查看我之前的文章,其中详细介绍了这些步骤:http://ilovevb.net/Web/blogs/vbmobile/archive/2008/01/07/vb-net-mobile-hello-world.aspx)。

一旦您运行了蜂窝网络模拟器,就给设备模拟器打个电话,让它像下图一样出现在屏幕上

CallBouncer/CB2.JPG

请注意,在来电过程中出现的“接受”和“忽略”软键。现在,请忽略测试电话,然后用您刚才呼叫的同一个号码,将其输入到窗体上的文本框中,如下图所示

CallBouncer/cb3.JPG

当您第二次拨打电话时,您可能在模拟器中看不到任何明显的反应——但请继续点击屏幕顶部栏中的“未接来电”通知图标……您现在应该会看到两个未接来电——第一个是您手动测试的,第二个是我们呼叫拦截器以编程方式处理的,如下所示

CallBouncer/cb4.JPG

而且,酷的地方在于,在模拟器中运行得如此之快,想象一下它在您的设备上运行的速度有多快!除非我的手机设置为震动且放在坚硬的表面上,否则我甚至不会意识到我的呼叫拦截器刚刚拒绝了一个电话……它发生得太快了。通常的情况是,一天晚些时候,我注意到一个未接来电图标,然后点击查看……果然,那里有一个 800 号码。

关于这个项目的几点最后说明……

那么,当您以编程方式按下手机上的忽略按钮时,到底发生了什么?在我的例子中,它会将呼叫者转到语音信箱——但这里的诀窍是,我故意不设置我的账户语音信箱(我有一个可用的,只是从未设置过),所以他们只会收到一条消息,说当前用户没有配置语音信箱——再见。在您的例子中,您可能已经设置了语音信箱,在这种情况下,您以后可能会收到语音信箱通知。

另外——在这个项目中,我提到了拦截“800”号码,我的手机现在可以做到这一点。然而,这个例子将其限制为仅仅在文本框中进行单个号码的比较,而不是使用某种匹配(提示:使用正则表达式进行 800 号码的**阻止表达式**)。我将留给读者来解决这个问题,让他们在本文提供的基础知识之上进行成长和学习。一旦您连接到 SNB 并处理了呼叫,后续的操作就取决于您了。

哦——还有关于那个俄亥俄州女士几个月来反复打我电话的事。她第一次打电话时,我接了,因为我确实有一些来自俄亥俄州的朋友在那里保留了他们的手机号码。当她找一个我明显不认识的人时,我告诉她打错了,几分钟后她又打来了。情况一样——还是打错了。我烦了,就把号码保存在了联系人列表里,叫“俄亥俄错号”。几天后,我再次看到那个号码来电,这次我接了,并说:“俄亥俄电信错号部,请问有什么可以帮您?”。接下来的对话是这样的:

:“我想联系 Sara,电话是 (555) 555-1212(*号码已隐藏以保护隐私*)。”

:“抱歉——您打错了,是 (111) 111-1111 (*我的号码已隐藏,所以不必将您中的许多人添加到我的拦截呼叫应用程序中!*)。要联系 Sara,您需要挂断电话并拨打 (555) 555-1212。”

:“好的,谢谢!”

然后,我想知道她什么时候才会发现这个交易中的漏洞。不管怎样——她从未发现。在接下来的几个月里,她偶尔还会继续打电话,我也会继续以“错号部”的身份接听。偶尔,当她打电话来时,我会在朋友们在场,我也会让他们充当“错号部”。去年晚些时候,她终于停止给我打电话了。现在,我把她添加到我手机上的应用程序的呼叫拦截列表中了!

掌控您的手机——夺回对您手机的控制权 - CodeProject - 代码之家
© . All rights reserved.