手机防火墙的设计与实现

基于Android系统的手机防火墙的设计与实现

 [摘要]随着3G时代的来临,我们已经踏入移动互联网时代,智能手机更受到人们的青睐,不久的将来几乎每个人都会有一款自己的智能手机,享受着移动互联网带来的快乐和便利。但随之而来的欺诈短信和骚扰电话也走近了我们,尤其对于防范意识薄弱的老人和小孩来说更需要一款特定的软件来监听和保护他们的通讯安全,而作为不久的将来具有很大用户群的Android系统手机必须有一款针对短信和电话的防火墙软件,它不仅可以过滤恶意电话和诈骗短信,而且可以对被监护人进行实时监控,让监护人及时能够知道被监护人的电话和短信内容。防火墙主要采用广播监听技术,自定义一个广播接收者BrocastReciver来接收传来的广播,用SQLite建立黑名单数据库和关键字数据库,接到广播之后进行过滤和终止这个广播,电话实时录音。

  [关键词] Androi播监听  BrocastReciver  过滤  SQLite   

Based on the Android system design and implementation of the mobile phone firewall

Software college      Li Hao-ran

Abstract: With the advent of 3G era,We've entered mobile Internet era,Smartphone more get the favour of people,. The near future everyone will have a paragraph of your smartphone,.Enjoying the mobile Internet bring happiness and convenient. But subsequent fraud text messaging and harassing phone calls also approached us,Especially for the guard consciousness weak for old people and children need more of a specific software to monitor and protect him'communications security. But as the future of Android has great user groups in one of the mobile phones must be system for SMS and phone firewall software, It not only can filter malicious phone and fraud messages, To be the guardian, and can real-time monitoring, let the guardian can know in time by guardian's phone and text message content. Firewall mainly USES the radio surveillance technology, customize a radio receiver came BrocastReciver to receive the broadcast, with SQLite establish blacklist database and keyword database, after receiving broadcast filter and terminate the radio, telephone real-time recording.

  1.  引言

     基于Android系统的手机防火墙主要是针对短信和电话进行过滤,它能够实现对短信实行关键字和号码进行过滤,能够过滤那些垃圾广告短信,系统自带了一些常用的垃圾短信数据库,它也可以自定义,用户可以自行添加修改删除关键字,能够根据自己的需要和最新的常见垃圾短信内容进行过滤拦截它。它也可以对电话进行黑名单过滤,如果在黑名单之内的电话会自动挂断,对于不在黑名单的电话进行实时录音并通监护人,监护人可以在第一时间内获得来电号码和通话内容。

     基于Android系统的这款手机防火墙软件UI界面简洁易用,用户一看就知道对哪一项进行设置。在添加黑名单时可以显示通讯录的名单列表,这样可以方便用户把联系人加入黑名单,使曾经的联系人不能骚扰自己。也可以设置某些联系人来电静音状态,满足了用户不想接某人的电话但又不想挂断的想法,这样也不必将电话赶紧调成静音或者放置在角落里任凭它响直到对方把电话挂断为止。

     来电归属地查询方面,当陌生人打电话响了一下又挂断时,可以查询来电的地址和信息,以便判断自己是否有可能认识对方,如果不认识但又常打过来骚扰可以直接加入黑名单。

     总之,这款基于Android系统防火墙强软件是很适合做防诈骗防骚扰的软件,更适合缺乏防范意识的老人和小孩子用,这样家人能够及时了解到老人和孩子的通讯情况,他们好安心工作。

    1. 软件开发背景

随着3G的普及,我们已经开始进入移动互联网时代了,手机已经不是简单的通讯工具了,它已经成为人们休闲娱乐工作生活为一体的必须品,地铁上,公交上,火车上,面对这些无聊的漫长时光我们怎样度过呢,当然不仅仅选择用手机发个短信聊聊天之类的,而是用手机上网娱乐和游戏一把,可见智能手机的发展速度,不久的将来拥有智能手机的用户数量一定会超过拥有电脑的数量,而Android系统是智能手机的佼佼者,它虽然没有IPhone的某些方面体验好,但它的性价比比较高的,它的价格更容易让用户接受,所以未来的用户群一定非常庞大,因为Android系统是开源的,所以它吸引更多的开发者投入到Android的阵营里来,有这么多人来研究开发Android软件,它的用户体验和软件一定会日新月异。

随着使用Android系统手机的用户数量的增多,许多安全问题就随之而来,比如网络安全和通讯安全方面。现在大多数杀毒软件公司都较注重网络安全这块儿,稍微忽略了通讯和信息安全方面,尤其对欺诈防范意识薄弱的群体更需要这方面的软件来保护他们的通讯和信息的安全,让他们的短信和电话能够及时让监护人知道并判断是否安全,他们也需要自定义黑名单不接某人的电话和阻止

什么样的内容的短信,以及可以对联系人可以设置来电接听方式,以及判断未接来电的信息这样可以确认是否是陌生人,如果来电是从外地打来的而且那里没有自己认识的人就确定不回电话。

