Design principle and implementation process of pattern unlocking in Android
In Android, to unlock a pattern, you must first understand the implementation principle of the pattern. The previous figure shows that the gesture records in the pattern are 1-9 or 0-8, and the password is saved in the order, of course, some of them can be repeated. For the sake of security, the original sequence cannot be stored directly. encryption is required, such as MD5 or Hash. (Author: a day a better) custom View unlocking is the most critical part. The following is the implementation of custom LockView. The annotations in the LockView are detailed.
Package com. example. patternlock; import java. util. arrayList; import java. util. list; import android. content. context; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. canvas; import android. graphics. color; import android. graphics. paint; import android. util. attributeSet; import android. view. motionEvent; import android. view. view; public class LockView extends View {private boolean inited = false; Paint paint = new Paint (Paint. ANTI_ALIAS_FLAG); // anti-sawtooth Paint pressPaint = new Paint (); // Paint errorPaint = new Paint () when pressed; // the Paint brush private Bitmap bitmapPointError when an error occurs; private Bitmap bitmapPointPress; private Bitmap bitmapPointNormal; private float bitmapR; // the radius of the point is private boolean isDraw = false; // whether float mouseX and mouseY are being drawn; private Point [] [] points = new Point [3] [3]; private ArrayList
PointList = new ArrayList
(); // Save the vertex private ArrayList
PassList = new ArrayList
(); Private OnDrawFinishedListener listener; public LockView (Context context, AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr ); // TODO Auto-generated constructor stub} public LockView (Context context, AttributeSet attrs) {super (context, attrs ); // TODO Auto-generated constructor stub} public LockView (Context context) {super (context); // TODO Auto-generated constructor stub} @ Over Ridepublic boolean onTouchEvent (MotionEvent event) {mouseX = event. getX (); mouseY = event. getY (); int [] ij; int I, j; switch (event. getAction () {case MotionEvent. ACTION_DOWN: resetPoints (); ij = getSelectedPoint (); if (ij! = Null) {isDraw = true; I = ij [0]; j = ij [1]; points [I] [j]. state = Point. STATE_PRESS; pointList. add (points [I] [j]); passList. add (I * 3 + j);} break; case MotionEvent. ACTION_MOVE: if (isDraw) {ij = getSelectedPoint (); if (ij! = Null) {I = ij [0]; j = ij [1]; if (! PointList. contains (points [I] [j]) {points [I] [j]. state = Point. STATE_PRESS; pointList. add (points [I] [j]); passList. add (I * 3 + j) ;}} break; case MotionEvent. ACTION_UP: boolean valid = false; if (listener! = Null & isDraw) {valid = listener. OnDrawFinished (passList);} if (! Valid) {for (Point p: pointList) {p. state = Point. STATE_ERROR ;}} isDraw = false; break; default: break;} this. postInvalidate (); return true;} private int [] getSelectedPoint () {Point pMouse = new Point (mouseX, mouseY); for (int I = 0; I <points. length; I ++) {for (int j = 0; j <points [I]. length; j ++) {if (points [I] [j]. distance (pMouse) <bitmapR) {int [] result = new int [2]; result [0] = I; result [1] = j; return re Sult ;}}return null;} public void resetPoints () {passList. clear (); pointList. clear (); for (int I = 0; I <points. length; I ++) {for (int j = 0; j <points [I]. length; j ++) {points [I] [j]. state = Point. STATE_NORMOL;} this. postInvalidate () ;}@ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); if (! Inited) {init ();} drawPoints (canvas); if (pointList. size ()> 0) {// draw line 2-> 3, 3-> 5... point a = pointList. get (0); for (int I = 1; I <pointList. size (); I ++) {Point B = pointList. get (I); drawLine (canvas, a, B); a = B;} if (isDraw) {// draw the last vertex drawLine (canvas,, new Point (mouseX, mouseY) ;}} private void drawLine (Canvas canvas, Point a, Point B) {if (. state = Point. STATE_ERROR) {canvas. drawLine (. x,. y, B. x, B. y, errorPaint);} else if (. state = Point. STATE_PRESS) {canvas. drawLine (. x,. y, B. x, B. y, pressPaint) ;}} private void drawPoints (Canvas canvas) {for (int I = 0; I <points. length; I ++) {for (int j = 0; j <points [I]. length; j ++) {if (points [I] [j]. state = Point. STATE_NORMOL) {// normolcanvas. drawBitmap (bitmapPointNormal, points [I] [j]. x-bitmapR, points [I] [j]. y-bitmapR, paint);} else if (points [I] [j]. state = Point. STATE_PRESS) {// presscanvas. drawBitmap (bitmapPointPress, points [I] [j]. x-bitmapR, points [I] [j]. y-bitmapR, paint);} else {// errorcanvas. drawBitmap (bitmapPointError, points [I] [j]. x-bitmapR, points [I] [j]. y-bitmapR, paint) ;}}} private void init () {pressPaint. setColor (Color. YELLOW); pressPaint. setStrokeWidth (4); errorPaint. setColor (Color. RED); errorPaint. setStrokeWidth (4); bitmapPointError = BitmapFactory. decodeResource (getResources (), R. drawable. error); bitmapPointNormal = BitmapFactory. decodeResource (getResources (), R. drawable. normal); bitmapPointPress = BitmapFactory. decodeResource (getResources (), R. drawable. press); bitmapR = bitmapPointError. getWidth ()/2; // the same size as the three points int width = getWidth (); int height = getHeight (); int offset = Math. abs (width-height)/2; int offsetX, offsetY; int space; if (width> height) {space = height/4; offsetX = offset; offsetY = 0 ;} else {space = width/4; offsetX = 0; offsetY = offset;} points [0] [0] = new Point (offsetX + space, offsetY + space ); points [0] [1] = new Point (offsetX + 2 * space, offsetY + space); points [0] [2] = new Point (offsetX + 3 * space, offsetY + space); points [1] [0] = new Point (offsetX + space, offsetY + 2 * space ); points [1] [1] = new Point (offsetX + 2 * space, offsetY + 2 * space ); points [1] [2] = new Point (offsetX + 3 * space, offsetY + 2 * space); points [2] [0] = new Point (offsetX + space, offsetY + 3 * space); points [2] [1] = new Point (offsetX + 2 * space, offsetY + 3 * space ); points [2] [2] = new Point (offsetX + 3 * space, offsetY + 3 * space); inited = true; // initialization complete} public interface OnDrawFinishedListener {boolean OnDrawFinished (List
PassList);} public void setOnDrawFinishedListener (OnDrawFinishedListener listener) {this. listener = listener ;}}
Set password:
Package com. jikexueyuan. screenlock; import android. content. intent; import android. content. sharedPreferences; import android. support. v7.app. actionBarActivity; import android. OS. bundle; import android. view. menu; import android. view. menuItem; import android. view. view; import android. widget. button; import android. widget. toast; import java. util. list; public class SettingActivity extends ActionBarActivity {List
PassList; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_setting); final GestureLock lock = (GestureLock) findViewById (R. id. lockView); Button btn_reset = (Button) findViewById (R. id. btn_reset); Button btn_save = (Button) findViewById (R. id. btn_save); lock. setOnDrawFinishedListener (new GestureLock. onDrawFinishedListener () {@ Override public boolean OnDrawFinished (List
PassList) {if (passList. size () <3) {Toast. makeText (SettingActivity. this, the password cannot be less than three points, Toast. LENGTH_SHORT ). show (); return false;} else {SettingActivity. this. passList = passList; return true ;}}); btn_reset.setOnClickListener (new View. onClickListener () {@ Override public void onClick (View v) {lock. resetPoints () ;}}); btn_save.setOnClickListener (new View. onClickListener () {@ Override public vo Id onClick (View v) {if (passList! = Null) {StringBuilder sb = new StringBuilder (); for (Integer I: passList) {sb. append (I);} SharedPreferences sp = SettingActivity. this. getSharedPreferences (password, SettingActivity. this. MODE_PRIVATE); SharedPreferences. editor editor = sp. edit (); editor. putString (password, sb. toString (); editor. commit (); Toast. makeText (SettingActivity. this, saved, Toast. LENGTH_SHORT ). show () ;}}) ;}@ Override public boolean onCreateOptionsMenu (Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater (). inflate (R. menu. menu_setting, menu); return true ;}@ Override public boolean onOptionsItemSelected (MenuItem item) {// Handle action bar item clicks here. the action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest. xml. int id = item. getItemId (); // noinspection SimplifiableIfStatement if (id = R. id. action_settings) {return true;} return super. onOptionsItemSelected (item );}}
Verify password:
Package com. example. patternlock; import android. app. activity; import android. content. sharedPreferences; import android. OS. bundle; import android. widget. toast; import java. util. list; import com. example. patternlock. lockView. onDrawFinishedListener; public class LockActivity extends Activity {@ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_lock); SharedPreferences sp = getSharedPreferences (password, this. MODE_PRIVATE); final String password = sp. getString (password,); LockView lock = (LockView) findViewById (R. id. lockView); lock. setOnDrawFinishedListener (new OnDrawFinishedListener () {@ Override public boolean OnDrawFinished (List
PassList) {StringBuilder sb = new StringBuilder (); for (Integer I: passList) {sb. append (I);} if (sb. toString (). equals (password) {Toast. makeText (LockActivity. this, correct, Toast. LENGTH_SHORT ). show (); return true;} else {Toast. makeText (LockActivity. this, error, Toast. LENGTH_SHORT ). show (); return false ;}}});}}