热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

WM有约II(五):区别对待不同的手机号码

WM有约II(五):区别对待不同的手机号码WrittenbyAllenLee不要删除我的短信息!试想一下,某天

WM有约II(五):区别对待不同的手机号码

 

Written by Allen Lee

 

不要删除我的短信息!

试想一下,某天你的朋友给你发了下面这条短信息:

在干嘛呢?早上收到你的东西了,今晚有空出来聊聊吗?

而此时应用程序正在运行,将会发生什么事呢?没错,你的朋友将会收到自动回复,但是,你却永远看不到这条短信息,因为它已经被删除了。能够想象吗,在某些情况下,错过上面这条短信息可能会引发一些不必要的误会……

为此,我们需要区分默认的查询短信息和自定义的查询短信息,前者在处理后应该自动删除,而后者则应该保留。因为默认的查询短信息都是以"{Trombone:"开头的,所以我们只需一个MessageInterceptor就可以截获所有默认的查询短信息了:

020809_0654_WMII1.png

代码 1

在继续之前,我要就某些类型的命名变更说明一下,首先是IInterceptionProcessor接口重命名为ISmsProcessor,它的Process方法的sms参数类型改为SmsMessage;接着是InterceptionManager类重命名为InterceptorManager,里面的m_InterceptionProcessors私有成员重命名为m_SmsProcessors。

在代码1里,我们需要从截获的短信息中提取出短信息处理器的名字,获取对应的短信息处理器对象,然后把短信息交由它处理,其中,提取名字的工作由ExtractSmsProcessorName方法负责:

020809_0654_WMII2.png

代码 2

至于自定义的查询短信息,我们仍然通过配置文件来存放MessageInterceptor的配置信息(旧的配置信息可以扔了):

020809_0654_WMII3.png

代码 3

这些MessageInterceptor的创建和之前的(参见《WM有约II(二):持续改进》的代码2)一样,除了InterceptionAction属性的值需要改为InterceptionAction.Notify,这样,自定义的查询短信息就不会被删除了。

好了,现在用Cellular Emulator发送一个短信息看看:

020809_0654_WMII4.png

图 1

嗯,自动回复功能正常,再来看看短信息有没有保留下来:

020809_0654_WMII5.png

图 2

很好!这样我们就不会错过任何重要的信息了。

 

这是谁的手机号码?

到目前为止&#xff0c;无论谁发送查询短信息&#xff0c;应用程序都会自动回复&#xff0c;这样不好&#xff0c;我希望应用程序忽略陌生的手机号码&#xff0c;即如果发送查询短信息的人不在我的联系人里&#xff0c;就不要回复了。那么&#xff0c;如何判断某个人是否在我的联系人里呢&#xff1f;我们可以通过SmsMessage.From属性获取一个Recipient对象&#xff0c;它存储了发送方的信息&#xff0c;包括发送方的姓名&#xff08;Recipient.Name属性&#xff09;和地址&#xff08;Recipient.Address属性&#xff09;。Recipient.Address属性的值可能是一个手机号码&#xff08;例如&#43;8613713149394&#xff09;&#xff0c;也可能是一个由姓名和手机号码组合而成的字符串&#xff08;例如"Stephen Chou" <&#43;8613713149394>&#xff09;&#xff0c;这取决于发送方是否在联系人里&#xff0c;所以你不能简单地把它的值和Contact.MobileTelephoneNumber属性的值进行比较。Recipient.Name属性的值可能是一个手机号码&#xff0c;也可能是一个姓名&#xff0c;当发送方不在联系人里时&#xff0c;它的值就是发送方的手机号码&#xff0c;而当发送方已在联系人里时&#xff0c;它的值则和Contact.FileAs属性的值相等&#xff0c;所以我们可以考虑把Recipient.Name属性的值和Contact.FileAs属性的值进行比较。据此&#xff0c;我们可以通过如下代码判断发送方是否在联系人里&#xff1a;

020809_0654_WMII6.png

代码 4

当应用程序截获一条查询短信息时&#xff0c;它首先要判断发送方是否有权执行查询操作&#xff0c;如果没有&#xff0c;忽略请求&#xff0c;否则&#xff0c;获取查询结果&#xff0c;然后回复发送方&#xff0c;整个过程如下图所示&#xff1a;

020809_0654_WMII7.png

图 3