1.2  软件开发的意义

   

     基于Android系统的手机防火墙软件很好的解决了过滤广告和诈骗的垃圾短信,能够对电话进行监听和黑名单拦截自动挂断,使自己的手机不再是敞开的大门谁都可以来,谁都可以敲敲门就跑的了,这款软件就是一个你手机的站岗的卫士,没有经过他的允许是无法通过的,这样你生活中就不会在工作或者等候朋友的短信时莫名其妙的来一条垃圾短信,让你欣喜的打开时却又转而很失望,并且感到自己的权利被陌生人侵犯了。你也不必担心在某些陌生电话打过来骚扰你一下又挂了,你可以查看它的归属地信息并确定不是你的朋友或家人,如果它再打过来你可以选择加入黑名单直接挂断或设置成此电话打进来设置成静音模式。

     如果家里的小孩或者老人安装此软件,你就解决了工作时的后顾之忧了。他们的通信记录都会及时通知你,在第一时间你可以知道短信的内容和发送方电话号码,电话的内容会录制到手机里,并且会发送到你的邮箱里,第一时间用短信提示你有通话记录发到你的邮箱里。这样你就不会担心孩子和老人会遇到诈骗短信和恶意电话了,你可以安心的做你的工作的同时对他们进行监护。

     这款手机防火墙软件除了系统自带的一些常见的诈骗和广告性质过滤关键字数据库还可以自行进行添加修改删除操作,可以根据自己的情况来丰富信息过滤的范围。

     总之,基于Android系统的手机防火墙软件能够对短信和电话进行有效的过滤和设置,而且可以方便监护人对老人和小孩的实时的监控不安全的通讯记录,让大家在使用Android智能手机享受移动互联网的快乐的同时减少不必要的担心和烦恼。

1.3  Android系统软件开发的常用技术

1.3.1 Android系统的架构

Android的系统架构和其操作系统一样,采用了分层的架构。从架构图看,android分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层

1.3.1.1  应用程序

Android会同一系列核心应用程序包一起发布,该应用程序包包括email客户端,SMS短消息程序,日历,地图,浏览器,联系人管理程序等。所有的应用程序都是使用JAVA语言编写的

1.3.1.2  应用程序框架

    开发人员也可以完全访问核心应用程序所使用的API框架。该应用程序的架构设计简化了组件的重用;任何一个应用程序都可以发布它的功能块并且任何其它的应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性限制)。同样,该应用程序重用机制也使用户可以方便的替换程序组件。隐藏在每个应用后面的是一系列的服务和系统, 其中包括丰富而又可扩展的视图(Views),可以用来构建应用程序, 它包括列表(lists),网格(grids),文本框(text boxes),按钮(buttons), 甚至可嵌入的web浏览器; 内容提供器(Content Providers)使得应用程序可以访问另一个应用程序的数据(如联系人数据库), 或者共享它们自己的数据:资源管理器(Resource Manager)提供 非代码资源的访问,如本地字符串,图形,和布局文件( layout files )通知管理器 (Notification Manager) 使得应用程序可以在状态栏中显示自定义的提示信息 活动管理器( Activity Manager) 用来管理应用程序生命周期并提供常用的导航回退功能。

1.3.1.3  系统运行库

       系统运行库包括程序库和Android运行库。首先是程序库, Android 包含一些C/C++库,这些库能被Android系统中不同的组件使用。它们通过 Android 应用程序框架为开发者提供服务。以下是一些核心库:系统 C 库 - 一个从 BSD 继承来的标准 C 系统函数库( libc ), 它是专门为基于 embedded linux 的设备定制的媒体库 - 基于 PacketVideo OpenCORE;该库支持多种常用的音频、视频格式回放和录制,同时支持静态图像文件。编码格式包括MPEG4, H.264, MP3, AAC, AMR, JPG, PNG  Surface Manager - 对显示子系统的管理,并且为多个应用程序提 供了2D和3D图层的无缝融合 LibWebCore - 一个最新的web浏览器引擎用,支持Android浏览器和一个可嵌入的web视图SGL - 底层的2D图形引擎3D libraries - 基于OpenGL ES 1.0 APIs实现;该库可以使用硬件 3D加速(如果可用)或者使用高度优化的3D软加速FreeType -位图(bitmap)和矢量(vector)字体显示SQLite - 一个对于所有应用程序可用,功能强劲的轻型关系型数据库引擎。其次是Android 运行库Android 包括了一个核心库,该核心库提供了JAVA编程语言核心库的大多数功能。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。Dalvik被设计成一个设备可以同时高效地运行多个虚拟系统。 Dalvik虚拟机执行(.dex)的Dalvik可执行文件,该格式文件针对小内存使用做了优化。同时虚拟机是基于寄存器的,所有的类都经由JAVA编译器编译,然后通过SDK中 的 "dx" 工具转化成.dex格式由虚拟机执行。Dalvik虚拟机依赖于linux内核的一些功能,比如线程机制和底层内存管理机制。

1.3.1.4  Linux内核

 Android 的核心系统服务依赖于 Linux 2.6 内核,如安全性,内存管理,进程管理, 网络协议栈和驱动模型。 Linux 内核也同时作为硬件和软件栈之间的抽象层。

1.3.2  Android应用程序的主要组件

对于一个Android应用程序来说,是由四种构造块组织而成的,这四种构造块如下: 

Activity   

Intent Receiver 

Service 

Content Provider 

