Android程序锁的实现以及逻辑
程序员文章站
2024-03-04 21:09:42
本项目是一个比较有趣的项目源码,可以给其他项目加锁,程序锁的原理是一个“看门狗”的服务定时监视顶层activity,如果activity对应的包名是之前上锁的应用程序的,则...
本项目是一个比较有趣的项目源码,可以给其他项目加锁,程序锁的原理是一个“看门狗”的服务定时监视顶层activity,如果activity对应的包名是之前上锁的应用程序的,则弹出一个页面要求输入解锁密码。
效果如下:
1.基本思路
①.创建已加锁应用的数据库(字段:_id,packagename),如果应用已加锁,将加锁应用的包名维护到数据库中
②.已加锁+未加锁 == 手机中所有应用(appinfoprovider)
2.已加锁和未加锁的数据适配器
class myadapter extends baseadapter{ private boolean islock; /** * @param islock 用于区分已加锁和未加锁应用的标示 true已加锁数据适配器 false未加锁数据适配器 */ public myadapter(boolean islock) { this.islock = islock; } @override public int getcount() { if(islock){ tv_lock.settext("已加锁应用:"+mlocklist.size()); return mlocklist.size(); }else{ tv_unlock.settext("未加锁应用:"+munlocklist.size()); return munlocklist.size(); } } @override public appinfo getitem(int position) { if(islock){ return mlocklist.get(position); }else{ return munlocklist.get(position); } } @override public long getitemid(int position) { return position; } @override public view getview(int position, view convertview, viewgroup parent) { viewholder holder = null; if(convertview == null){ convertview = view.inflate(getapplicationcontext(), r.layout.listview_islock_item, null); holder = new viewholder(); holder.iv_icon = (imageview) convertview.findviewbyid(r.id.iv_icon); holder.tv_name = (textview) convertview.findviewbyid(r.id.tv_name); holder.iv_lock = (imageview) convertview.findviewbyid(r.id.iv_lock); convertview.settag(holder); }else{ holder = (viewholder) convertview.gettag(); } final appinfo appinfo = getitem(position); final view animationview = convertview; holder.iv_icon.setbackgrounddrawable(appinfo.icon); holder.tv_name.settext(appinfo.name); if(islock){ holder.iv_lock.setbackgroundresource(r.drawable.lock); }else{ holder.iv_lock.setbackgroundresource(r.drawable.unlock); } holder.iv_lock.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { //添加动画效果,动画默认是非阻塞的,所以执行动画的同时,动画以下的代码也会执行 animationview.startanimation(mtranslateanimation);//500毫秒 //对动画执行过程做事件监听,监听到动画执行完成后,再去移除集合中的数据,操作数据库,刷新界面 mtranslateanimation.setanimationlistener(new animationlistener() { @override public void onanimationstart(animation animation) { //动画开始的是调用方法 } @override public void onanimationrepeat(animation animation) { //动画重复时候调用方法 } //动画执行结束后调用方法 @override public void onanimationend(animation animation) { if(islock){ //已加锁------>未加锁过程 //1.已加锁集合删除一个,未加锁集合添加一个,对象就是getitem方法获取的对象 mlocklist.remove(appinfo); munlocklist.add(appinfo); //2.从已加锁的数据库中删除一条数据 mdao.delete(appinfo.packagename); //3.刷新数据适配器 mlockadapter.notifydatasetchanged(); }else{ //未加锁------>已加锁过程 //1.已加锁集合添加一个,未加锁集合移除一个,对象就是getitem方法获取的对象 mlocklist.add(appinfo); munlocklist.remove(appinfo); //2.从已加锁的数据库中插入一条数据 mdao.insert(appinfo.packagename); //3.刷新数据适配器 munlockadapter.notifydatasetchanged(); } } }); } }); return convertview; } }
mlockadapter = new myadapter(true); lv_lock.setadapter(mlockadapter); munlockadapter = new myadapter(false); lv_unlock.setadapter(munlockadapter);
3.已加锁和未加锁条目点击事件处理
holder.iv_lock.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { //添加动画效果,动画默认是非阻塞的,所以执行动画的同时,动画以下的代码也会执行 animationview.startanimation(mtranslateanimation);//500毫秒 //对动画执行过程做事件监听,监听到动画执行完成后,再去移除集合中的数据,操作数据库,刷新界面 mtranslateanimation.setanimationlistener(new animationlistener() { @override public void onanimationstart(animation animation) { //动画开始的是调用方法 } @override public void onanimationrepeat(animation animation) { //动画重复时候调用方法 } //动画执行结束后调用方法 @override public void onanimationend(animation animation) { if(islock){ //已加锁------>未加锁过程 //1.已加锁集合删除一个,未加锁集合添加一个,对象就是getitem方法获取的对象 mlocklist.remove(appinfo); munlocklist.add(appinfo); //2.从已加锁的数据库中删除一条数据 mdao.delete(appinfo.packagename); //3.刷新数据适配器 mlockadapter.notifydatasetchanged(); }else{ //未加锁------>已加锁过程 //1.已加锁集合添加一个,未加锁集合移除一个,对象就是getitem方法获取的对象 mlocklist.add(appinfo); munlocklist.remove(appinfo); //2.从已加锁的数据库中插入一条数据 mdao.insert(appinfo.packagename); //3.刷新数据适配器 munlockadapter.notifydatasetchanged(); } } }); } });
4.程序锁必须在服务中去维护
①基本思路
- 判断当前开启的应用(现在手机可见任务栈)
- 如果开启的应用在已加锁的列表中,弹出拦截界面
- 看门狗服务,一直(死循环(子线程,可控))对开启的应用做监听
public class watchdogservice extends service { private boolean iswatch; private applockdao mdao; private list<string> mpacknamelist; private innerreceiver minnerreceiver; private string mskippackagename; private mycontentobserver mcontentobserver; @override public void oncreate() { //维护一个看门狗的死循环,让其时刻监测现在开启的应用,是否为程序锁中要去拦截的应用 mdao = applockdao.getinstance(this); iswatch = true; watch(); intentfilter intentfilter = new intentfilter(); intentfilter.addaction("android.intent.action.skip"); minnerreceiver = new innerreceiver(); registerreceiver(minnerreceiver, intentfilter); //注册一个内容观察者,观察数据库的变化,一旦数据有删除或者添加,则需要让mpacknamelist重新获取一次数据 mcontentobserver = new mycontentobserver(new handler()); getcontentresolver().registercontentobserver( uri.parse("content://applock/change"), true, mcontentobserver); super.oncreate(); } class mycontentobserver extends contentobserver{ public mycontentobserver(handler handler) { super(handler); } //一旦数据库发生改变时候调用方法,重新获取包名所在集合的数据 @override public void onchange(boolean selfchange) { new thread(){ public void run() { mpacknamelist = mdao.findall(); }; }.start(); super.onchange(selfchange); } } class innerreceiver extends broadcastreceiver{ @override public void onreceive(context context, intent intent) { //获取发送广播过程中传递过来的包名,跳过次包名检测过程 mskippackagename = intent.getstringextra("packagename"); } } private void watch() { //1,子线程中,开启一个可控死循环 new thread(){ public void run() { mpacknamelist = mdao.findall(); while(iswatch){ //2.监测现在正在开启的应用,任务栈 //3.获取activity管理者对象 activitymanager am = (activitymanager) getsystemservice(context.activity_service); //4.获取正在开启应用的任务栈 list<runningtaskinfo> runningtasks = am.getrunningtasks(1); runningtaskinfo runningtaskinfo = runningtasks.get(0); //5.获取栈顶的activity,然后在获取此activity所在应用的包名 string packagename = runningtaskinfo.topactivity.getpackagename(); //如果任务栈指向应用有切换,将mskippackagename空字符串 //6.拿此包名在已加锁的包名集合中去做比对,如果包含次包名,则需要弹出拦截界面 if(mpacknamelist.contains(packagename)){ //如果现在检测的程序,以及解锁了,则不需要去弹出拦截界面 if(!packagename.equals(mskippackagename)){ //7,弹出拦截界面 intent intent = new intent(getapplicationcontext(),enterpsdactivity.class); intent.setflags(intent.flag_activity_new_task); intent.putextra("packagename", packagename); startactivity(intent); } } //睡眠一下,时间片轮转 try { thread.sleep(500); } catch (interruptedexception e) { e.printstacktrace(); } } }; }.start(); } @override public ibinder onbind(intent arg0) { return null; } @override public void ondestroy() { //停止看门狗循环 iswatch = false; //注销广播接受者 if(minnerreceiver!=null){ unregisterreceiver(minnerreceiver); } //注销内容观察者 if(mcontentobserver!=null){ getcontentresolver().unregistercontentobserver(mcontentobserver); } super.ondestroy(); } }
public class enterpsdactivity extends activity { private string packagename; private textview tv_app_name; private imageview iv_app_icon; private edittext et_psd; private button bt_submit; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); //获取包名 packagename = getintent().getstringextra("packagename"); setcontentview(r.layout.activity_enter_psd); initui(); initdata(); } private void initdata() { //通过传递过来的包名获取拦截应用的图标以及名称 packagemanager pm = getpackagemanager(); try { applicationinfo applicationinfo = pm.getapplicationinfo(packagename,0); drawable icon = applicationinfo.loadicon(pm); iv_app_icon.setbackgrounddrawable(icon); tv_app_name.settext(applicationinfo.loadlabel(pm).tostring()); } catch (namenotfoundexception e) { e.printstacktrace(); } bt_submit.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { string psd = et_psd.gettext().tostring(); if(!textutils.isempty(psd)){ if(psd.equals("123")){ //解锁,进入应用,告知看门口不要再去监听以及解锁的应用,发送广播 intent intent = new intent("android.intent.action.skip"); intent.putextra("packagename",packagename); sendbroadcast(intent); finish(); }else{ toastutil.show(getapplicationcontext(), "密码错误"); } }else{ toastutil.show(getapplicationcontext(), "请输入密码"); } } }); } private void initui() { tv_app_name = (textview) findviewbyid(r.id.tv_app_name); iv_app_icon = (imageview) findviewbyid(r.id.iv_app_icon); et_psd = (edittext) findviewbyid(r.id.et_psd); bt_submit = (button) findviewbyid(r.id.bt_submit); } @override public void onbackpressed() { //通过隐式意图,跳转到桌面 intent intent = new intent(intent.action_main); intent.addcategory(intent.category_home); startactivity(intent); super.onbackpressed(); } }
5.隐藏最近打开的activity
<activity android:excludefromrecents="true" android:name="com.itheima.mobilesafe.enterpwdactivity" android:launchmode="singleinstance" />
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Python实现的密码强度检测器示例