|
| 1 | +android-lockpattern 实现原理解析 |
| 2 | +==================================== |
| 3 | +> 本文为 [Android 开源项目实现原理解析](https://github.com/android-cn/android-open-project-analysis) 中 android-lockpattern 部分 |
| 4 | +> 项目地址:[android-lockpattern](https://code.google.com/p/android-lockpattern/),分析的版本:v3.1,Demo 地址:等待添加 |
| 5 | +> 分析者:[爱早起](https://github.com/liang7),校对者:[${校对者}](${校对者 Github 地址}),校对状态:未完成 |
| 6 | +
|
| 7 | +###1. 介绍 |
| 8 | + |
| 9 | +####1.1 关于 |
| 10 | + |
| 11 | +Android的图案密码解锁 |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +####1.2 特点 |
| 16 | + |
| 17 | +- 支持: Android 1.6+ (API 4+). |
| 18 | +- 无特殊依赖. |
| 19 | +- 支持手机与平板的布局. |
| 20 | +- Stealth mode (invisible pattern). |
| 21 | +- 5种主题: |
| 22 | + - Dark/Light |
| 23 | + - Light with dark action bar (API 14+) |
| 24 | + - Dark/Light dialogs |
| 25 | +- 有验证码模式. |
| 26 | + |
| 27 | +###2. 总体设计 |
| 28 | + |
| 29 | +用户只需要做一些配置后启动这个LockPatternActivity就能够使用,对外接口很友好,使用很方便,具体实现请参考下面的分析。 |
| 30 | + |
| 31 | +###3. 流程图 |
| 32 | + |
| 33 | +####3.1 创建解锁图形 |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +####3.2 验证解锁图形 |
| 38 | + |
| 39 | + |
| 40 | + |
| 41 | +###4. 详细设计 |
| 42 | + |
| 43 | +####4.1 类关系图 |
| 44 | + |
| 45 | + |
| 46 | + |
| 47 | +####4.2 核心类功能介绍 |
| 48 | + |
| 49 | +#####4.2.1 LockPatternActivity.java |
| 50 | + |
| 51 | +LockPatternActivity 类负责所有外部请求,根据 `ACTION_CREATE_PATTERN` `ACTION_COMPARE_PATTERN` `ACTION_VERIFY_CAPTCHA` 等Action选择操作模式,加载设置后初始化LockPatternView,在用户完成操作后退出并返回结果。 |
| 52 | + |
| 53 | +主要方法说明: |
| 54 | + |
| 55 | +- public void onCreate(Bundle savedInstanceState) |
| 56 | +首次创建时调用,根据intent设置theme,设置resultIntent,调用loadSettings() initContentView() |
| 57 | +- private void loadSettings() |
| 58 | +根据metaData与Settings类的内容进行显示模式、最少图形点数、自动存储、自定义加密等配置。 |
| 59 | +- private void initContentView() |
| 60 | +根据Aciton与配置信息初始化UI,实例化OnPatternListener设置到LockPatternView类的对象。 |
| 61 | +- private void doCheckAndCreatePattern(final List<Cell> pattern) |
| 62 | +首先检查pattern是否合法,然后判断Intent是否保存有特征码,如果没有就把pattern加密并提取特征码put到Intent,如果有就把特征码解密并与pattern对比,根据对比结果设置UI。 |
| 63 | +- private void doComparePattern(final List<Cell> pattern) |
| 64 | +首先检查pattern是否合法,然后从Intent或者Settings中get特征码,把特征码解密后与pattern对比,成功则调用finishWithResultOk(null),失败次数超过最大次数则调用finishWithNegativeResult(result_failed)。 |
| 65 | +- private void finishWithResultOk(char[] pattern) |
| 66 | +- private void finishWithNegativeResult(int resultCode) |
| 67 | + |
| 68 | +#####4.2.2 LockPatternView.java |
| 69 | + |
| 70 | +LockPatternView 类主要是显示解锁的图形界面,在用户操作的时候显示连线与动画,用户操作完成后根据结果做提示。 |
| 71 | + |
| 72 | +**添加图形点** |
| 73 | + |
| 74 | +- private int getRowHit(float y) |
| 75 | +遍历所有图形点行高,寻找坐标y在哪个图案点的行高范围内。 |
| 76 | +- private int getColumnHit(float x) |
| 77 | +遍历所有图形点列宽,寻找坐标x在哪个图案点的列宽范围内。 |
| 78 | +- private Cell checkForNewHit(float x, float y) |
| 79 | +根据```getRowHit(float y)```与```getColumnHit(float x)```返回的行、列判断是否是新的图形点,如果是返回新点否则返回null。 |
| 80 | +- private Cell detectAndAddHit(float x, float y) |
| 81 | +调用```checkForNewHit(float x, float y)```返回当前图形点,如图形点非null,继续判断pattern list是否为空,如果不为空就把last与当前的图形点之间同一直线的其他点加入list,然后把当前点加入list。 |
| 82 | + |
| 83 | +**按下事件** |
| 84 | + |
| 85 | +- handleActionDown(MotionEvent event) |
| 86 | +首先清理屏幕,获取当前手指的坐标,调用```detectAndAddHit(float x, float y)```并判断其返回值发送通知与局部刷新。 |
| 87 | + |
| 88 | +**移动事件** |
| 89 | + |
| 90 | +- private void handleActionMove(MotionEvent event) |
| 91 | +检查手指移动过程中每一个点的坐标,判断如果pattern list不为空,则把最后一个图形点的坐标与当前手指坐标的区域进行局部刷新,如果在移动过程中加入了新的图形点则以此点坐标继续局部刷新。 |
| 92 | + |
| 93 | +**弹起事件** |
| 94 | + |
| 95 | +- private void handleActionUp(MotionEvent event) |
| 96 | +检查pattern list如果不为空则停止添加,发送完成消息,全局刷新。 |
| 97 | + |
| 98 | +**onDraw** |
| 99 | + |
| 100 | +###5. 对比 |
| 101 | + |
| 102 | +####5.1 与Android source code对比 |
| 103 | + |
| 104 | +待续 |
| 105 | + |
| 106 | +###6. 使用 |
| 107 | + |
| 108 | +####6.1 准备 |
| 109 | +``` |
| 110 | +<activity |
| 111 | + android:name="com.haibison.android.lockpattern.LockPatternActivity" |
| 112 | + android:theme="@style/Alp.42447968.Theme.Dark" /> |
| 113 | +``` |
| 114 | +####6.2 创建图形锁模式 |
| 115 | + |
| 116 | +``` |
| 117 | + private static final int REQ_CREATE_PATTERN = 1; |
| 118 | +
|
| 119 | + Intent intent = new Intent(LockPatternActivity.ACTION_CREATE_PATTERN, null, your-context, LockPatternActivity.class); |
| 120 | + startActivityForResult(intent, REQ_CREATE_PATTERN); |
| 121 | +``` |
| 122 | + |
| 123 | +``` |
| 124 | +
|
| 125 | +@Override |
| 126 | +protected void onActivityResult(int requestCode, int resultCode, |
| 127 | + Intent data) { |
| 128 | + switch (requestCode) { |
| 129 | + case REQ_CREATE_PATTERN: { |
| 130 | + if (resultCode == RESULT_OK) { |
| 131 | + char[] pattern = data.getCharArrayExtra( |
| 132 | + LockPatternActivity.EXTRA_PATTERN); |
| 133 | + ... |
| 134 | + } |
| 135 | + break; |
| 136 | + }// REQ_CREATE_PATTERN |
| 137 | + } |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +####6.3 验证图形锁 |
| 142 | + |
| 143 | +``` |
| 144 | +private static final int REQ_ENTER_PATTERN = 2; |
| 145 | +
|
| 146 | +char[] savedPattern = ... |
| 147 | +
|
| 148 | +Intent intent = new Intent(LockPatternActivity.ACTION_COMPARE_PATTERN, null, |
| 149 | + your-context, LockPatternActivity.class); |
| 150 | +intent.putExtra(LockPatternActivity.EXTRA_PATTERN, savedPattern); |
| 151 | +startActivityForResult(intent, REQ_ENTER_PATTERN); |
| 152 | +``` |
| 153 | + |
| 154 | +``` |
| 155 | +@Override |
| 156 | +protected void onActivityResult(int requestCode, int resultCode, |
| 157 | + Intent data) { |
| 158 | + switch (requestCode) { |
| 159 | + case REQ_ENTER_PATTERN: { |
| 160 | + |
| 161 | + switch (resultCode) { |
| 162 | + case RESULT_OK: |
| 163 | + // The user passed |
| 164 | + break; |
| 165 | + case RESULT_CANCELED: |
| 166 | + // The user cancelled the task |
| 167 | + break; |
| 168 | + case LockPatternActivity.RESULT_FAILED: |
| 169 | + // The user failed to enter the pattern |
| 170 | + break; |
| 171 | + case LockPatternActivity.RESULT_FORGOT_PATTERN: |
| 172 | + // The user forgot the pattern and invoked your recovery Activity. |
| 173 | + break; |
| 174 | + } |
| 175 | +
|
| 176 | + int retryCount = data.getIntExtra( |
| 177 | + LockPatternActivity.EXTRA_RETRY_COUNT, 0); |
| 178 | +
|
| 179 | + break; |
| 180 | + }// REQ_ENTER_PATTERN |
| 181 | + } |
| 182 | +} |
| 183 | +``` |
0 commit comments