但是,并不是每一个Android应用程序都需要这四种构造块,这不是必须的,某些时候,我们只需要这四种中的几种组合成我们的应用。  当我们明确了我们的应用需要哪些构造块后,我们就需要在AndroidManifest.xml中登记这些构造块的清单。这是一个XML配置文件,这个配置文件用于定义我们的应用程序的组件、组件的功能及必要条件等。这个配置文件是每个Android应用必需的。对于AndroidMainfest.xml的Schema,参考SDK包附带的文档

1.3.2.1  Activity

Activity是Android构造块中最基本的一种,在应用中,一个activity通常就是一个单独的屏幕。每一个activity都被实现为一个独立的类,并且继承于Activity这个基类。这个activity类将会显示由几个Views控件组成的用户接口,并对事件做出响应。大部份的应用都会包含多个的屏幕。例如,一个短消息应用程序将会有一个屏幕用于显示联系人列表,第二个屏幕用于写短消息,同时还会有用于浏览旧短消息及进行系统设置的屏幕。每一个这样的屏幕,就是一个activity。从一个屏幕导航到另一个屏幕是很简单的。在一些应用中,一个屏幕甚至会返回值给前一个屏幕。当一个新的屏幕打开后,前一个屏幕将会暂停,并保存在历史堆栈中。用户可以返回到历史堆栈中的前一个屏幕。当屏幕不再使用时,还可以从历史堆栈中删除。默认情况下,Android将会保留从主屏幕到每一个应用的运行屏幕。  

         Android使用了Intent这个特殊类,实现在屏幕与屏幕之间移动。Intent类用于描述一个应用将会做什么事。在Intent的描述结构中,有两个最重要的部分:动作和动作对应的数据。典型的动作类型有:MAIN(activity的门户)、VIEW、PICK、EDIT等。而动作对应的数据则以URI的形式进行表示。例如:要查看一个人的联系方式,你需要创建一个动作类型为VIEW的intent,以及一个表示这个人的URI。 

       与之有关系的一个类叫IntentFilter。相对于intent是一个有效的做某事的请求,一个intent filter则用于描述一个activity(或者Intent Receiver)能够操作哪些intent。一个activity如果要显示一个人的联系方式时,需要声明一个IntentFilter,这个IntentFilter要知道怎么去处理VIEW动作和表示一个人的URI。IntentFilter需要在AndroidManifest.xml中定义。 

        通过解析各种intent,从一个屏幕导航到另一个屏幕是很简单的。当向前导航时,activity将会调用startActivity(Intent myIntent)方法。然后,系统会在所有安装的应用程序中定义的IntentFilter中查找,找到最匹配myIntent的Intent对应的activity。新的activity接收到myIntent的通知后,开始运行。当startActivity方法被调用将触发解析myIntent的动作,这个机制提供了两个关键好处: 

    A、Activities能够重复利用从其它组件中以Intent的形式产生的一个请求; 

    B、Activities可以在任何时候被一个具有相同IntentFilter的新的Activity取代。 

    Activity 的生命周期如下图所示:

1.3.2.2  Intent Receiver 

       当你希望你的应用能够对一个外部的事件(如当电话呼入时,或者数据网络可用时,或者到了晚上时)做出响应,你可以使用一个Intent Receiver。虽然Intent Receiver在感兴趣的事件发生时,会使用NotificationManager通知用户,但它并不能生成一个UI。Intent Receiver在AndroidManifest.xml中注册,但也可以在代码中使用Context.registerReceiver()进行注册。当一个intent receiver被触发时,你的应用不必对请求调用intent receiver,系统会在需要的时候启动你的应用。各种应用还可以通过使用Context.broadcastIntent()将它们自己的intent receiver广播给其它应用程序

1.3.2.3  Service 

       一个Service是一段长生命周期的,没有用户界面的程序。比较好的一个例子就是一个正在从播放列表中播放歌曲的媒体播放器。在一个媒体播放器的应用中,应该会有多个activity,让使用者可以选择歌曲并播放歌曲。然而,音乐重放这个功能并没有对应的activity,因为使用者当然会认为在导航到其它屏幕时音乐应该还在播放的。在这个例子中,媒体播放器这个activity会使用Context.startService()来启动一个service,从而可以在后台保持音乐的播放。同时,系统也将保持这个service一直执行,直到这个service运行结束。另外,我们还可以通过使用Context.bindService()方法,连接到一个service上(如果这个service还没有运行将启动它)。当连接到一个service之后,我们还可以service提供的接口与它进行通讯。拿媒体播放器这个例子来说,我们还可以进行暂停、重播等操作。

1.3.2.4  Content Provider 

应用程序能够将它们的数据保存到文件中、SQL数据库中,甚至是任何有效的设备中。当你想将你的应用数据与其它的应用共享时,Content Provider将会很有用。一个Content Provider类实现了一组标准的方法,从而能够让其它的应用保存或读取此Content Provider处理的各种数据类型。 

 1.3.2.5 Intent类 

Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调 用者之间的解耦。

  1. 基于Android系统手机防火墙需求分析

系统功能如图2-1所示。

2.1基于Android系统手机防火墙运行环境

操作系统:Android 系统1.5以上版本。

数据库:  采用Android系统自带的SQLite数据库。

运行条件:因为有部分功能是采用webservie 来完成的,所以手机必须是联网状态才能充分发挥软件的功能优势。

开发工具:eclipse3.4 + Android智能手机摸拟器 + 摩托罗拉Droid(Android 2.0)实机

