手机程序锁是安卓上一款加密应用程序的安全类工具,当你打开某个应用程序的时候,如果已经对其加锁,则会弹出密码框或者图形锁,输入正确后才可以进入,其可以对所有的APK程序进行加密,包括打开图片处理软件,音乐软件,短信,微信等等.那么现有的程序锁实用吗?答案是确定的,经本人测试不太实用。存在以下几个问题:
1)不够方便的解锁处理;
2)密码存储的加密保护不够好;
3)整个程序锁进程可以被结束掉,保护如同虚设。所以,让我们来打造一个实用的程序锁。
原理分析
程序锁的应用是一个服务定时监视顶层Activity,如果Activity对应的包名是之前上锁的应用程序的,则弹出一个页面要求输入解锁密码,这里我们改成图形解锁,通过判断解锁密码是否与之前设定的相符,来决定是否正常使用这些软件。
而密码存储可以进行加密处理,所以不做过多分析,进程保护的方法我在14年一期里介绍到过,所以这里也不做讲解了,代码嵌套进去即可。而为了更加方便用户的使用,采用九宫格方式解锁,其原理将会在下面的编程分析里详细介绍。
编程分析
1.九宫格的设计与绘制
图案解锁原理:先绘制九个点,其实就是找个九个位置,给九个点绘制图案;考虑图案正常下的状态,用户点击的时候的状态;要考虑连线错误时候的状态,图案的限制;在设置密码的时候,画图连线保存成密码。
privatevoiddrawLine(Pointstart,Pointend,Canvascanvas,Paintpaint){ doubled=MathUtil.distance(start.x,start.y,end.x,end.y); floatrx=(float)((end.x-start.x)*dotRadius/4/d); floatry=(float)((end.y-start.y)*dotRadius/4/d); canvas.drawLine(start.x+rx,start.y+ry,end.x-rx,end.y-ry,paint); } privatevoiddrawArrow(Canvascanvas,Paintpaint,Pointstart,Pointend,floatarrowHeight, intangle){ doubled=MathUtil.distance(start.x,start.y,end.x,end.y); floatsin_B=(float)((end.x-start.x)/d); floatcos_B=(float)((end.y-start.y)/d); floattan_A=(float)Math.tan(Math.toRadians(angle)); floath=(float)(d-arrowHeight-dotRadius*1.1); floatl=arrowHeight*tan_A; floata=l*sin_B; floatb=l*cos_B; floatx0=h*sin_B; floaty0=h*cos_B; floatx1=start.x+(h+arrowHeight)*sin_B; floaty1=start.y+(h+arrowHeight)*cos_B; floatx2=start.x+x0-b; floaty2=start.y+y0+a; floatx3=start.x+x0+b; floaty3=start.y+y0-a; Pathpath=newPath(); path.moveTo(x1,y1); path.lineTo(x2,y2); path.lineTo(x3,y3); path.close(); canvas.drawPath(path,paint); } privatevoidinitCache(){ width=this.getWidth(); height=this.getHeight(); floatx=0; floaty=0; if(width>height){ x=(width-height)/2; width=height; }else{ y=(height-width)/2; height=width; } intleftPadding=15; floatdotPadding=width/3-leftPadding; floatmiddleX=width/2; floatmiddleY=height/2; mPoints[0][0]=newPoint(x+middleX-dotPadding,y+middleY-dotPadding,1); mPoints[0][1]=newPoint(x+middleX,y+middleY-dotPadding,2); mPoints[0][2]=newPoint(x+middleX+dotPadding,y+middleY-dotPadding,3); mPoints[1][0]=newPoint(x+middleX-dotPadding,y+middleY,4); mPoints[1][1]=newPoint(x+middleX,y+middleY,5); mPoints[1][2]=newPoint(x+middleX+dotPadding,y+middleY,6); mPoints[2][0]=newPoint(x+middleX-dotPadding,y+middleY+dotPadding,7); mPoints[2][1]=newPoint(x+middleX,y+middleY+dotPadding,8); mPoints[2][2]=newPoint(x+middleX+dotPadding,y+middleY+dotPadding,9); Log.d(jerome,canvaswidth:+width); dotRadius=width/10; isCache=true; initPaints(); }
2.程序锁后台服务实现
启动定时器,新建任务,先获取当前顶层的应用程序包名,读取数据库,判断是否加锁的包名,是的话则要跳转到我们写好的解锁画面。如果是第一次打开,则跳出设置解锁的图案,这样每个应用程序解锁图案都不一样,可以提高安全性。如果不是枷锁的包名,则不做任何操作,允许进入使用。核心代码如下:
privatevoidstartTimer(){ if(timer==null){ newTimer().schedule(newTimerTask(){ @Override publicvoidrun(){ Log.i(patternlock,timerisstarted); ComponentNamecn=am.getRunningTasks(1).get(0).topActivity; StringpackageName=cn.getPackageName(); StringclassName=cn.getClassName(); Log.i(patternlock,packageName) if(!lastpack.equals(packageName)!packageName.equals(com.example.patternlock)){ Check.getIntence().saveIsFinished(context,lastpack,false); Check.getIntence().saveOpened(context,lastpack+locked,false); } if(dbs.query(packageName)){ if (Check.getIntence().getIsFinished(context,packageName)||Check.getIntence().getLockOpened(con text,packageName+locked)){ //Toast.makeText(context,foundbutlocked,3000).show(); Log.i(patternlock,checked); return; }else{ //Toast.makeText(context,foundandshow,3000).show(); Check.getIntence().saveOpened(context,packageName+locked,true); Intentintent=newIntent(); intent.setClassName(com.example.patternlock, com.example.patternlock.WelActivity); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Bundlebundle=newBundle(); bundle.putString(packName,packageName); intent.putExtras(bundle); startActivity(intent); } lastpack=packageName; }else{ //Toast.makeText(context,didnotfind,3000).show(); return; } //Looper.loop(); } },1000,1000);}}
编译以上代码,运行程序打开界面,设置枷锁应用如图1所示。
第二次打开加锁应用,会弹出设置好的密码解锁,如图2所示。
图2
经过测试,本程序可以实现程序锁的功能,九宫格解锁,进程保护代码我在2014年一期讲过,直接嵌入进去就可以了,可以保证不会在后台被结束掉,但是密码没有加密存储,可定义一个算法,用一些常用的算法接口,这样一个实用的程序锁就完成了。