基于Android的手机安全卫士的开发
开发环境
处理器:Intel® Core™ i5-5200U CPU 2.20GHz
内存:4GB
硬盘:500GB
操作系统:Windows 7中文版,64位操作系统
开发工具:Eclipse(根据自己的使用工具写)
开发语言:Java
系统主要开发的功能如下:
(一)检查和更新版本
打开手机管家首页,会检查本地版本号与服务器端的版本号是否一致,低于服务器端的版本号提示用户更新版本,如果用户选择立即更新,应用在服务器端下载新版本,自动并安装。
(二)手机防盗
(1)密码加密
想要使用手机防盗模块需设置密码,对密码采用MD5加密算法,加密后的密码存储到配置文件。要进入此模块需要再次输入密码才可进入。
(2)SIM卡的绑定
绑定SIM卡,一旦换卡,会向安全号码发送报警短信,首先获取SIM卡序列号,然后将其写入配置文件。
(3)滑屏功能
手机防盗的几个设置界面之间的切换使用手势滑动,根据触摸位置的很坐标判断滑屏的方向。设置四个小圆点界面,滑屏时对应页面显示是,小圆点的颜色会有所变化,根据具体页面而具体变化。
(4)添加安全号码
安全号码可以手动添加,也可以获取手机联系人列表,在联系人列表中选中已有联系人进行添加,安全号码需要存入配置文件中。
(5)开启防盗功能
使用状态按钮开启防盗功能,并将开启状态存入配置文件,用于回显。
(三)通讯卫士模块
对添加到黑名单中的号码进行电话拦截、短信拦截。添加到黑名单有两种方式,一种是直接输入电话号,另一种是从联系人列表中选择。
(四)软件管家模块
获取当前手机中的所有应用,以及手机剩余内存、SD卡剩余内存,当点击某个应用时,下方会浮出一个操作条,可以管理应用启动、卸载、分享、设置。
(五)手机杀毒模块
手机杀毒模块用于全盘扫描手机程序,检测是否有病毒,如果某个程序含有病毒,应用名称会显示红色,手动卸载程序即可,如果没有病毒,则显示扫描完成。
(六)缓存清理
用于清理所有程序缓存,当扫描完所有程序后出现缓存时,可以点击“一键清理”按钮,系统会进行清理。
(七)进程管理
扫描手机正在运行的进程,并可以进行清理,可以选择清理某个进程,也可以选择清理所有进程。
(八)流量统计模块
本模块用于统计手机当月使用的流量、手机的总流量、本月手机已用的流量以及本日手机已用的流量。
(九)高级工具模块
(1)号码归属地查询
通过数据库查询出手机号码所在的城市以及运营商。
(2)短信备份和还原
将手机中的短信以XML格式保存在本地,可以通过短信还原功能将误删的短信还原到系统短信数据库中。
(3)程序锁
使用此程序给手机自动上锁。
(十)设置中心模块
用于设置黑名单的拦截,以及程序锁是否开启。
手机安全卫士主要分为九个功能模块,其中包含手机防盗、通讯卫士、软件管家、手机杀毒、缓存清理、进程管理、流量统计、高级工具、设置中心九个模块,如图3-3.1所示。
图3-3.1手机安全卫士功能模块
手机安全卫士分为两个大模块,一个是首先进入的欢迎界面,另一个界面是主界面。欢迎界面会显示系统的版本号,以及功能提示等,然后会进入主界面,主界面显示九个功能模块,每个功能模块还有具体的小功能。
4.设计和实现过程
4.1页面展示及检查和更新版本
4.1.1 欢迎页面
布局文件使用的是RelativeLayout布局,该布局中放置了ProgressBar控件和TextView控件,ProgressBar控件用于显示程序加载的进度条,TextView控件用于显示程序的版本号。
用户点击手机安全卫士此页面时,首先显示的是一个欢迎页面,本页面会展示应用的版本号。如下图4.1.1.1所示。
图4.1.1.1 欢迎页面展示
4.1.2 检查及更新版本
①本程序使用Tomcat作为服务器,因此事先需要配置好服务器。在Tomcat的webapps/ROOT文件夹下放上updateinfo.html以及手机安全卫视2.0的APK,使用xUtils下载APK,要将工具包导入工程中,用DownLoadUtils.java用于存放下载文件的工具类。
在下载APK之前需要先获取程序的版本号,当检测到本地版本号与服务器版本号不一致时,才会弹出更新提醒的对话框(如下图4.1.2.1所示),进行下载安装,本部分代码功能独立,单独创建一个工具类,将其放在MyUtils中。
图4.1.2.1 提示更新对话框
版本更新的整体逻辑代码在VersionUpdateUtils.java中,HttpGet httpGet=new HttpGet(“http://10.0.2.2:8080/updateinfo.html”);通过HttpGet请求updateinfo.hml页面,解析该页面的JSON数据,从而调用方法弹出升级对话框。升级之后页面也会发生相应的变化。
4.1.3 系统主页面
系统主页面中使用的是GridView控件,该控件是一个二维的ViewGroup,有9个页面,从而展示九宫格效果,每个Item的格式都是一样的,都由一张图片和一个标题组成。主页面效果图如图4.1.3所示。
图4.1.3 系统主页面
4.2手机防盗模块
4.2.1设置及输入密码
设置密码和输入密码大体类似,都是使用回调函数setCallBack传递MyCallBack接口,该接口中有两个方法分别用于处理确定与取消选项, public void setCallBack(MyCallBack myCallBack)
{this.myCallBack = myCallBack;}
密码使用MD5加密,因此需要将其抽取作为工具类单独存放。设置密码页面如图4.2.1.1所示。
图4.2.1.1 设置密码页面
4.2.2 手势滑动
手势滑动是在设置向导中比较核心的内容,每一个Activity都要有手势识别器,也要设置小圆点界面,当滑动到当前界面是,当前界面的小圆点会显示不同的颜色,在每个页面下方都引入此部分的代码。
界面平移效果的动画有四个,需要分别定义四个动画效果。android:duration=“1000”,表示切换动画执行时长为1000毫秒,即为1秒。用showNext()方法和showPre()方法,分别用于展示下一个和上一个页面。再用手势识别器去分析识别手势事件,开启新的activity并且关闭自己。
4.2.3 SIM卡绑定
设置向导第一个页面是单纯的展示功能,逻辑代码都比较简单,SIM卡绑定在的第二个页面, 因此进入第二个页面时,需要设置第二个小圆点的颜色与其他的不一样。使用bindSIM()方法(如图4.2.3.1所示)来绑定sim卡,if语句判断SIM是否绑定,没有绑定则获取手机的SIM卡串号,并且再存入SharedPreferences对象中。
图4.2.3.1 绑定sim卡
接下来需要创建一个Application子类App,Application用于检测SIM卡是否发生变化,当Android程序启动时,系统会创建Application对象,单例模式的一个类,需要再application标签增加name属性,并添加Application名字即可。可以将检测SIM卡是否变更的方法放在Application的onCreat()方法中。App.java中部分代码用于判断手机SIM卡是否更换,当防盗保护开启时,获取绑定的SIM卡串号,然后获取当前手机的SIM卡串号进行对比,如果一致则代表SIM卡未发生变化,如果不一致则代表SIM卡发生变化,此时需要向安全号码发送短信,提示手机SIM卡已更换。
SIM卡绑定界面如图4.2.3.2所示。
图4.2.3.2 SIM卡绑定
4.2.4 添加安全号码
设置向导的第三个页面用于选择或输入安全联系人,当手机SIM卡变更后会向安全号码发送短信通知,用showNext()方法(如图4.2.4.1所示)用于判断文本编辑框中是否输入了安全号码,号码保存在SharedPreferences对象中,然后可以进入下一个界面。
图 4.2.4.1
如果需要选择联系人,就需要有联系人信息,联系人信息都存储在SQLite数据库中,联系人的信息被封装在ContactInfo中,然后存入List集合。从数据库查询出的联系人信息,需要通过数据适配器填充到ListView中,因此需要创建一个定义联系人列表的数据适配器ContactAdapter.java中。
添加安全号码的界面如图4.2.4.2所示。
图4.2.4.2 添加安全号码界面
4.2.5 开启防盗保护
设置想到的最后一个界面是用于展示设置完成的界面,并且默认开启防盗保护功能,也可以选择关闭,是一个选择器,可以自行选择开启或关闭。当按钮为被选中事件,显示“防盗保护已开启”,按钮的状态会被存储在SharedPreferences对象中。此部分代码被在onCheckedChaged方法中(如图4.2.5.1)。
图4.2.5.1
开启防盗保护页面如图4.2.5.2所示。
图4.2.5.2 开启防盗保护页面
4.2.6防盗指令
此页面是最后设置完毕的防盗指令页面,可以控制防盗功能的开启和关闭、重新进入设置向导界面以及展示当前可以通过哪些指令来远程操纵手机。
其中isSetUp()用于获取SharedPreferences对象存入的isSetUp是否为true,可以用来判断是否设置过向导。private boolean isSetUp() {return msharedPreferences.getBoolean(“isSetUp”, false);}
为了监听安全号码发送的防盗指令,需要创建一个广播接受者SmsLostFindReciver,根据收到的防盗指令来执行不同的操作,如果防盗保护开启则可获取超级管理员权限,超级管理员才能完成远程清除数据和远程锁屏功能,此权限也需要在清单文件中配置。部分代码如图4.2.6.1所示。
图4.2.6.1
在防盗指令中也有使用到定位服务,该服务用于获取手机的经度、维度、移动速度、精确度等,因此需要创建一个GPSLocationService,需要获取系统的位置管理器,然后通过Criteria对象返回可用的位置提供者,通过lm.getBestProvider获取最好的位置提供者。另外需要定义了一个位置监听器MyListener,并实现了位置变化的四个方法,onLocationChaged()是当手机位置发生变化是调用,onStatusChanged()表示当前位置提供者可用的时候调用,onProviderEnabled()当某个位置提供者可用的时候调用的方法,onProviderDisabled()当某个位置提供者不可用的时候调用的方法。
防盗指令页面如图4.2.6.3所示。
图4.2.6.3 防盗指令页面
4.3 通讯卫士模块
通讯卫士的开发流程图有些复杂。首先进入通讯卫士界面时,会先判断是否由黑名单,如果有则在主界面中显示黑名单列表,否则会显示“您还没有添加黑名单”。而添加黑名单有两种方式:一种是直接添加;另一种是从联系人列表中选择,然后指定电话拦截或者短信拦截后添加至黑名单,添加之后黑名单信息就会展示在主页面中。
黑名单中的数据需要长期保存,要想实现黑名单拦截功能,首先需要根据需求设计一个黑名单数据库(blacknumber.db),用于存放存储黑名单中的联系人信息,BlackNumberDao是一个可以对黑名单中的数据进行增、删、改、查等操作的工具类。主界面的功能主要包含显示黑名单信息(姓名、电话以及拦截模式),点击删除按钮将从当前黑名单从界面及数据库中删除。编写主页面业务逻辑具体代码在SecurityPhoneActivity当中。部分代码如图4.3.2所示。
图4.3.2
4.3.1 通讯卫士界面
XML部分:
添加黑名单部分的布局文件主要包含两个FrameLayout布局,这两个布局分别用于显示黑名单和无黑名单的情况,当这两个布局在切换时实际上就是控制两个FrameLayout的显示与隐藏。布局下一个Button按钮,该按钮的背景图片使用了图片选择器,按钮按下与松开分别显示不同的颜色。添加黑名单部分主页面入图4.3.1.1所示。
图4.3.1.1 添加黑名单部分主页面
拦截短信和拦截电话部分布局文件的中有四个按钮,都使用了背景选择器,给每个按钮都添加一个selector。
添加黑名单部分界面如图4.3.1.2所示。
图4.3.1.2 添加黑名单部分界面
整体完成之后的界面如图4.3.1.3所示。
图4.3.1.3
4.3.2 逻辑代码部分
主界面是通过ListView显示黑名单列表的,要使用数据适配器BaseAdapter,因此需要创建数据适配器BlackContactAdapter。BlackContactAdapter()方法是用来接收两个参数,List和Context,其中List表示从主界面传递的黑名单数据集合,从而加载到页面上的数据都从该集合中取出。
而当点击删除按钮后,当前条目在数据库中删除,并且页面中也会删除,刷新当前页面,删除按钮的点击事件调用的是callBack.DataSizeChanged()方法,该方法是一个回调方法,在点击删除按钮后数据库中没有数据调用。由于只有将数据库中的数据完全删除之后才调用回调函数,因此删除最后一条数据是会显示默认布局,将ListView布局隐藏,部分代码如图4.3.2.2所示。
图 4.3.2.2
添加黑名单部分中点击onClick()方法用于相应按钮的点击事件,当点击添加按钮时,首先会对输入框进行校验,只有当电话号码和姓名不为空时才可以选择拦截模式,然后消炎数据库中是否有当前号码,如果没有将其添加到黑名单中,当点击从联系人中选择按钮时,会跳转到联系人列表里面ContactSelectActivity进行选择联系人。
黑名单拦截部分分别是拦截短信和拦截电话。
拦截部分需要在广播中获取到电话号码以及短信内容,然后查询该号码是否在黑名单的数据库中,如果在,会判断是哪种拦截模式,并进行拦截。首先用if语句用于判断黑名单拦截功能是否开启,如果需要拦截,就会终止广播。电话拦截是当电话铃响是需要自动挂断电话并且不让该记录显示在界面上,需要挂断电话的操作只能通过反射获取底层服务。CallLogObserver是内容的观察者,观察系统联系人的数据库,如果呼叫的号码在黑名单中时,在系统联系人数据库中产生记录时就调用deleteCallLog()方法清除历史记录,deleteCallLog()用于清除历史记录。部分代码如图4.3.2.3所示。
图4.3.2.3
4.4软件管家模块
4.4.1 软件管家界面
软件管家主页面如图4.4.1.1所示
图4.4.1.1 软件管家主页面
软件管家界面主要使用了一个相对布局及一个帧布局,相对布局中放置了两个TextView,分别显示手机剩余内存和SD卡剩余内存信息。TextView控件使用了textview12sp样式,用于控制字体的大小,垂直居中等。软件管家Item布局使用了一个相对布局和一个线性布局,相对布局中放置了一个ImageView控件和三个TextView控件,线性布局中放置了四个TextView控件和三个View控件,当选中一个应用程序时,程序的下方会浮出一个小条目,可以进行启动、卸载、分享、设置四个选项可以对程序进行操作。
4.4.2 逻辑代码部分
首先需要获取手机中所有已经安装的程序,将所有的获取到的应用程序信息放在List集合中,在获取应用程序大小时,需要先获取到应用程序的路径,然后通过File对象获取到应用程序的大小,并存储到AppInfo对象中。而AppInfo中的对象也会添加至List集合中,然后将AppInfo对象和在为null,将之前获取到应用程序的信息删除,用于存储再次循环得到的应用程序信息。在卸载、开启等方法处理应用程序时需要获得相对应的权限。
准备工作做完之后,编写软件管家界面的逻辑代码,用if语句判断Adapter的状态,为空时创建AppManagerAdapter对象,并且将数据填充给ListView控件,更新界面,否则调用notifyDataSetChanged()更新界面。获取手机本身和SD卡内存的方法是getMemoryFormPhone()方法。还需要定义广播接收者,接收应用卸载成功的广播,当应用卸载成功后,调用initData()方法,清除数据重新加载应用列表,更新界面。部分代码如图4.4.2.1所示。
图4.4.2.1
4.5手机杀毒模块
4.5.1 手机杀毒界面
病毒查杀界面界面主要由两部分组成,界面上方用于显示病毒图标以及上次扫描病毒的时间,下方是用于显示全盘扫描病毒条目,点击该条目跳转到病毒查杀界面,主界面主要是一个线性布局内嵌套了两个相对布局,第一个相对布局中的TextView显示时间,第二个显示病毒扫描的文字提示。界面如图4.5.1.1所示。
图4.5.1.1 病毒查杀界面
查杀进度界面有三部分组成,上方按百分比显示查杀进度以及正在扫描的应用列表,中间的ListView控件展示扫描的应用列表,下方有取消按钮。此页面也使用了ListView控件,需要定义一个Item布局用于展示应用程序信息,使用两个ImageView控件和TextView控件。界面展示如图4.5.1.2所示。
图4.5.1.2 查杀进度界面
4.5.2 逻辑代码部分
由于病毒的种类十分繁多,需要使用第三方数据库anvitirus.db,复制在assets目录下,通过AntiVirusDao.java中的checkVirus()方法接收的参数为应用的MD5码,与数据库中的作比较,并且返回病毒描述信息。getFileMD5()方法接收一个应用的全路径名,最后返回该应用的MD5码。
主界面的逻辑代码需要执行数据库的复制操作,将assets目录下的数据库复制到工程目录下。onResume()方法使用SharedPreferences对象getString()方法获取Key,看是否显示上次查杀时间。查杀进度上scanVirus()是开启一个子线程,在子线程中处理扫描应用是否是病毒的操作,并将结果使用Handler发送进行处理。checkVirus()判断MD5码是否存在病毒数据库中。部分代码如图4.5.2.1所示。
图4.5.2.1
病毒查杀界面也使用了ListView控件,该控件中需要使用适配器进行填充,要定义一个数据适配器,ScanvirusAdapter类的构造方法接收一个List参数,该参数保存了已经扫描过的应用程序,最后通过getView()方法显示在ListView()的条目中。
4.6 缓存清理模块
4.6.1 缓存清理界面
缓存清理部分的界面与手机杀毒界面类似,上方的相对布局中包含一个ImageView和两个TextView控件,中间的ListView控件用于显示已扫描缓存的应用列表,下方的线性布局中放置一个Button按钮用于点击之后进行清理缓存操作。而ImageView控件使用了一个帧动画,类似GIF图片,每张图片显示0.2秒进行左右摇摆切换。
扫描缓存界面下方使用了一个ListView控件,为其定义一个Item布局,该布局中包括两个ImageView控件和两个TextView控件。第一个ImageView控件用于显示程序图标,第二个ImageView用于显示对号图标,第一个TextView用于显示程序名称,第二个TextView用于显示有多少缓存。如图4.6.1.1所示。
在缓存清理完成之后界面主要由两个帧布局组成,第一个帧布局用于展示正在清理缓存界面,第二个帧布局用于展示缓存清理完成界面。第一个帧布局中的ImageView控件使用了一个动画控制器,该选择是一个帧动画,用于控制垃圾桶图标400毫秒切换,如图4.6.1.2所示。
图4.6.1.2 清理完成后界面
4.6.2 逻辑代码部分
主界面要定义一个Handler,用于处理从initData()方法中传递的数据。首先通过formatMemory()方法格式化单位,将获得memory的值显示在桌面上,显示正在清理缓存的过程。Intent获得从上个界面传输过来的缓存总大小。initData()在onCreate()方法中调用,首先执行了cleanAll()方法清除缓存。
在清除缓存的时候使用了IpackageDataObserver.aidl接口,因此需要将其复制到android.content.pm包中。
4.7 进程管理模块
4.7.1 进程管理界面
进程管理模块主要由三个线性布局组成,第一个线性布局用于显示正在运行的进程个数、可用内存和总内存大小,第二个线性布局用于展示所有正在运行的进程流标,地三个线性布局用于展示三个按钮,分别是清理、全选、反选,这三个按钮都使用了背景选择器均用于控制按钮的按下与弹起效果。
进程管理主页面如图4.7.1.1所示。
图4.7.1.1 进程管理主页面
在进程管理的Item布局中,进程管理界面中的ListView展示的数据的布局都一样,因此要定义一个Item条目布局用于展示数据, ImageView控件用于展示程序图标,第一个TextView控件用于展示程序名称,第二个TextView用于展示程序占用内存大小,ChexkBox控件用于选中当前程序。
进程管理设置部分如图4.7.1.3所示。
图4.7.1.3 进程管理设置部分
4.7.2 逻辑代码部分
onResume()方法是当Activity可见时,如果ListView的适配器对象存在,则直接调用Adapter的notifyDataSetChanged()方法更新已生成的数据列表。系统会通过调用SystemInfoUtils类,获取正在运行的进程的个数、可用内存空间、可用/总内存大小。
initListener()方法用于初始化界面,给按钮添加监听,以及设置ListView的条目点击事件和滚动事件。在ListView的条目点击监听的onItemClick()方法中,循环遍历所有正在运行的程序,然后通过TaskInfo的isChecked的属性标记是否被选中,并更新数据。在ListView滚动事件监听的onScroll()方法中,用于判断程序在滚动的过程中mProcessNumTV文本显示的内容,当滚动的数目超出用户抄书用户进程个数是,显示系统进程个数,否则显示用户进程个数。如图4.7.2.1所示。
图4.7.2.1
FillData()方法用于填充数据,在子线程中通过TaskInfoParser类的getRunningTaskInfos()方法获取所有正在运行的程序,并且将用户程序和系统程序分别存储在userTaskInfos和sysTaskInfo集合中。cleanProcess()方法用于清理进程,inverse()方法用于控制反选按钮,selectAll()方法用于控制全选按钮,如图4.7.2.2所示。
图4.7.2.2
需要定义一个数据适配器,其中的getCount()方法用于返回总条目数,如果系统程序大于0并且SharedPreferences中存储的的key为showSystemProcess的值为true是,会返回“用户程序+系统程序+2”,其中2表示的是mProcessNumTV的数量。否则返回“用户程序+1”,这个1表示展示用户程序个数的mProcessNumTV文本标签。getItem()方法用于返回当前进程对象,getTextView()方法用于创建一个TextView,创建了两个,分别用于显示进程个数、系统进程个数。
在设置进程方面onCheckedChanged()方法用于监听ToggleButton按钮的状态改变,当“显示系统进程”按钮状态改变时,调用saveStatus()方法将showSystemProcess状态保存,当“锁屏清理进程”按钮状态是选中时,会启动AutoKillProcessService服务,否则服务会停止。
4.8 流量统计模块
4.8.1 流量统计界面
运营商设置界面分为三部分,第一部分有一张提示图片和一段文字组成;第二部分为一个TextView控件以及一个下拉控件,用于选择运营商信息;最下方放置一个按钮,点击之后进入流量监控界面,该界面在下次进入时不会再出现。
运营商设置界面如图4.8.1-1所示。
图 4.8.1.1 运营商设置
运营商设置完成之后会进入流量监控界面,在次界面中会定义一个TextView用于提示当前剩余流量信息,剩余流量充足和流量不足时会显示不同的文字。在文字左侧有一个ImageView,下方有三个TextView,分别用于提示今日已用流量,本月已用流量以及本月流量最下面有一个校正流量的Button,该控件也是一个图片选择器。
图 4.8.1.2 流量监控界面
4.8.2 逻辑代码部分
运营商设置界面主要选择手机使用的运营商,并将运营商存储在SharedPreferences对象中。initView()方法初始化界面布局控件,将运营商的信息填充到Spinner控件中显示在界面上。onClick()方法为按钮的点击事件,将运营商选择完毕之后点击完成按钮,首先使用SharedPreferences将选择的运营商信息存储,并且存储一个boolean值类型数据进行判断,然后进入该模块的主界面TrafficMonitoringActivity,boolean类型判断过运营商信息已经设置过则会直接进入流量监控界面,如图4.8.2.1所示。
图4.8.2.1
在进行流量统计之前,需要先创建一个数据库,用于存储程序所使用的的流量。还需要创建一个TrafficDao.java,当数据库创建完成后,使用其对数据库进行操作,其中包括对流量的查询、增加、修改。
TrafficMonitoringActivity中的initData()方法获取流量使用的具体情况并将信息展示在界面中。registReceiver()方法为注册自定义广播接收者,action注册了接收短信的活动,onClick()方法用于监听校正流量按钮的点击事件,按下按钮后首先判断手机号码属于哪一个运营商。自定义一个广播接收者CorrectFlowReceiver,当有短信到来时会执行onReceiver()方法,获取流量之后信息或使用SharedPreferences进行存储,并显示在TextView上。
TrafficMonitoringService服务的主要作用是获取应用程序的实时流量信息,逻辑代码部分需要有一个判断,如果该服务没有开启则开启该服务。该服务中onCreate()方法在该服务刚启动时统计一次从本次开机到现在所使用的总流量 ,updateTodayGPRS()向数据库中插入和更新最新的流量,并将共使用的数据存储到SharedPreferences对象中。
4.9 高级工具模块
4.9.1 高级工具界面
高级工具模块包含四个独立工具模块,即有四个条目,每个条目代表一个功能,四个条目的布局都是一样的,因此使用自定义的控件来实现,每个条目布局由三部分组成,左边显示功能图标,中间显示功能名称,右边显示一个箭头符号在使用自定义控件时,每个控件的开始节点和结束节点都为自定义控件类的全路径,需要注意点的是,在使用自定义控件是必须使用XML命名空间:
xmlns:custom_android=http://schemas.android.com/apk/res/com.example.mobliesafe将自定义的控件引入到布局中。
高级工具界面如图4.9.1.1所示。
图4.9.1.1
号码归属地查询界面是一个输入框,一个查询按钮,以及显示归属地信息的TextView组成,默认情况下显示号码归属地得到TextView不显示,只有当输入框中输入查询号码并且点击查询时,才会显示内容,Button按钮使用的是一个背景选择器。
号码归属地界面如图4.9.1.2所示。
图 4.9.1.2
一键备份和一键还原是界面中间有一个红色按钮,点击之后开始备份短信,要在自定义控件中使用自定义的属性要在res/valus目录下的attrs.xml文件中创建对应的变量,MyCircleProgress是自定义的控件和根节点。在布局中开始节点和结束节点设置为该自定义类的全路径名。
程序锁界面包含两个Fragment,分别用来展示未加锁界面和已加锁界面,并使用ViewPager控件使这两个页面可以滑动切换。最顶端定义一个LinearLayout用于显示两个TextView,分别显示未加锁和以加锁;下方定义了一个LinearLayout用于显示红色线条;在页面最下方定义了ViewPager用于进行页面的滑动切换。其中TextView控件以及View控件都使用了一个zero_widthwrapcontent样式,用于控制宽、高、权重的展示形式。程序锁界面如图4.9.1.4所示。
4.9.2逻辑代码部分
主界面的逻辑比较简单,主要是设置每一个条目的点击事件,跳转到相应的界面即可。initView()方法,用于初始化布局中的自定义控件,直接给事件添加监听事件即可。onClick()方法用于响应主界面4个条目的点击事件。startActivity()方法开启新的Activity。
号码归属地的操作需要创建一个address.db数据库,用于存储内地所有省市的号码信息,放入工程下的assets下。在进行号码归属地查询时,主要通过电话号码与数据库中的数据进行比对实现的,因此需要创建一个数据库操作类,在该类中通过SQL语句查询出号码的归属地,部分代码如下所示。
if (phonenumber.matches("^1[34578]\\d{9}$")) {Cursor cursor=db.rawQuery("select city from address_tb where _id=(select outkey from numinfo where mobileprefix =?)", new String[]{phonenumber.substring(0,7)});if (cursor.moveToNext()) {location=cursor.getString(0);}cursor.close();
号码归属地逻辑代码要要用onClick()方法用于响应界面中按钮的点击事件,如果文本框中没有内容就会提示其先输入电话号码,然后会查询数据库是否存在,如果不存在则先进行数据库复制,然后遍历数据库,查出号码归属地。
短信备份是要使用XML形式保存短信内容,保存在/data/data/com.android.provider.telephony应用的database目录下的mmssms.db数据库。setFlag()方法是在SMSBackupActivity界面中的点击备份或者取消按钮调用,用来控制短信备份的开始或者取消。backUpSms()用来备份短信,在备份时会先创建一个backup.xml然后获取到短信内容,并对其序列化。CountResolver得到短信数据。短信备份在开启子线程中调用短信备份工具类smsBackUpUtils()的backUpSms()方法开始进行短信备份。如果没有短信,则弹出Toast提示并发送Handler将按钮文字改为一键备份,部分代码如图4.9.2.1所示。
图 4.9.2.1
短信还原功能与短信备份的功能是相对应的,在还原的时候同样需要使用XML解析器将已备份的短信还原。短信还原的工具类的代码在SmsReducitionUtils,定义了一个SmsReducitionCalBack,该接口中有两个方法beforeSmsReducition()和onSmsReducition(),前者是获取将要还原的短信总条数,后者表示得到将要还原的进度,XML的解析也在此完成。在还原短信界面需要实现对SmsReducitionUtils类中的回调方法。
4.10 设置中心模块
4.10.1 设置中心界面设计
设置中心界面有两个小条目,每个条目有两个TextView,一个ToggleButton以及一个View对象。先定义一个Item布局作为自定义控件的布局,其中包括设置标题、状态开启或关闭、Toggle是否被选中等信息。
设置中心页面如图4.10.1.1所示。
图4.10.1.1
4.10.2 逻辑代码部分
实现自定义控件,在定义控件时,需要继承RelativeLayout,并创建自定义控件类的构造方法。SettingView()方法用于获取属性,通过context.obtainStyledAttributes创建TypedArray对象,然后通过该对象获取attrs.xml文件中定义的属性值,最后回收TypedArray对象。setChecked()方法用于实现组合控件的选中方式,黑名单拦截是否开启与程序锁是否开启都可以调用此方法。setStatus()方法用于设置组合控件的是否选中,如果是选中众泰,则mSettingStatusTV显示文本为已开启(status_on),否则显示已关闭。setOnCheckedStatusIsChaged()方式用于设置状态监听,并且会传递一个接口对象onCheckedStatusIsChecked,此接口为一个回调接口。
界面逻辑中onstart()方法是当Activity启动时会自动调用该方法,判断服务是否运行,并将返回结果设置给mAppLockSV控件。onCheckedChaged()方法用于监听ToggleButton按钮状态改变。saveStatus()方法用于保存黑名单拦截是否开启。
部分代码如图4.10.2所示。
图4.10.2
5 调试过程
5.1解决错误
在移动应用开发的过程中会出现很多的错误,因此需要做进一步调试改错,以下是我本次课程设计出现的部分错误及改正。
Android开发想要获取手机联系人需要给系统添加READ_CONTACTS权限,查看LogCat可知,我没有配置此权限,做出以下改变,如图5.1.2所示。开发过程中还会有此类错误,都是这样修改,不再过多描述。
图5.1.2 修改错误①
2.错误2,在版本更新时显示IO异常,无法正常弹出显示更新的页面。
无法正常弹出显示更新的页面,显示的IO异常,翻看代码,查看出现IO异常的原因,从而解决问题。catch(IOException e){ handler.sendEmptyMessage(MESSAGE_IO_EEOR);
e.printStackTrace();
IOException 是在使用流、文件和目录访问信息时引发的异常的基类。查看到新版本的下载地址填写有误,需要在版本更新的工具类的中创建HttpGet对象,请求updateinfo.html页面。修改如下,如图5.1.4所示。
图 5.1.4 修改错误2
5.2系统调试
一、logcat日志
可在 Window->Show View->Other->Android->Log Cat 调出 Log Cat 界面常用的日志: 普通运行信息:i 错误信息:e 输出日志: Log.i(TAG, strings); 其中TAG 为日志标识符,一般用类名表示(方便查看此日志是某个类的输出),且常声明为静态常量.stirngs 为要输出的字符串.例:
Log.i(TAG, strings)
成功运行程序后,在输出日志Log Cat 视图中 即可查看到标识为 PhoneSMSTest 的信息
PS:可在Log cat 中创建一个过虑器,Log cat->create filter->Filter Name:随意.by tab name: 日志标识符,此处为 PhoneSMSTest
二、断点调试
1、设置断点:
在编码窗体的左边框上用鼠标双击,或者右键点击菜单,选择 Toggle Breakpoint菜单项。
2、在debug模式下运行程序进入调试状态:通过点击工具栏上的小虫按钮或者是在项目右键点击然后选择Debug As,Android Application菜单,启动程序的调试模式。
第一次运行调试模式eclipse会弹出如下确认窗口:
当程序运行到你的断点地方时就会停下,这时可以按照下面的功能键按需求进行调试:
Run->step Into 逐语句 (或F5)
Run->step Over 逐过程 (或F6,略过方法
Run->step Return 单步返回(或F7 , 逐语句进入方法后跳出.);
Run->Run To Line 运行到光标处 (或 Ctrl + R)
Run->Resume 断续运行到结束 (或F8)
查看断点时变量当前的值:右键点击对应的变量,在菜单上选择 watch 菜单项,变量的值就会出现在 expressions窗口中。
本系统采用Log.i也进行了调试。
手机安全卫士是生活中手机上比较基础的一个软件,功能比较多比较复杂,所以我采用了参考部分书籍和学习资料的方法来完成本次课程设计。为了保证版本升级能够正常完成,刚开始要配置好环境,以及Tomcat服务器,以及打包好高版本的应用。后期都严格按照流程来写本次实验,包括各个Activity之间的跳转,服务器与客户端之间的连接,数据库的连接等。后面部分的代码也有些复杂,有些错误对我来说无法解决,初步百度解决问题,如果解决不了的话就去向老师请教。