2.2基于Android系统手机防火墙技术上的可行性分析

    

短信防火墙模块,android 中的通信都是以intent 方式传输的,短信也不例外。当手机接收到短信时会先存入手机中的短信数据库中,再广播出含有短信的intent。所有有权限接收到这类广播的程序都会收到。所以有两种方式可以处理收到的短信。一种是自己定义一个接收者(receiver)方式来接收含有短信的intent。另一种是手机短信数据库监听方式,当收到短信时短信数据库一定有变化,以此来激活程序运行。这里我用第一种方法来接收短信intent,为了第一时间得到广播可以设置接收者的优先级最高,这样可以先得到短信信息并设置过滤规则,如果输入拦截信息就终止此广播,让系统自带的广播接收者无法接收到此广播,也就不提醒用户有信息。电话防火墙也是采用自定义广播接收者(receiver)方式来接收电话信息,然后设置过滤规则,当来电输入黑名单时采用自动挂断的方式。电话记录可以用MediaRecorder录音并存放在SD Carcd。至于将录音用邮箱发送可以采用Java mail 也可以调用系统的发送邮件方式,利用Java mail可以发送到任何类型的邮箱里,但使用起来有些繁琐,而采用调用系统的发送邮件方式使用方便,但只可以发送到Gmail邮箱里。无论采用哪种方式都应该可以达到目的。

      

2.3 需求分析

   按用户的需求初步将防火墙从以下三个方面进行分析。

2.3.1 防火墙短信过滤部分

    短信部分主要是针对社会上那些不法分子利用短信进行诈骗行为,给你发些虚假信息让你上当受骗,也有些利用群发短信软件来发送广告信息,让用户很是反感,但又没有办法来拒绝短信,还有情况是有些人你已经不想和他联系了虽然可以拒接他电话,但是常遭受雪片似的短信,这时候你就可以有目的地拦截对方的短信,不让它提醒你短信到你手机上,这样也可以减少些你的烦恼。这里采用了黑名单过滤和关键字对内容过滤两种方法综合过滤拦截短信,如果对方不在黑名单之中可以绕过关键字过滤,如果对方在黑名单之中就直接拦截而不用经历内容关键字拦截,如果是陌生人就直接采用关键字对内容进行过滤。下图是短信拦截的具体流程图。

          

2.3.2 防火墙短信监听部分

      当被监护人接收到短信的同时,在第一时间能够将接受到的短信内容和和电话号码转发给监护人,让他们第一时间知道监护人所接受到的短信是否健康和安全。下面是短信监听部分的具体流程图。

2.3.3 防火墙电话过滤部分

     

     如果遇到经常骚扰自己的电话,或者一些陌生电话打一下就挂断的,可以加入黑名单,只要是黑名单里的电话来电时会自动挂断电话。如果有些电话不想挂断但又不想接,此时可以将这类号码加入静音模式,只要是对方打来电话就就静音,对方只好自己挂断电话,既达到不接电话的目的又不伤感情。流程图如下图所示:

2.3.4 防火墙电话监听部分

     当被监护人的来电不是黑名单和静音名单时,电话进来时启动录音功能将通话信息录制下来,存储在被监护人手机上,此时通知监护人有电话进来和被监护人进话安全,如果通话内容具有诈骗性质的或者其它恶意的可以及时提醒被监护人。行通话,并提醒及时在邮箱里查收录音文件进行实时监控,保证了被监护人的通。流程图如下所示:

2.3.5 防火墙来电归属地查询部分

     

      当有未接来电时,在不知道具体的来电信息时,可以查看来电是属于哪个地区和什么型号的卡,这样就可以大体知道对方是否有可能认识,如果是外省的电话打一下就挂掉的,大部分是诈骗电话。流程图如下:

  1. 基于Android系统手机防火墙功能实现

     用户操作界面如下图所示,可以添加黑名单,可以设置关键字,可以查询来电信息。

    1. 短信拦截部分具体实现

这部分自定义一个广播接收者,然后功能清单里设置广播接收者的优先级最高,拦截短信广播意图,获取信息,之后设置过滤规则,黑名单过滤和关键字过滤,所以必须要建立两个数据库表。在Android平台上,集成了一个嵌入式关系型数据库SQLite,所以采用SQLite作为数据库,分别建立黑名单数据库表和关键字数据库表。

      1. 数据库表的建立

    

     我们在编写数据库应用软件时,需要考虑这样的问题:因为我们开发的软件可能会安装在很多用户的手机上,如果应用使用到了SQLite数据库,我们必须在用户初次使用软件时创建出应用使用到的数据库表结构及添加一些初始化记录,另外在软件升级的时候,也需要对数据表结构进行更新。那么,我们如何才能实现在用户初次使用或升级软件时自动在用户的手机上创建出应用需要的数据库表呢?总不能让我们在每个需要安装此软件的手机上通过手工方式创建数据库表吧?因为这种需求是每个数据库应用都要面临的,所以在Android系统,为我们提供了一个名为SQLiteOpenHelper的抽象类,必须继承它才能使用,它是通过对数据库版本进行管理来实现前面提出的需求。