不同的查询操作只有中间那步是不同的&#xff0c;于是&#xff0c;我们不妨考虑在ISmsProcessor接口和PingStatusProcessor类、PingScheduleProcessor类之间添加一个SmsProcessorBase抽象类&#xff1a;

020809_0654_WMII8.png

图 4

SmsProcessorBase.Process方法负责定义逻辑框架以及实现IsAuthorized和SendResponse两个方法&#xff1a;

020809_0654_WMII9.png

代码 5

剩下的就是处理PingStatusProcessor类、PingScheduleProcessor类和SmsProcessorBase抽象类之间的继承关系了……

不知不觉又到了测试的时候了&#xff0c;首先准备若干联系人&#xff1a;

020809_0654_WMII10.png

图 5

接着&#xff0c;通过Cellular Emulator使用如下手机号码发送查询短信息&#xff1a;

  • 15933449394
  • 13122113344

只有第一个手机号码得到自动回复&#xff0c;第二个已被忽略了&#xff1a;

020809_0654_WMII11.png

图 6

 

谁查询过我的状态/安排&#xff1f;

到目前为止&#xff0c;查询短信息的截获和状态/安排的自动回复都是应用程序悄悄完成的&#xff0c;我们无从得知背后究竟发生了什么事情。人有时候很矛盾&#xff0c;一方面希望事情最好能够自动完成&#xff0c;另一方面又害怕自动化会把控制权夺走。自动化可以解放我们的注意力&#xff0c;但同时也会产生认知空白&#xff0c;从而导致情绪上的焦虑。于是&#xff0c;我们不难想象&#xff0c;故事的发展会产生一个新的需求——告诉我谁查询过我的状态/安排以及应用程序如何处理每个查询请求。不用我说你也知道&#xff0c;这个需求会导致用户界面的改变&#xff08;下面那个灰色方框是DataGrid控件&#xff09;&#xff1a;

020809_0654_WMII12.png

图 7

这些历史纪录将会存储在InterceptionHistory.xml里&#xff0c;这个文件的内容结构如下所示&#xff1a;

020809_0654_WMII13.png

代码 6

其中&#xff0c;每个interception元素将会对应一个Interception对象&#xff0c;它的定义如下&#xff1a;

020809_0654_WMII14.png

代码 7

历史纪录的管理是由InterceptionHistory类来负责的&#xff0c;因为它的实现方式基本上是照搬StatusTextManager的&#xff08;包括应用Singleton模式和使用BindingList集合&#xff09;&#xff0c;所以我就不在这里重复整个实现细节了。

那么&#xff0c;我们应该在什么时候添加历史纪录&#xff1f;想想看&#xff0c;什么时候我们能够得到一条纪录所需的全部数据&#xff1f;没错&#xff0c;答案就在SmsProcessorBase.Process方法里&#xff1a;

020809_0654_WMII15.png

代码 8

最后&#xff0c;我们只需要把InterceptionHistory.Interceptions属性&#xff08;类型为BindingList&#xff09;关联到用户界面那个灰色方框就行了&#xff1a;

020809_0654_WMII16.png

代码 9

现在&#xff0c;我们再做一次刚才那个测试&#xff0c;不过这此我们把目光投向应用程序的主界面上&#xff1a;

020809_0654_WMII17.png

图 8

嗯&#xff0c;很好&#xff0c;不过有个小小的问题&#xff0c;就是Time那列只显示日期&#xff0c;没有时间&#xff0c;我不知道如何控制DataGrid按照特定格式显示DateTime&#xff0c;有人知道怎样做吗&#xff1f;

 

你还想要什么&#xff1f;

你上次不是说还有个什么白名单吗&#xff1f;怎么我没看到&#xff1f;噢&#xff0c;是的&#xff0c;我没有忘记&#xff0c;因为那个需求将会引出一连串其它需求&#xff0c;比如说&#xff0c;执行某个查询请求需要什么权限&#xff0c;如何指定&#xff0c;发送方拥有什么权限&#xff0c;这些权限又是如何界定的等等。另外&#xff0c;陌生人似乎也比较无奈&#xff0c;因为他/她什么也不能做&#xff0c;是否应该考虑给他/她一个"注册"的机会呢&#xff1f;

转:https://www.cnblogs.com/allenlooplee/archive/2009/02/08/1386252.html



推荐阅读
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
author-avatar
201153蜡笔小新
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有