Android 智能手机在全球市场有着极高的市场占有率,越来越受到广大消费者的青睐。但 Android 作为开源操作系统,且很容易可以获得系统 root 权限,Android 系统的安全问题也是用户和开发者最关心的问题之一。
手势密码作为手机上方便的一种安全保护措施,受到了众多 APP 开发者的青睐,市场上一些金融类 APP 基本都配有手势密码,如下图即为手势绘制过程的一个状态。
目前大多数 Android 手机都具有手势锁屏功能,Android 系统自身是带了手势密码功能的,不同的 ROM 厂商做了不同的定制。本文通过Android自身的源码简单介绍手势密码的原理。
Android手势相关类
回忆或者尝试一下用手势解锁 Android 手机的过程:首先用户通过点击九宫格的点连接出一条路径,当手指抬起时,会判断此次连接的点路径是否和设置的相匹配。
在这个过程中,涉及到两个方面(不考虑设置手势时的存储):
- 手势的绘制
- 手势的验证/匹配
针对这两个过程,通过 AOSP 查找源码,我们可以发现两个相关类:
- LockPatternView.java:View类,九宫格手势图形显示的类。
- LockPatternUtils.java:手势转换、匹配工具类。
本篇文章通过分析这两个类中重要的部分来说明手势表示和绘制的原理。
LockPatternView
该类是 View 的子类,其中定义了整个手势绘制区相关的 View,比如九宫格的点、绘制的路径、View 的状态模式、以及手势监听等。类中覆写了 View 父类的 onDraw 方法,点的选中状态、绘制线条都是实时绘制的。
九宫格中的每个「宫」作为静态内部类定义为 Cell,每个 Cell 包括两个坐标,即行(row)和列(column),row 和 column 的范围均在 [0, 3) 内。这样定义的好处,一是利用矩阵的思想来表示九宫格,二是可以把「row 3 + column*」作为 Cell 的值,用 0~8 共 9 个数字来表示九宫格。比如,绘制的路径是 「L」 型,就可以用「03678」来表示这个路径。
public static final class Cell {
final int row;
final int column;
// keep # objects limited to 9
private static final Cell[][] sCells = createCells();
private static Cell[][] createCells() {
Cell[][] res = new Cell[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
res[i][j] = new Cell(i, j);
}
}
return res;
}
/**
* @param row The row of the cell.
* @param column The column of the cell.
*/
private Cell(int row, int column) {
checkRange(row, column);
this.row = row;
this.column = column;
}
public int getRow() {
return row;
}
public int getColumn() {
return column;
}
public static Cell of(int row, int column) {
checkRange(row, column);
return sCells[row][column];
}
private static void checkRange(int row, int column) {
if (row < 0 || row > 2) {
throw new IllegalArgumentException("row must be in range 0-2");
}
if (column < 0 || column > 2) {
throw new IllegalArgumentException("column must be in range 0-2");
}
}
@Override<