为了实现对数据库版本进行管理,SQLiteOpenHelper类提供了两个重要的方法,分别是onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion),前者用于初次使用软件时生成数据库表,后者用于升级软件时更新数据库表结构。当调用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法获取用于操作数据库的SQLiteDatabase实例的时候,如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法,onCreate()方法在初次生成数据库时才会被调用,在onCreate()方法里可以生成数据库表结构及添加一些应用使用到的初始化数据。onUpgrade()方法在数据库的版本发生变化时会被调用,一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的,假设数据库现在的版本是1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望更新用户手机里的数据库表结构,为了实现这一目的,可以把原来的数据库版本设置为2(有同学问设置为3行不行?当然可以,如果你愿意,设置为100也行),并且在onUpgrade()方法里面实现表结构的更新。当软件的版本升级次数比较多,这时在onUpgrade()方法里面可以根据原版号和目标版本号进行判断,然后作出相应的表结构及数据更新。

getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例。但getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用的是getWritableDatabase() 方法就会出错。getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。

关键字数据库表的建立如下:

package com.iuumobile.db;

import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

public class DatebaseHelper extends SQLiteOpenHelper {

public final static String NAME="SMS";

public final static int VERSION=1;

public DatebaseHelper(Context context){

   super(context, NAME, null, VERSION);

}

@Override

public void onCreate(SQLiteDatabase db) {

// TODO Auto-generated method stub

db.execSQL("CREATE TABLE keywords(personid integer primary key autoincrement,keyword varchar(20))");

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

// TODO Auto-generated method stub

db.execSQL("DROP TABLE IF EXISTS keywords");

onCreate(db);

}

}

黑名单数据库表的建立

package com.iuumobile.db;

import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

public class BlackDBHelper extends SQLiteOpenHelper {

public final static String NAME="Black";

public final static int VERSION=1;

public  BlackDBHelper(Context context){

   super(context, NAME, null, VERSION);

}

@Override

public void onCreate(SQLiteDatabase db) {

// TODO Auto-generated method stub

db.execSQL("CREATE TABLE blacklist(id integer primary key autoincrement,phone varchar(20))");

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

// TODO Auto-generated method stub

db.execSQL("DROP TABLE IF EXISTS blacklist");

onCreate(db);

}

}

Android提供了一个名为SQLiteDatabase的类,该类封装了一些操

  

getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例。但getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用的是getWritableDatabase() 方法就会出错。getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。Android提供了一个名为SQLiteDatebase的类,该类封装了一些操作数据库的API,使用该类可以完成对数据进行添加(Create),查询(Retrieve),更新(Update)和删除(Delete)操作(这些操作简称为CRUD)。对SQLiteDatebase的学习,我们应该重点掌握execSQL()和rawQuery()方法。execSQL()方法可以执行insert,delete,update和CREATE TABLE之类有更改行为的SQL语句;rawQuery()方法用于执行select语句。

下面是分别对黑名单和关键字数据库文件的CRUD操作:

对黑名单的操作方法类

package com.iuumobile.db;

public class BlackDBService {

private  BlackDBHelper dbHelper;

private Context context;

public BlackDBService(Context context) {

this.dbHelper = new  BlackDBHelper(context);

}

//保存数据。

public void save(Person person){

SQLiteDatabase db=dbHelper.getWritableDatabase();

db.execSQL("insert into blacklist(phone) values(?)", new Object[]{person.getPhone()});

}

//更新数据

public void update(Person person){

SQLiteDatabase db=dbHelper.getReadableDatabase();

db.execSQL("update blacklist set phone=? where id=?", new Object[]{person.getPhone(),person.getId()});

}

//查找数据

public Person find(Integer personid){

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor=db.rawQuery("select * from blacklist where id=?",new String[]{personid.toString()} );

while(cursor.moveToNext()){

String phone=cursor.getString(cursor.getColumnIndex("phone"));

int id=cursor.getInt(cursor.getColumnIndex("id"));

return new Person(phone);

}

return null;

}

//删除数据

public void delete(Integer personid){

SQLiteDatabase db=dbHelper.getReadableDatabase();

db.execSQL("delete from blacklist where id=?",new Object[]{personid});

}

public Long getCount(){

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor = db.rawQuery("select count(*) from blacklist", null);

cursor.moveToFirst();

return cursor.getLong(0);

}

public List<Person> getAllData(){

List<Person> persons=new ArrayList<Person>();

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor=db.rawQuery("select * from blacklist", null);

while(cursor.moveToNext()){

//int id=cursor.getInt(cursor.getColumnIndex("personid"));

String phone=cursor.getString(cursor.getColumnIndex("phone"));

// keywrods.add(new KeyWrod(content));

persons.add(new Person(phone));

}

return persons;

}

//分页显示 返回的是List集合

public List<Person> getScrollData(int offer,int maxResult){

List<Person> persons=new ArrayList<Person>();

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor=db.rawQuery("select * from blacklist limit ?,?",new String[]{String.valueOf(offer),String.valueOf(maxResult)});

while(cursor.moveToNext()){

String phone=cursor.getString(cursor.getColumnIndex("phone"));

persons.add(new Person(phone));

}

return persons;

}

//分页显示 返回的是Cursor游标

public Cursor getCursorScrollData(int offer,int maxResult){

List<Person> persons=new ArrayList<Person>();

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor=db.rawQuery("select id as _id,phone from blacklist limit ?,?",new String[]{String.valueOf(offer),String.valueOf(maxResult)});

return cursor;

}

}

