1,软件锁(功能描述:当软件处于以加锁的列表中时,打开这个软件会跳转到密码输入界面,输入正确会跳转到软件界面,否则密码错误)
①ui参考
不使用fragment,采用布局叠加隐藏,点击一个文本,就显示一个界面(列表ListView),另一个布局界面隐藏起来(frameLayout帧布局实现).
②程序未加锁界面的展现
找到所有关心的控件,默认把所有的应用程序未加锁界面列表中.
参考条目ui
额外:加锁的小图标带有状态选择器,点击变换图片
横线可以考虑加个宽度为1的imageView;
③点击条目添加到以加锁列表中,并在当前列表进行移除.
由于以加锁是列表条目是需要长期保存的,所以创建数据库去记录数据.
参考表名:lockinfo,_id,主键自增长,packname应用程序包名,
然后创建dao类,操作这个表的增删改查逻辑.
如果异常出现unix之类的 C代码异常,就有可能是模拟器挂掉了.
点击条目>>添加到数据库>>以加锁条目添加数据.
额外:获取应用程序集合的时候,分流:以加锁的应用程序集合,未加锁的应用程序集合.(查表判断)
④加锁条目的显示:也是一个ListView,注意右边解锁小图标的不同.
条目点击事件里,如果点击了加锁,一个集合移除,另一个集合添加.
ui更新:把切换条目放到标题上
⑤条目的动画效果,点击之后向左移动(解锁),点击加锁,向左移动.
//位移动画.
点击条目之后播放动画,然而播放的动画效果出现在下一个条目上.(适配器.notifyDataSetChanged和动画的代码先后顺序不影响.)
因为动画的播放不是一个阻塞式的代码(并不按从上到下的代码执行顺序,而是开启了一个计时器.)
所以要注册动画的监听器setAnimationListener(new xxx){
onAnimationStart()//开始播放时
onAnimationRepeat()//重复播放
onAnimationEnd()//当动画停止播放时
}
2,程序锁看门狗的核心原理:
2.1观察Log日志,可以发现当用户打开应用的时候ActivityManager会打印一条日志,开启的应用.
所以只需要通过获取ActivityManager的数据就可以监视系统运行的状态了.
看门狗需要长期驻扎在后台程序,所以需要创建一个服务,去获取(不停的)数据
开一个子线程,死循环,或者计时器都可以达到不停获取数据的效果.
am.getRunningTask(最大任务栈数1000)//获取正在运行的任务,返回一个正在运行的任务栈集合.
一般安卓任务栈不会超过50,WIndows都不过100
这个api的特点:最近使用的在最前面,最后使用的在最后面.
RunningTaskInfo.topActivity.getPackageName();
2.2 所以只要不断获取运行的任务栈中第一个任务,然后判断它就能实现看门狗的效果.
值得注意的是,死循环需要用一个变量来控制它,方便进行关闭,不然子线程无法关闭.同时要给它每次获取数据设置一个短暂的延迟,否则每秒上千次循环遍历很容易消耗资源.
2.3 在设置中心加一个新的开关:开启,打开服务,关闭,关闭服务
记得判断状态,进行回显状态.
//权限:GET_TASK 获取任务栈状态
3,代码实现看门狗效果
3.1
①看门狗运行期间,获取到第一个任务,然后查询数据库,判断是否受保护,如果是,开启一个密码界面
服务开启activiy,记得添加flag,intent.setFlag(Intent.FLAG_ACTIVIYT_NEW_TASK);
开启界面的时候,把应用程序的包名传递过来intent.putExtra(packagename);在密码界面显示出来,方便用户区分要开启的应用是什么.
②密码界面参考ui:
③密码输入正确,finsh()掉当前页面,密码输入错误,提示错误,输入框抖动(参考api demo中的效果)
密码输入正确之后,应该告诉看门狗临时停止检测这个应用(发送广播,绑定远程服务都可以).
这里用自定义广播,如果密码输入正确,发送一条自定义广播,携带包名(为了临时停止保护)
在服务里接收到这个广播,把包名记录下来,在判断完是否需要保护,再判断是否需要临时停止检测.
3.2 BUG修复:
①用户点击返回键,密码界面消失后,可以看到一瞬间的界面,所以在密码输入界面点击返回键,就让用户直接返回桌面.
重写onBackPressd()//如果把这里面的super()代码删掉,点击返回就不会关闭界面了.
这里需要让用户返回桌面.//查看上层应用,桌面的源代码.
②用户返回桌面再打开密码保护应用时,密码保护界面还是上一次的应用.
解决方案:当界面不可见的时候关闭它.
③开启应用可以看到一瞬间的界面:看门狗循环时间间隔太长,简短即可.
3.3 如果开启了手机卫士,最小化之后,开启受保护的应用,输入正确的密码,来到的界面是手机卫士,而不是想要代开的应用.
原因:因为手机卫士的任务栈存在多个界面,当打开受保护的应用时,弹出密码输入界面.手机卫士任务栈存在两个界面,输入正确,输入密码正确只是关闭了密码输入的界面,会返回手机卫士的上一个界面.而不是受保护的应用.
解决方法:Activity期末模式:单一实例singleInstance
开发的时候灵活的使用启动模式,可以解决一些应用程序的用户体验BUG,提高程序执行效
3.4 应用程序的效率优化
①把一些引用提取到死循环的外面
②am.getRunningTasks(1);//只需要第一个任务栈中的任务就行了
③看门狗查询数据库的操作是比较消耗时间的,所以增加一个查询所有的保护应用的集合,这样每次查询的时候,就不用查询数据库,直接查询集合(在内存中,效率高)即可.
④输入密码界面的初始化操作放到死循环外面
3.5,优化之后引发的BUG
①获取数据库集合操作只执行了一次.如果在服务开启期间,增加或删除不起作用
解决:通过内容观察者实现
Uri : content://xxxxxxx
在DAO中context.getContentResolver().notifyChange(uri,通知的观察者(null,谁注册谁观察));
在服务类中,创建内容解析器.注册内容内容观察者(uri,true(前缀满足即可),内容观察者);
创建内容观察者内部类,继承ContentObserver,重写onChange()方法,当数据发生变化时调用.
发生变化之后,重新获取一次集合即可.
关键字:观察者设计模式
4.程序锁的电量优化
程序锁在后台服务一直执行,耗电量高.
当用户在操作手机的时候才进行看门狗行为,锁屏的时候关闭循环,子线程就结束掉了,解锁屏幕的时候开启子线程.
//这两个事件都会发出广播,在看门狗的内部广播接收者注册的时候增加两个action
接收到广播的时候,过滤一下action.