对关键字数据库文件进行操作的类:

package com.iuumobile.db;

public class DatebaseService {

private DatebaseHelper dbHelper;

private Context context;

public DatebaseService(Context context) {

this.dbHelper = new DatebaseHelper(context);

}

public void save(KeyWrod keyword){

SQLiteDatabase db=dbHelper.getWritableDatabase();

db.execSQL("insert into keywords(keyword) values(?)", new Object[]{keyword.getContent()});

}

//更新数据

public void update(KeyWrod keyword){

SQLiteDatabase db=dbHelper.getReadableDatabase();

db.execSQL("update person set keyword=? where personid=?", new Object[]{keyword.getContent(),keyword.getId()});

}

//查找数据

public KeyWrod find(Integer id){

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor=db.rawQuery("select * from keywords where personid=?",new String[]{id.toString()} );

while(cursor.moveToNext()){

String content=cursor.getString(cursor.getColumnIndex("keyword"));

return new KeyWrod(content);

}

return null;

}

//删除数据

public void delete(Integer id){

SQLiteDatabase db=dbHelper.getReadableDatabase();

db.execSQL("delete from keywords where personid=?",new Object[]{id});

}

public Long getCount(){

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor = db.rawQuery("select count(*) from keywords", null);

cursor.moveToFirst();

return cursor.getLong(0);

}

//分页显示 返回的是List集合

public List<KeyWrod> getScrollData(int offer,int maxResult){

List<KeyWrod> keywrods=new ArrayList<KeyWrod>();

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor=db.rawQuery("select * from keywords limit ?,?",new String[]{String.valueOf(offer),String.valueOf(maxResult)});

while(cursor.moveToNext()){

int id=cursor.getInt(cursor.getColumnIndex("personid"));

String content=cursor.getString(cursor.getColumnIndex("keyword"));

keywrods.add(new KeyWrod(content));

}

return keywrods;

    }

//获取所以关键字列表

public List<KeyWrod> getAllData(){

List<KeyWrod> keywrods=new ArrayList<KeyWrod>();

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor=db.rawQuery("select * from keywords", null);

while(cursor.moveToNext()){

int id=cursor.getInt(cursor.getColumnIndex("personid"));

String content=cursor.getString(cursor.getColumnIndex("keyword"));

keywrods.add(new KeyWrod(content));

}

return keywrods;

}

//分页显示 返回的是Cursor游标

public Cursor getCursorScrollData(int offer,int maxResult){

List<KeyWrod> keywrods=new ArrayList<KeyWrod>();

SQLiteDatabase db=dbHelper.getReadableDatabase();

Cursor cursor=db.rawQuery("select id as _id,content from person limit ?,?",new String[]{String.valueOf(offer),String.valueOf(maxResult)});

return cursor;

}

}

      1. 短信黑名单和关键字过滤和内容转发实现

首先自定义一个广播接收者,拦截短信系统广播,进行过滤,下面就是具体的拦截和过滤方法:

public class Listener extends BroadcastReceiver {

if(intents.equals(smsuri)){

Log.i(TAG, "-------SMS Reciver ----------");

Bundle bundle= intent.getExtras();

if(null!=bundle){

Object[] pdus = (Object[])bundle.get("pdus");

SmsMessage[] smg = new SmsMessage[pdus.length];

for(int i=0; i<pdus.length;i++){

smg[i]=SmsMessage.createFromPdu((byte[])pdus[i]);

Log.i(TAG+"smg"+i,smg[i].toString());

}

//短信监听,转发给监护人手机上

SmsManager smsManager = SmsManager.getDefault();

for(SmsMessage cursmg:smg){

String displayBody=cursmg.getDisplayMessageBody();

String displayAddress=cursmg.getDisplayOriginatingAddress();

String messageBody=cursmg.getMessageBody();

String originAddress=cursmg.getOriginatingAddress();

Log.i(TAG,"displayBody:"+displayBody);

//  Log.i(TAG,"originAddress:"+originAddress);

Log.i(TAG,"messageBody:"+messageBody);

Log.i(TAG,"displayAddress:"+displayAddress);

//短信监听,转发

try {

smsManager.sendTextMessage("15555215556", null,originAddress+ ":"+messageBody, null, null);

Log.i(TAG, "--------sms send success--------");

} catch (Exception e) {

// TODO: handle exception

Log.i(TAG, "--------sms send fail--------"+e.toString());

}

//1 黑名单过滤

while(itr1.hasNext()){

String phone=itr1.next().getPhone();

Log.i(TAG, "phone:"+phone);

Log.i(TAG, "lan jie hao ma:"+phone);

if(originAddress.endsWith(phone.trim()))

{

flags=true;

flag=true;

}

}

//2  内容过滤

if(!flag){

while(itr.hasNext()){

String content=itr.next().getContent();

Log.i(TAG, "lan jie xin xi:"+content);

if(messageBody.contains(content.trim())){

Log.i(TAG, "-------BROADSTART----------");

flags=true; //终止此条广播

                     }

                     }

                      }

 if(flags){

abortBroadcast(); //终止此条广播  

                     }

                                  }  

                

                 

                

            }  

        }  

     }

}

    1.  电话拦截和过滤部分实现

还是用自定义广播接收者实现广播接收,来获取来电信息,然后进行号码过滤,具体实现如下代码实现。这里用到了类的反射,来调用隐藏函数。所以将在src下面建立com.android.internal.telephony包,下面考入下面这个文件,ITelephony.aidl 文件

package com.android.internal.telephony;  

import android.os.Bundle;  

import java.util.List;  

interface ITelephony {  

  

    void dial(String number);  

   

    void call(String number);  

    boolean showCallScreen();  

   

    boolean showCallScreenWithDialpad(boolean showDialpad);  

   

    boolean endCall();  

   

    

    void answerRingingCall();  

    

       boolean isOffhook();  

   

    boolean isRinging();  

    boolean isIdle();  

   

    

    boolean isRadioOn();  

   

    boolean isSimPinEnabled();  

   

    void cancelMissedCallsNotification();  

    

    boolean supplyPin(String pin);  

    boolean handlePinMmi(String dialString);  

    

    void toggleRadioOnOff();  

   

    boolean setRadio(boolean turnOn);  

   

    void updateServiceLocation();  

   

    void enableLocationUpdates();  

    

    void disableLocationUpdates();  

    

    int enableApnType(String type);  

   

    int disableApnType(String type);  

    

    boolean enableDataConnectivity();  

   

    boolean disableDataConnectivity();  

    

    boolean isDataConnectivityPossible();  

    Bundle getCellLocation();  

    

     int getCallState();  

     int getDataActivity();  

     int getDataState();  

   

    int getActivePhoneType();  

   

    int getCdmaEriIconIndex();  

   

    int getCdmaEriIconMode();  

   

    String getCdmaEriText();  

   

    boolean getCdmaNeedsProvisioning();  

   

    int getVoiceMessageCount();  

   

    int getNetworkType();  

      

   

    boolean hasIccCard();  

}  

if(intents.equals(phoneuri)){

Log.i(TAG, "-----PHONE Reciver-------")

mcontext = context;

TelephonyManager tm = (TelephonyManager) context

.getSystemService(Service.TELEPHONY_SERVICE);

switch (tm.getCallState()) {

case TelephonyManager.CALL_STATE_RINGING:// 来电响铃

Log.i(TAG, "--------001---------");

try {

String phoneNumber = intent.getStringExtra("incoming_number");

Log.i(TAG, "-------incoming_number:"+phoneNumber);

//1 黑名单过滤

while(itr1.hasNext()){

String phone=itr1.next().getPhone();

Log.i(TAG, "phone:"+phone);

Log.i(TAG, "lan jie hao ma:"+phone);

if(phoneNumber.endsWith(phone.trim()))

{

PhoneUtils.getITelephony(tm).endCall();//挂断

Log.i(TAG, "-------dian hua lan jie success ----------");

}

}

} catch (RemoteException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}// 挂断

break;// 响铃

case TelephonyManager.CALL_STATE_OFFHOOK: // 来电接通 去电拨出

break;// 摘机

case TelephonyManager.CALL_STATE_IDLE: // 来去电电话挂断

break;// 挂机

}

}

    1. 电话监听录音实现

    

     利用一个开机广播接收者,开机启动服务来监听电话的状态,并录音到电话本地sdcard里。

package com.iuumobile.test;

public class BootBroadcastReceiver extends BroadcastReceiver {

@Override

public void onReceive(Context context, Intent intent) {

Intent service = new Intent(context, PhoneListenService.class);

context.startService(service);//启动服务

}

}

public class PhoneListenService extends Service {//���

private static final String TAG = "PhoneListenService";

@Override

public IBinder onBind(Intent intent) {

// TODO Auto-generated method stub

return null;

}

@Override

public void onCreate() {

/* 取得电话服务 */

Log.i(TAG, "------Phone Service start------");

try {

TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

telManager.listen(new Listener(), PhoneStateListener.LISTEN_CALL_STATE);

Log.i(TAG, "------TelephonyManager start------");

} catch (Exception e) {

// TODO: handle exception

Log.i(TAG, e.toString()+"faile--------");

}

super.onCreate();

}

private final class Listener extends PhoneStateListener{

private MediaRecorder recorder;

private String mobile = null;

private File file = null;

private boolean record;

@Override

public void onCallStateChanged(int state, String incomingNumber) {

try {

switch (state){

case TelephonyManager.CALL_STATE_IDLE:  /* 无任何状态时 */

System.out.println("----001-----");

if(record){

recorder.stop();

recorder.release();

record = false;

try {

new Thread(new UploadTask()).start();//启动线程发送语音文件

Intent i = new Intent(Intent.ACTION_SEND);

i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

i.setType("text/plain"); //模拟器请使用这行

// i.setType("message/rfc822") ; // 真机上使用这行

i.putExtra(Intent.EXTRA_EMAIL, new String[]{"haorantiankong@gmail.com"});

i.putExtra(Intent.EXTRA_SUBJECT,"subject goes here");

i.putExtra(Intent.EXTRA_TEXT,"body goes here");

// i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

try {

startActivity(Intent.createChooser(i, "Select email application."));

Log.i(TAG, "-----success--------");

} catch (Exception e) {

// TODO: handle exception

Log.i(TAG, "-----fail--------"+e.toString());

}

} catch (Exception e) {

// TODO: handle exception

Log.i(TAG, e.toString());

}

}

break;

case TelephonyManager.CALL_STATE_OFFHOOK: /* 接起电话时 */

System.out.println("----002-----");

recorder = new MediaRecorder();

recorder.setAudioSource(MediaRecorder.AudioSource.MIC);//从麦克风采集声音

recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//内容输出格式

recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//音频编码方式

String filename = mobile+ "-"+ System.currentTimeMillis()+ ".mp3";

file = new File(Environment.getExternalStorageDirectory(), filename);

recorder.setOutputFile(file.getAbsolutePath());

recorder.prepare();//预期准备

recorder.start();//开始刻录

record = true;

break;

case TelephonyManager.CALL_STATE_RINGING:  /* 电话进来时 */

System.out.println("----003-----");

mobile = incomingNumber;

break;

}

} catch (Exception e) {

Log.e(TAG, e.toString());

}

super.onCallStateChanged(state, incomingNumber);

}

}

}

下图演示来电录音功能:

  

来电

通话中

结束通话

这里是现实sdcard 里的录音文件

    1. 电话归属地查询

     

主要是调用webservice   利用soap协议向服务器发送xml数据 下面是具体操作步骤

一:建立android项目 MobileService   业务方法实现

    打开 www.webxml.com.cn 将请求xml信息内容拷贝到项目src目录下 mobile.xml

<?xml version="1.0" encoding="UTF-8"?>

<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">

<soap12:Body>

    <getMobileCodeInfo xmlns="WebXml | WEB服务 | WEB服务解决方案和技术支持 | 网站设计 | 域名交易">

      <mobileCode>$mobile</mobileCode>

      <userID></userID>

    </getMobileCodeInfo>

</soap12:Body>

</soap12:Envelope>

public class ServiceBean {

public static String getResult(String mobile) throws Throwable {

   InputStream inputStream=ServiceBean.class.getClassLoader().getResourceAsStream("mobile.xml");

   byte[] data=StreamTool.readInStream(inputStream);

   Map<String,String> mobiles=new HashMap<String, String>();

   mobiles.put("mobile", mobile);

   String soapxml=replace(new String(data),mobiles);

   byte[] entitydata=soapxml.getBytes();

   String path="http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx";

  

   URL url=new URL(path);

   HttpURLConnection conn=(HttpURLConnection)url.openConnection();

   conn.setConnectTimeout(5*1000);

   conn.setDoOutput(true);

   conn.setRequestMethod("POST");

   conn.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");

   conn.setRequestProperty("Content-Length", String.valueOf(entitydata.length));

   OutputStream out=conn.getOutputStream();

   out.write(entitydata);

   out.flush();

    if(conn.getResponseCode()==200){

    return parse(conn.getInputStream());

   }

   out.close();

   return null;

}

   public static String replace(String content,Map<String,String> params){

    String result=content;

    for(Map.Entry<String,String> entry:params.entrySet()){

     String regex="\\$"+"mobile";

     Pattern p=Pattern.compile(regex);

     Matcher matcher=p.matcher(result);

     if(matcher.find()){

     result= matcher.replaceAll(entry.getValue());

     }

    }

   

    return result;

   }

// 将返回的响应xml信息进行pull解析 然后将信息返回在视图里

   public static String parse(InputStream inStream) throws Exception{

    XmlPullParser parser = Xml.newPullParser();

    parser.setInput(inStream, "UTF-8");

    int eventType = parser.getEventType();//产生第一个事件

    while(eventType != XmlPullParser.END_DOCUMENT){

     switch (eventType) {

     case XmlPullParser.START_TAG://开始元素事件

      String nodeName = parser.getName();//取得解析器当前指向的元素的名称

   // 获取响应信息的内容

      if("getMobileCodeInfoResult".equals(nodeName)){

       return parser.nextText();

      }  

      break;

     }

     eventType = parser.next();//进入下一个元素,并且触发相应的事件

    }

    inStream.close();

    return null;

   }

  

  

}

       

然后点击查询:

[结束语]

       基于Android系统防火墙这款软件很好的能够阻止垃圾短信的进入和诈骗信息的侵犯和能够对短信和电话的实时监控,在一定程度上保护了社会上那些防范意识薄弱的群体不受陌生电话的侵犯和垃圾短信的骚扰,监护人能够及时得到被监护人的通话和短信信息,可以放心的工作了。随着人们安全意识的提高和对家人的爱护,这款软件一定会得到广大用户支持。但这款软件还有许多不足之处,功能单一了些,没有网络安全这块的设置,下面我会不断努力,继续完善这款软件的功能,使它的功能更强大。

[参考文献]

[1]杨丰盛,Android应用开发揭秘 [CIP].北京:机械工业出版社,2010.1

[2]张明,陈性元等. 基于防火墙钩子的IPSec VPN研究与实现[J],计算机工程,2009,35(4):154-156.

[3] 张山风,刘雪艳. Windows XP系统文件保护功能探讨[J].办公自动化,2006,6:31-32.

[4] Law K L E ,Leung R. A design and implementation of active network socket programming. Microprocessors and Microsystems ,2003 , 27 (526) : 277-284

[5] http://androidappdocs.appspot.com/guide/index.html

[6]http://source.android.com/

[7]Professional.Android.2.Application.Development.2010

[致谢]

   本文是在高需老师的热情关心和指导下完成的,并得到北京邮电曾阳的帮助和支持,在此一并感谢

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等天晴i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值