├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── attrs.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── alaska.JPG
│ │ │ │ ├── timg.jpg
│ │ │ │ ├── for_one.png
│ │ │ │ ├── for_two.png
│ │ │ │ ├── getmore.png
│ │ │ │ ├── handpsw.png
│ │ │ │ ├── finger_red.png
│ │ │ │ ├── fingerprint.png
│ │ │ │ ├── for_three.png
│ │ │ │ ├── handsetting.png
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── auto_bidding_off.png
│ │ │ │ ├── auto_bidding_on.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── icon_finger_selected.png
│ │ │ │ ├── icon_finger_unselected.png
│ │ │ │ ├── icon_finger_selected_small.png
│ │ │ │ ├── icon_finger_unselected_new.png
│ │ │ │ └── icon_finger_unselected_small.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── back.png
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── drawable
│ │ │ │ ├── tips_bg.xml
│ │ │ │ └── textview_cricle_white.xml
│ │ │ └── layout
│ │ │ │ ├── activity_splash.xml
│ │ │ │ ├── view_toast.xml
│ │ │ │ ├── activity_close_pattern_psw.xml
│ │ │ │ ├── item_dialog.xml
│ │ │ │ ├── activity_setting_pattern_psw.xml
│ │ │ │ ├── activity_verify_finger.xml
│ │ │ │ └── activity_main.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── chaos
│ │ │ │ └── chaossecuritycenter
│ │ │ │ ├── BaseGlideModel.java
│ │ │ │ ├── base
│ │ │ │ └── BaseApplication.java
│ │ │ │ ├── utils
│ │ │ │ ├── MyToast.java
│ │ │ │ ├── BitmapCircleTransformation.java
│ │ │ │ ├── AlertUtil.java
│ │ │ │ └── PreferenceCache.java
│ │ │ │ ├── activity
│ │ │ │ ├── SettingPatternPswActivity.java
│ │ │ │ ├── SplashActivity.java
│ │ │ │ ├── ClosePatternPswActivity.java
│ │ │ │ ├── VerifyFingerActivity.java
│ │ │ │ └── MainActivity.java
│ │ │ │ └── weight
│ │ │ │ └── ChaosGestureView.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── chaos
│ │ │ └── chaossecuritycenter
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── chaos
│ │ └── chaossecuritycenter
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── .idea
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── modules.xml
├── runConfigurations.xml
├── gradle.xml
├── compiler.xml
└── misc.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── README.md
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ChaosSecurityCenter
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/alaska.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/alaska.JPG
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/timg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/timg.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xxhdpi/back.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/for_one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/for_one.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/for_two.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/for_two.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/getmore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/getmore.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/handpsw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/handpsw.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/finger_red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/finger_red.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/fingerprint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/fingerprint.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/for_three.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/for_three.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/handsetting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/handsetting.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/auto_bidding_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/auto_bidding_off.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/auto_bidding_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/auto_bidding_on.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_finger_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/icon_finger_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_finger_unselected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/icon_finger_unselected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_finger_selected_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/icon_finger_selected_small.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_finger_unselected_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/icon_finger_unselected_new.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_finger_unselected_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChaosOctopus/ChaosSecurityCenter/HEAD/app/src/main/res/mipmap-xhdpi/icon_finger_unselected_small.png
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tips_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/textview_cricle_white.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Nov 29 14:10:49 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/BaseGlideModel.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter;
2 |
3 | import com.bumptech.glide.annotation.GlideModule;
4 | import com.bumptech.glide.module.AppGlideModule;
5 |
6 | /**
7 | * Created by yc.Zhao on 2017/11/30 0030.
8 | */
9 | @GlideModule
10 | public class BaseGlideModel extends AppGlideModule {
11 | }
12 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ChaosSecurityCenter
2 | 仿支付宝手势密码,自定义手势密码View
3 |
4 | 
5 |
6 | 
7 |
8 | 
9 |
10 | [简书文章介绍](http://www.jianshu.com/p/ab8a3dbb6982)
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #000
7 | #fff
8 | #333333
9 | #3691ff
10 | #8f00
11 | #6666
12 |
13 |
--------------------------------------------------------------------------------
/app/src/test/java/com/chaos/chaossecuritycenter/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/base/BaseApplication.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.base;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | /**
7 | * Created by yc.Zhao on 2017/11/29 0029.
8 | */
9 |
10 | public class BaseApplication extends Application {
11 | private static Context mAppContext;
12 | @Override
13 | public void onCreate() {
14 | super.onCreate();
15 | mAppContext = getApplicationContext();
16 | }
17 | public static Context getAppContext() {
18 | return mAppContext;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/chaos/chaossecuritycenter/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.chaos.chaossecuritycenter", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\SDK\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/utils/MyToast.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.utils;
2 |
3 | import android.content.Context;
4 | import android.view.Gravity;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.TextView;
8 | import android.widget.Toast;
9 |
10 | import com.chaos.chaossecuritycenter.R;
11 |
12 | public class MyToast extends Toast {
13 |
14 | public MyToast(Context context) {
15 | super(context);
16 | }
17 |
18 | /**
19 | * 生成一个只有文本的自定义Toast
20 | * @param context // 上下文对象
21 | * @param text // 要显示的文字
22 | * @param duration // Toast显示时间
23 | * @return
24 | */
25 | public static MyToast makeTextToast(Context context, CharSequence text, int duration) {
26 | MyToast result = new MyToast(context);
27 | LayoutInflater inflate = (LayoutInflater) context
28 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
29 | View v = inflate.inflate(R.layout.view_toast, null);
30 | TextView tv = (TextView) v.findViewById(android.R.id.message);
31 | tv.setText(text);
32 | result.setView(v);
33 | // setGravity方法用于设置位置,此处为垂直居中
34 | result.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
35 | result.setDuration(duration);
36 | return result;
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_toast.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | buildToolsVersion "26.0.1"
6 | defaultConfig {
7 | applicationId "com.chaos.chaossecuritycenter"
8 | minSdkVersion 16
9 | targetSdkVersion 26
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 | repositories {
22 | mavenCentral()
23 | maven { url 'https://maven.google.com' }
24 | }
25 |
26 | dependencies {
27 | compile fileTree(dir: 'libs', include: ['*.jar'])
28 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
29 | exclude group: 'com.android.support', module: 'support-annotations'
30 | })
31 | compile 'com.android.support:appcompat-v7:26.+'
32 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
33 | compile 'com.wei.android.lib:fingerprintidentify:1.2.1'
34 | testCompile 'junit:junit:4.12'
35 | compile 'com.github.bumptech.glide:glide:4.3.1'
36 | annotationProcessor 'com.github.bumptech.glide:compiler:4.3.1'
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
18 |
19 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
17 |
20 |
21 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_close_pattern_psw.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
18 |
19 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/activity/SettingPatternPswActivity.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.activity;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import com.chaos.chaossecuritycenter.R;
9 | import com.chaos.chaossecuritycenter.utils.PreferenceCache;
10 | import com.chaos.chaossecuritycenter.weight.ChaosGestureView;
11 |
12 | import java.util.List;
13 |
14 | public class SettingPatternPswActivity extends AppCompatActivity implements ChaosGestureView.GestureCallBack{
15 | private TextView tv_back;
16 | private ChaosGestureView gestureView;
17 | private int jumpFlg;
18 | private int flag;
19 | @Override
20 | protected void onCreate(Bundle savedInstanceState) {
21 | super.onCreate(savedInstanceState);
22 | setContentView(R.layout.activity_setting_pattern_psw);
23 | jumpFlg = getIntent().getIntExtra("jumpFlg", 0);
24 | flag = getIntent().getIntExtra("flag", 0);
25 | initView();
26 | }
27 |
28 | private void initView() {
29 | tv_back = (TextView) findViewById(R.id.tv_setting_back);
30 | gestureView = (ChaosGestureView) findViewById(R.id.gesture);
31 | gestureView.setGestureCallBack(this);
32 | //不调用这个方法会造成第二次启动程序直接进入手势识别而不是手势设置
33 | gestureView.clearCache();
34 | tv_back.setOnClickListener(new View.OnClickListener() {
35 | @Override
36 | public void onClick(View view) {
37 | finish();
38 | }
39 | });
40 | }
41 |
42 | @Override
43 | public void gestureVerifySuccessListener(int stateFlag, List data, boolean success) {
44 | if (stateFlag == ChaosGestureView.STATE_LOGIN) {
45 | PreferenceCache.putGestureFlag(true);
46 | finish();
47 | }
48 | }
49 |
50 | @Override
51 | public void onPointerCaptureChanged(boolean hasCapture) {
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/utils/BitmapCircleTransformation.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.utils;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapShader;
6 | import android.graphics.Canvas;
7 | import android.graphics.Paint;
8 |
9 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
10 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
11 |
12 | import java.security.MessageDigest;
13 |
14 | /**
15 | * Created by yc.Zhao on 17/3/19.
16 | */
17 | public class BitmapCircleTransformation extends BitmapTransformation {
18 | public BitmapCircleTransformation(Context context) {
19 | super(context);
20 | }
21 |
22 | @Override
23 | protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
24 | return circleCrop(pool, toTransform);
25 | }
26 |
27 | private Bitmap circleCrop(BitmapPool pool, Bitmap source) {
28 | if (source == null) {
29 | return null;
30 | }
31 | int size = Math.min(source.getWidth(), source.getHeight());
32 | int x = (source.getWidth() - size) / 2;
33 | int y = (source.getHeight() - size) / 2;
34 |
35 | //创建一个正方形的空白bitmap对象,将来在该Bitmap上绘制图案
36 | Bitmap bitmap = pool.get(size, size, Bitmap.Config.ARGB_4444);
37 | if (bitmap == null) {
38 | bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_4444);
39 | }
40 |
41 | Canvas canvas = new Canvas(bitmap);
42 | Paint paint = new Paint();
43 | paint.setAntiAlias(true);
44 |
45 | //选择原图的中心点,裁切出一个正方形区域,将来绘制在空白的bitmap上
46 | Bitmap squared = Bitmap.createBitmap(source , x , y , size , size);
47 | paint.setShader(new BitmapShader(squared , BitmapShader.TileMode.CLAMP , BitmapShader.TileMode.CLAMP));
48 | canvas.drawCircle(size/2 , size/2 , size/2 , paint);
49 | return bitmap;
50 | }
51 |
52 |
53 | @Override
54 | public void updateDiskCacheKey(MessageDigest messageDigest) {
55 |
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
15 |
25 |
35 |
42 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_setting_pattern_psw.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
12 |
22 |
29 |
30 |
31 |
32 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_verify_finger.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
14 |
23 |
33 |
44 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/activity/SplashActivity.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.activity;
2 |
3 | import android.content.Intent;
4 | import android.os.Handler;
5 | import android.os.Message;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.os.Bundle;
8 |
9 | import com.chaos.chaossecuritycenter.R;
10 | import com.chaos.chaossecuritycenter.utils.PreferenceCache;
11 |
12 | import java.lang.ref.WeakReference;
13 |
14 | public class SplashActivity extends AppCompatActivity {
15 | MyHandler myHandler;
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_splash);
20 | myHandler = new MyHandler(this);
21 | myHandler.postDelayed(new Runnable() {
22 | @Override
23 | public void run() {
24 | initJump();
25 |
26 | }
27 | }, 2000);
28 | }
29 |
30 | private void initJump() {
31 | //指纹高优先级
32 | if (PreferenceCache.getFingerFlg()){
33 | //指纹已开启
34 | Intent intent = new Intent(SplashActivity.this,VerifyFingerActivity.class);
35 | startActivity(intent);
36 | finish();
37 | return;
38 | }
39 | if (PreferenceCache.getGestureFlag()){
40 | Intent intent = new Intent(getApplicationContext(),ClosePatternPswActivity.class);
41 | //等于3为认证成功
42 | intent.putExtra("gestureFlg",3);
43 | startActivity(intent);
44 | finish();
45 | return;
46 | }
47 | startActivity(new Intent(getApplicationContext(), MainActivity.class));
48 | finish();
49 | }
50 |
51 | static class MyHandler extends Handler {
52 | private final WeakReference mActivty;
53 |
54 | public MyHandler(SplashActivity activity){
55 | mActivty =new WeakReference(activity);
56 | }
57 |
58 | @Override
59 | public void handleMessage(Message msg) {
60 | super.handleMessage(msg);
61 | }
62 | }
63 |
64 | @Override
65 | protected void onDestroy() {
66 | super.onDestroy();
67 | if(myHandler != null){
68 | myHandler.removeCallbacksAndMessages(null);
69 | myHandler = null;
70 | }
71 | }
72 |
73 | @Override
74 | public void onBackPressed() {
75 | super.onBackPressed();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/activity/ClosePatternPswActivity.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.activity;
2 |
3 | import android.content.Intent;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.widget.TextView;
7 |
8 | import com.chaos.chaossecuritycenter.weight.ChaosGestureView;
9 | import com.chaos.chaossecuritycenter.utils.PreferenceCache;
10 | import com.chaos.chaossecuritycenter.R;
11 | import com.chaos.chaossecuritycenter.utils.AlertUtil;
12 |
13 | import java.util.List;
14 |
15 | public class ClosePatternPswActivity extends AppCompatActivity implements ChaosGestureView.GestureCallBack {
16 | private ChaosGestureView gestureView;
17 | private TextView tv_user_name;
18 | private int gestureFlg = -1;
19 | @Override
20 | protected void onCreate(Bundle savedInstanceState) {
21 | super.onCreate(savedInstanceState);
22 | setContentView(R.layout.activity_close_pattern_psw);
23 |
24 | gestureFlg = getIntent().getIntExtra("gestureFlg", -1);
25 | gestureView = (ChaosGestureView) findViewById(R.id.gesture1);
26 | tv_user_name = (TextView) findViewById(R.id.tv_user_name);
27 | gestureView.setGestureCallBack(ClosePatternPswActivity.this);
28 | gestureView.clearCacheLogin();
29 | }
30 |
31 | @Override
32 | public void gestureVerifySuccessListener(int stateFlag, List data, boolean success) {
33 | if (success) {
34 | if (gestureFlg==1){
35 | //删除密码
36 | PreferenceCache.putGestureFlag(false);
37 | gestureView.clearCache();
38 | AlertUtil.t(ClosePatternPswActivity.this,"清空手势密码成功");
39 | Intent intent = new Intent(ClosePatternPswActivity.this,MainActivity.class);
40 | startActivity(intent);
41 | finish();
42 | }else if (gestureFlg==2){
43 | //修改密码
44 | AlertUtil.t(ClosePatternPswActivity.this,"验证手势密码成功,请重新设置");
45 | Intent intent = new Intent(ClosePatternPswActivity.this,SettingPatternPswActivity.class);
46 | startActivity(intent);
47 | finish();
48 | }else if (gestureFlg==3){
49 | Intent intent = new Intent(ClosePatternPswActivity.this,MainActivity.class);
50 | startActivity(intent);
51 | finish();
52 | }
53 | }else{
54 |
55 | }
56 | }
57 |
58 | @Override
59 | public void onPointerCaptureChanged(boolean hasCapture) {
60 |
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | C:\Users\Administrator\AppData\Roaming\Subversion
48 |
49 |
50 |
51 |
52 |
53 | 1.8
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/utils/AlertUtil.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.utils;
2 |
3 | import android.content.Context;
4 | import android.view.Gravity;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.TextView;
8 | import android.widget.Toast;
9 |
10 | import com.chaos.chaossecuritycenter.R;
11 |
12 | public class AlertUtil {
13 |
14 | private static Toast mToast;
15 |
16 | public static void t(Context context, String msg) {
17 | if (mToast == null) {
18 | mToast = new MyToast(context);
19 | LayoutInflater inflate = (LayoutInflater) context
20 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
21 | View v = inflate.inflate(R.layout.view_toast, null);
22 | TextView tv = (TextView) v.findViewById(android.R.id.message);
23 | tv.setText(msg);
24 | mToast.setView(v);
25 | // setGravity方法用于设置位置,此处为垂直居中
26 | mToast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
27 | mToast.setDuration(Toast.LENGTH_SHORT);
28 | } else {
29 | mToast.setText(msg);
30 | }
31 | mToast.show();
32 | }
33 |
34 | public static void t(Context context, int msgRes) {
35 | if (mToast == null) {
36 | mToast = new MyToast(context);
37 | LayoutInflater inflate = (LayoutInflater) context
38 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
39 | View v = inflate.inflate(R.layout.view_toast, null);
40 | TextView tv = (TextView) v.findViewById(android.R.id.message);
41 | tv.setText(msgRes);
42 | mToast.setView(v);
43 | // setGravity方法用于设置位置,此处为垂直居中
44 | mToast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
45 | mToast.setDuration(Toast.LENGTH_SHORT);
46 | } else {
47 | mToast.setText(msgRes);
48 | }
49 | mToast.show();
50 | }
51 |
52 | public static void t(Context context, int msgRes, int duration) {
53 | Toast mToast = new MyToast(context);
54 | LayoutInflater inflate = (LayoutInflater) context
55 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
56 | View v = inflate.inflate(R.layout.view_toast, null);
57 | TextView tv = (TextView) v.findViewById(android.R.id.message);
58 | tv.setText(msgRes);
59 | mToast.setView(v);
60 | // setGravity方法用于设置位置,此处为垂直居中
61 | mToast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
62 | mToast.setDuration(duration);
63 | mToast.show();
64 | }
65 |
66 | public static void t(Context context, String msg, int duration) {
67 | Toast mToast = new MyToast(context);
68 | LayoutInflater inflate = (LayoutInflater) context
69 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
70 | View v = inflate.inflate(R.layout.view_toast, null);
71 | TextView tv = (TextView) v.findViewById(android.R.id.message);
72 | tv.setText(msg);
73 | mToast.setView(v);
74 | // setGravity方法用于设置位置,此处为垂直居中
75 | mToast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
76 | mToast.setDuration(duration);
77 | mToast.show();
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/activity/VerifyFingerActivity.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.activity;
2 |
3 | import android.app.Dialog;
4 | import android.content.Intent;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.ImageView;
9 | import android.widget.TextView;
10 |
11 | import com.chaos.chaossecuritycenter.GlideApp;
12 | import com.chaos.chaossecuritycenter.R;
13 | import com.chaos.chaossecuritycenter.utils.AlertUtil;
14 | import com.chaos.chaossecuritycenter.utils.BitmapCircleTransformation;
15 | import com.chaos.chaossecuritycenter.utils.PreferenceCache;
16 | import com.wei.android.lib.fingerprintidentify.FingerprintIdentify;
17 | import com.wei.android.lib.fingerprintidentify.base.BaseFingerprint;
18 |
19 | public class VerifyFingerActivity extends AppCompatActivity implements View.OnClickListener {
20 | private ImageView imageView;
21 | private FingerprintIdentify mFingerprintIdentify;
22 | private TextView tv_hand_login;
23 | private Dialog dialog;
24 | private boolean isClick;
25 | private TextView tv_mian_login;
26 | private ImageView iv_finger_icon;
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_verify_finger);
31 | iv_finger_icon = findViewById(R.id.iv_finger_icon);
32 | GlideApp.with(VerifyFingerActivity.this).load(R.mipmap.alaska).transforms(new BitmapCircleTransformation(VerifyFingerActivity.this)).into(iv_finger_icon);
33 | mFingerprintIdentify = new FingerprintIdentify(this);
34 |
35 | //弹出dialog,自动弹出
36 | dialog = new Dialog(VerifyFingerActivity.this, R.style.Dialog);
37 | dialog.setContentView(R.layout.item_dialog);
38 | dialog.setCancelable(false);
39 | dialog.show();
40 | TextView tv = (TextView) dialog.findViewById(R.id.tv_cancel);
41 |
42 | tv.setOnClickListener(new View.OnClickListener() {
43 | @Override
44 | public void onClick(View view) {
45 | dialog.dismiss();
46 | }
47 | });
48 | if (dialog.isShowing()){
49 | initVerify();
50 | }
51 | tv_hand_login = (TextView) findViewById(R.id.tv_hand_login);
52 | if (PreferenceCache.getGestureFlag()){
53 | tv_hand_login.setVisibility(View.VISIBLE);
54 | }else{
55 | tv_hand_login.setVisibility(View.GONE);
56 | }
57 |
58 | tv_hand_login.setOnClickListener(new View.OnClickListener() {
59 | @Override
60 | public void onClick(View view) {
61 | Intent intent = new Intent(getApplicationContext(),ClosePatternPswActivity.class);
62 | //等于3为认证成功
63 | intent.putExtra("gestureFlg",3);
64 | startActivity(intent);
65 | finish();
66 | }
67 | });
68 | imageView = (ImageView) findViewById(R.id.iv_verify_finger);
69 | imageView.setOnClickListener(this);
70 | tv_mian_login = (TextView) findViewById(R.id.tv_mian_login);
71 | tv_mian_login.setOnClickListener(this);
72 |
73 | }
74 |
75 | private void initVerify() {
76 | mFingerprintIdentify.startIdentify(4, new BaseFingerprint.FingerprintIdentifyListener() {
77 | @Override
78 | public void onSucceed() {
79 | Intent intent = new Intent(VerifyFingerActivity.this,MainActivity.class);
80 | startActivity(intent);
81 | finish();
82 | }
83 |
84 | @Override
85 | public void onNotMatch(int availableTimes) {
86 | AlertUtil.t(VerifyFingerActivity.this,"验证失败,您还有"+availableTimes+"次机会");
87 |
88 |
89 | }
90 |
91 | @Override
92 | public void onFailed(boolean isDeviceLocked) {
93 | AlertUtil.t(VerifyFingerActivity.this,"验证失败指纹暂被锁定");
94 | isClick=true;
95 | if (dialog.isShowing()){
96 | dialog.dismiss();
97 | }
98 |
99 |
100 | }
101 |
102 | @Override
103 | public void onStartFailedByDeviceLocked() {
104 | AlertUtil.t(VerifyFingerActivity.this,"验证失败,指纹已被锁定");
105 | }
106 | });
107 | }
108 |
109 | @Override
110 | public void onClick(View view) {
111 | switch (view.getId()){
112 | case R.id.iv_verify_finger:
113 | if (!isClick){
114 | if (!dialog.isShowing()){
115 | dialog.show();
116 | }
117 | }
118 |
119 | break;
120 | case R.id.tv_mian_login:
121 | AlertUtil.t(VerifyFingerActivity.this,"到自己登录页面重新登陆,处理逻辑");
122 | break;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.activity;
2 |
3 | import android.content.Intent;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.ImageView;
8 | import android.widget.LinearLayout;
9 |
10 | import com.chaos.chaossecuritycenter.GlideApp;
11 | import com.chaos.chaossecuritycenter.utils.PreferenceCache;
12 | import com.chaos.chaossecuritycenter.R;
13 | import com.chaos.chaossecuritycenter.utils.AlertUtil;
14 | import com.chaos.chaossecuritycenter.utils.BitmapCircleTransformation;
15 | import com.wei.android.lib.fingerprintidentify.FingerprintIdentify;
16 |
17 | public class MainActivity extends AppCompatActivity implements View.OnClickListener{
18 | private ImageView mIvHandSwitch;
19 | private ImageView mIvFingerSwitch;
20 | private LinearLayout mlinearLayputSetting;
21 | private View mView;
22 | private FingerprintIdentify mFingerprintIdentify;
23 | private ImageView iv_icon_main;
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_main);
28 | initView();
29 | //处理页面
30 | initData();
31 | }
32 |
33 | private void initData() {
34 | if (PreferenceCache.getGestureFlag()){
35 | mIvHandSwitch.setImageResource(R.mipmap.auto_bidding_off);
36 | mlinearLayputSetting.setVisibility(View.VISIBLE);
37 | mView.setVisibility(View.VISIBLE);
38 | }else{
39 | mIvHandSwitch.setImageResource(R.mipmap.auto_bidding_on);
40 | mlinearLayputSetting.setVisibility(View.GONE);
41 | mView.setVisibility(View.GONE);
42 | }
43 |
44 | if (PreferenceCache.getFingerFlg()){
45 | mIvFingerSwitch.setImageResource(R.mipmap.auto_bidding_off);
46 | }else{
47 | mIvFingerSwitch.setImageResource(R.mipmap.auto_bidding_on);
48 | }
49 | }
50 |
51 | private void initView() {
52 | mIvHandSwitch = (ImageView) findViewById(R.id.iv_hand_switch);
53 | mIvFingerSwitch = (ImageView) findViewById(R.id.iv_fingerprint_switch);
54 | mIvFingerSwitch.setOnClickListener(this);
55 | mIvHandSwitch.setOnClickListener(this);
56 | mlinearLayputSetting = (LinearLayout) findViewById(R.id.ll_setting_hand);
57 | mlinearLayputSetting.setOnClickListener(this);
58 | mView = findViewById(R.id.view_second);
59 | mFingerprintIdentify = new FingerprintIdentify(this);
60 | iv_icon_main = findViewById(R.id.iv_icon_main);
61 | GlideApp.with(MainActivity.this).load(R.mipmap.alaska).transforms(new BitmapCircleTransformation(MainActivity.this)).into(iv_icon_main);
62 | }
63 |
64 | @Override
65 | public void onClick(View view) {
66 | switch (view.getId()){
67 | case R.id.iv_hand_switch:
68 | if (!PreferenceCache.getGestureFlag()){
69 | Intent intent = new Intent(MainActivity.this,SettingPatternPswActivity.class);
70 | startActivityForResult(intent,1);
71 | }else{
72 | Intent close_intent = new Intent(MainActivity.this,ClosePatternPswActivity.class);
73 | //等于1为删除密码
74 | close_intent.putExtra("gestureFlg", 1);
75 | startActivityForResult(close_intent,1);
76 | }
77 | break;
78 | case R.id.ll_setting_hand:
79 | Intent intent = new Intent(MainActivity.this,ClosePatternPswActivity.class);
80 | //等于2为修改密码
81 | intent.putExtra("gestureFlg",2);
82 | startActivityForResult(intent,1);
83 | break;
84 | case R.id.iv_fingerprint_switch:
85 | if (mFingerprintIdentify.isHardwareEnable()){
86 | //指纹可用
87 | if (mFingerprintIdentify.isFingerprintEnable()){
88 | if (PreferenceCache.getFingerFlg()){
89 | //取消指纹
90 | mIvFingerSwitch.setImageResource(R.mipmap.auto_bidding_on);
91 | AlertUtil.t(MainActivity.this,"指纹验证功能已取消");
92 | PreferenceCache.putFingerFlg(false);
93 | }else{
94 | //打开指纹
95 | mIvFingerSwitch.setImageResource(R.mipmap.auto_bidding_off);
96 | AlertUtil.t(MainActivity.this,"指纹验证功能已打开");
97 | PreferenceCache.putFingerFlg(true);
98 | }
99 |
100 | }else{
101 | AlertUtil.t(MainActivity.this,"请先去录入指纹");
102 | }
103 | }else{
104 | AlertUtil.t(MainActivity.this,"辣鸡手机,用不了指纹,换手机吧");
105 | }
106 | break;
107 | }
108 |
109 | }
110 |
111 | @Override
112 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
113 | super.onActivityResult(requestCode, resultCode, data);
114 | if (requestCode==1){
115 | initData();
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
19 |
28 |
29 |
35 |
40 |
47 |
56 |
63 |
64 |
67 |
74 |
81 |
90 |
91 |
97 |
98 |
103 |
108 |
115 |
124 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/utils/PreferenceCache.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.content.SharedPreferences.Editor;
6 |
7 | import com.chaos.chaossecuritycenter.base.BaseApplication;
8 |
9 |
10 | public class PreferenceCache {
11 | public static final String PF_TOKEN = "token"; // token
12 | public static final String PF_GUIDE_PAGE = "guide_page";
13 | public static final String PF_VERSION = "";
14 | public static final String PF_AUTO_LOGIN = "auton_login"; // 自动登录
15 | public static final String PF_PHONE_NUM = "phone_number"; // 自动登录
16 | public static final String PF_USERNAME = "username";// 保存上次登录的用户名
17 | public static final String PF_SKIP_LOGIN = "skip_login"; // 跳过登录环节
18 | public static final String PF_MOBILE_VERIFICATION_CODE = "mobile_verification_code"; // 手机验证码
19 | public static final String BANK_OPEN_FLG = "bank_open_flg"; // 登陆后是否跳出dialog提示银行开通账户
20 | public static final String GESTURE_FLG = "gesture_flg"; // 判断是否设置有手势密码
21 | public static final String GESTURE_TIME = "gesture_time"; // 手势密码输入错误超过5次时间
22 | public static final String ACCOUNT_EYE = "account_eye"; // 我的账户页面eye
23 | public static final String FINGEER_FLG="finger_flg";//存储指纹flg
24 |
25 | private static SharedPreferences getSharedPreferences() {
26 | BaseApplication app = (BaseApplication) BaseApplication.getAppContext();
27 | return app.getSharedPreferences("csyh", Context.MODE_PRIVATE);
28 | }
29 | public static void putToken(String token) {
30 | SharedPreferences pref = getSharedPreferences();
31 |
32 | Editor editor = pref.edit();
33 | editor.putString(PF_TOKEN, token);
34 | editor.commit();
35 | }
36 |
37 | public static String getToken() {
38 | return getSharedPreferences().getString(PF_TOKEN, "");
39 | }
40 |
41 | public static void putUsername(String username) {
42 | SharedPreferences pref = getSharedPreferences();
43 |
44 | Editor editor = pref.edit();
45 | editor.putString(PF_USERNAME, username);
46 | editor.commit();
47 | }
48 |
49 | public static String getUsername() {
50 | return getSharedPreferences().getString(PF_USERNAME, "");
51 | }
52 |
53 | public static boolean ifSkipLogin() {
54 | return getSharedPreferences().getBoolean(PF_SKIP_LOGIN, false);
55 | }
56 |
57 | public static void putIfSkipLogin(boolean skipLogin) {
58 | SharedPreferences pref = getSharedPreferences();
59 |
60 | Editor editor = pref.edit();
61 | editor.putBoolean(PF_SKIP_LOGIN, skipLogin);
62 | editor.commit();
63 | }
64 |
65 | public static void putAutoLogin(boolean isAutonLogin) {
66 | SharedPreferences pref = getSharedPreferences();
67 |
68 | Editor editor = pref.edit();
69 | editor.putBoolean(PF_AUTO_LOGIN, isAutonLogin);
70 | editor.commit();
71 | }
72 |
73 | public static boolean isAutoLogin() {
74 | return getSharedPreferences().getBoolean(PF_AUTO_LOGIN, true);
75 | }
76 |
77 | public static void putPhoneNum(String phoneNum) {
78 | SharedPreferences pref = getSharedPreferences();
79 |
80 | Editor editor = pref.edit();
81 | editor.putString(PF_PHONE_NUM, phoneNum);
82 | editor.commit();
83 | }
84 |
85 | public static String getPhoneNum() {
86 | return getSharedPreferences().getString(PF_PHONE_NUM, "");
87 | }
88 |
89 | public static void putGuidePage(boolean guidePage) {
90 | SharedPreferences pref = getSharedPreferences();
91 |
92 | Editor editor = pref.edit();
93 | editor.putBoolean(PF_GUIDE_PAGE, guidePage);
94 | editor.commit();
95 | }
96 |
97 | public static boolean getGuidePage() {
98 | return getSharedPreferences().getBoolean(PF_GUIDE_PAGE, true);
99 | }
100 |
101 | // 版本
102 | public static String getVersion() {
103 | return getSharedPreferences().getString(PF_VERSION, "");
104 | }
105 |
106 | public static void putVersion(String version) {
107 | SharedPreferences pref = getSharedPreferences();
108 | Editor editor = pref.edit();
109 | editor.putString(PF_VERSION, version);
110 | editor.commit();
111 | }
112 |
113 | public static void putVerificationCode(String mobileVerificationCode) {
114 | SharedPreferences pref = getSharedPreferences();
115 |
116 | Editor editor = pref.edit();
117 | editor.putString(PF_MOBILE_VERIFICATION_CODE, mobileVerificationCode);
118 | editor.commit();
119 | }
120 |
121 | public static String getVerificationCode() {
122 | return getSharedPreferences()
123 | .getString(PF_MOBILE_VERIFICATION_CODE, "");
124 | }
125 |
126 |
127 | public static void putBankOpenFlag(boolean flg) {
128 | SharedPreferences pref = getSharedPreferences();
129 |
130 | Editor editor = pref.edit();
131 | editor.putBoolean(BANK_OPEN_FLG, flg);
132 | editor.commit();
133 | }
134 |
135 | public static boolean getBankOpenFlag() {
136 | return getSharedPreferences()
137 | .getBoolean(BANK_OPEN_FLG, false);
138 | }
139 |
140 | public static void putLoginFlag(boolean flg) {
141 | SharedPreferences pref = getSharedPreferences();
142 |
143 | Editor editor = pref.edit();
144 | editor.putBoolean(BANK_OPEN_FLG, flg);
145 | editor.commit();
146 | }
147 |
148 | public static boolean getLoginFlag() {
149 | return getSharedPreferences()
150 | .getBoolean(BANK_OPEN_FLG, false);
151 | }
152 |
153 | public static void putGestureFlag(boolean flg) {
154 | SharedPreferences pref = getSharedPreferences();
155 |
156 | Editor editor = pref.edit();
157 | editor.putBoolean(GESTURE_FLG, flg);
158 | editor.commit();
159 | }
160 |
161 | public static boolean getGestureFlag() {
162 | return getSharedPreferences()
163 | .getBoolean(GESTURE_FLG, false);
164 | }
165 |
166 | public static void putFingerFlg(boolean flg){
167 | SharedPreferences pref = getSharedPreferences();
168 |
169 | Editor editor = pref.edit();
170 | editor.putBoolean(FINGEER_FLG, flg);
171 | editor.commit();
172 | }
173 | public static boolean getFingerFlg(){
174 | return getSharedPreferences()
175 | .getBoolean(FINGEER_FLG, false);
176 | }
177 |
178 | public static void putGestureTime(long time) {
179 | SharedPreferences pref = getSharedPreferences();
180 | Editor editor = pref.edit();
181 | editor.putLong(GESTURE_TIME, time);
182 | editor.commit();
183 | }
184 |
185 | public static long getGestureTime() {
186 | return getSharedPreferences()
187 | .getLong(GESTURE_TIME, 0);
188 | }
189 |
190 | public static void putAccountEye(boolean eyeFlg) {
191 | SharedPreferences pref = getSharedPreferences();
192 | Editor editor = pref.edit();
193 | editor.putBoolean(ACCOUNT_EYE, eyeFlg);
194 | editor.commit();
195 | }
196 |
197 | public static boolean getAccountEye() {
198 | return getSharedPreferences()
199 | .getBoolean(ACCOUNT_EYE, true);
200 | }
201 |
202 | }
203 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chaos/chaossecuritycenter/weight/ChaosGestureView.java:
--------------------------------------------------------------------------------
1 | package com.chaos.chaossecuritycenter.weight;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Bitmap;
8 | import android.graphics.BitmapFactory;
9 | import android.graphics.Canvas;
10 | import android.graphics.Color;
11 | import android.graphics.Paint;
12 | import android.graphics.drawable.BitmapDrawable;
13 | import android.graphics.drawable.Drawable;
14 | import android.os.Handler;
15 | import android.os.Message;
16 | import android.support.annotation.Nullable;
17 | import android.util.AttributeSet;
18 | import android.view.MotionEvent;
19 | import android.view.View;
20 |
21 | import com.chaos.chaossecuritycenter.R;
22 | import com.chaos.chaossecuritycenter.utils.AlertUtil;
23 | import com.chaos.chaossecuritycenter.utils.PreferenceCache;
24 |
25 | import java.util.ArrayList;
26 | import java.util.Date;
27 | import java.util.List;
28 | import java.util.Timer;
29 | import java.util.TimerTask;
30 |
31 | /**
32 | * Created by yc.Zhao on 2017/12/1.
33 | */
34 |
35 | public class ChaosGestureView extends View{
36 | //手势初始化录入状态
37 | public static final int STATE_REGISTER = 101;
38 | //手势确认 使用状态
39 | public static final int STATE_LOGIN = 100;
40 | //设置一个参数记录当前是出于初始化阶段还是使用阶段,默认为确认状态
41 | private int stateFlag = STATE_LOGIN;
42 | //获取上下
43 | private Context mContext;
44 | //定义计时器
45 | private Timer mTimer;
46 | private TimerTask mTimerTask;
47 | //记录是否失败次数超过限制
48 | private boolean mTimeOut;
49 | //剩余的等待时间
50 | private int leftTime;
51 | private int waitTime;
52 | //记录是否手势密码处于可用状态
53 | private boolean mError;
54 | //尝试失败的最大次数 默认为5
55 | private int tempCount;
56 | //最小设置手势的点数
57 | private int minPointNums;
58 | //定义一个接口
59 | private GestureCallBack gestureCallBack;
60 | //定义两个存储的list
61 | private List listDatas;
62 | private List listDatasCopy;
63 |
64 | //用于储存最后一个点的坐标
65 | private GestureBean lastGestrue = null;
66 |
67 | private Bitmap selectedBitmap;
68 | private Bitmap unSelectedBitmap;
69 | private Bitmap selectedBitmapSmall;
70 | private Bitmap unSelectedBitmapSmall;
71 |
72 | //一行3*1单位行高
73 | private float mLineHeight;
74 | //给小手势view留的空间
75 | private static int panelHeight = 300;
76 | //view经过measure之后的宽度
77 | private int mPanelWidth;
78 | //单元控件的宽度
79 | private float pieceWidth;
80 | private float pieceWidthSmall;
81 |
82 | private String message = "请绘制手势";
83 | private float currX;
84 | private float currY;
85 |
86 |
87 | private Paint mPaint;
88 | //接受TimerTask消息,通知UI
89 | private Handler handler = new Handler(){
90 | @Override
91 | public void handleMessage(Message msg) {
92 | leftTime--;
93 | if (leftTime == 0){
94 | if (mTimer != null)
95 | mTimerTask.cancel();
96 | mTimeOut = false;
97 | AlertUtil.t(mContext,"请绘制解锁图案");
98 | mError = false;
99 | invalidate();
100 | //将计时信息还原
101 | reSet();
102 | return;
103 | }
104 | mError = true;
105 | invalidate();
106 | }
107 | };
108 |
109 | private void reSet() {
110 | leftTime = waitTime;
111 | tempCount = 5;
112 | }
113 |
114 | public ChaosGestureView(Context context) {
115 | this(context,null);
116 | }
117 |
118 | public ChaosGestureView(Context context, @Nullable AttributeSet attrs) {
119 | this(context, attrs,0);
120 | }
121 |
122 | public ChaosGestureView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
123 | super(context, attrs, defStyleAttr);
124 | TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.SecurityCenter);
125 | Drawable dw_selected = ta.getDrawable(R.styleable.SecurityCenter_selectedBitmap);
126 | Drawable dw_unSeclect = ta.getDrawable(R.styleable.SecurityCenter_unselectedBitmap);
127 | Drawable dw_selected_small = ta.getDrawable(R.styleable.SecurityCenter_selectedBitmapSmall);
128 | Drawable dw_unSeclect_small = ta.getDrawable(R.styleable.SecurityCenter_unselectedBitmapSmall);
129 | if (dw_selected!=null){
130 | selectedBitmap = ((BitmapDrawable) dw_selected).getBitmap();
131 | }else{
132 | selectedBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_finger_selected);
133 | }
134 | if (dw_unSeclect!=null){
135 | unSelectedBitmap = ((BitmapDrawable) dw_unSeclect).getBitmap();
136 | }else{
137 | unSelectedBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_finger_unselected);
138 | }
139 | if (dw_selected_small!=null){
140 | selectedBitmapSmall = ((BitmapDrawable) dw_selected_small).getBitmap();
141 | }else{
142 | selectedBitmapSmall = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_finger_selected_small);
143 | }
144 | if (dw_unSeclect_small!=null){
145 | unSelectedBitmapSmall= ((BitmapDrawable) dw_unSeclect_small).getBitmap();
146 | }else{
147 | unSelectedBitmapSmall = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_finger_unselected_new);
148 | }
149 | //等待时间,默认30s
150 | waitTime = ta.getInteger(R.styleable.SecurityCenter_waitTime,30);
151 | //尝试次数,默认5
152 | tempCount = ta.getInteger(R.styleable.SecurityCenter_maxFailCounts,5);
153 | //最小设置的点,默认4个
154 | minPointNums = ta.getInteger(R.styleable.SecurityCenter_minPoint,4);
155 | //设置画笔的颜色
156 | mPaint = new Paint();
157 | mPaint.setAntiAlias(true);
158 | mPaint.setDither(true);
159 | mPaint.setStrokeWidth(10);
160 | mPaint.setStyle(Paint.Style.STROKE);
161 | //画笔的颜色
162 | int color = ta.getColor(R.styleable.SecurityCenter_paintColor, context.getResources().getColor(R.color.black));
163 | mPaint.setColor(color);
164 | //字体的大小
165 | float textsize = ta.getDimension(R.styleable.SecurityCenter_paintTextSize, 40);
166 | mPaint.setTextSize(textsize);
167 | //避免重新创建时候的错误
168 | ta.recycle();
169 |
170 | initView(context);
171 | }
172 |
173 | private void initView(Context mContext ) {
174 | this.mContext = mContext;
175 | //让当前的Activity继承View的接口
176 | try {
177 | gestureCallBack = (GestureCallBack) mContext;
178 | } catch (final ClassCastException e) {
179 | throw new ClassCastException(mContext.toString() + " must implement GestureCallBack");
180 | }
181 |
182 | mTimer = new Timer();
183 | //计算上次失败时间与现在的时间差
184 | try {
185 | long lastTime = PreferenceCache.getGestureTime();
186 | Date date = new Date();
187 | if (lastTime !=0 && (date.getTime()-lastTime)/1000();
202 | listDatasCopy = new ArrayList<>();
203 | stateFlag = getState();
204 |
205 | }
206 |
207 | @Override
208 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
209 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
210 | int widthSize = MeasureSpec.getSize(widthMeasureSpec);
211 | int widthMode = MeasureSpec.getMode(widthMeasureSpec);
212 | int heightSize = MeasureSpec.getSize(heightMeasureSpec);
213 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
214 | //width即为大View的单位宽 高
215 | int width = Math.min(widthSize, heightSize);
216 | if (widthMode == MeasureSpec.UNSPECIFIED) {
217 | width = heightSize;
218 | } else if (heightMode == MeasureSpec.UNSPECIFIED) {
219 | width = widthSize;
220 | }
221 | //大View一行3*1单位行高
222 | mLineHeight = width / 3;
223 | //大手势View为边长width的正方形,panelHeight是给小手势view预留的空间
224 | setMeasuredDimension(width, width + panelHeight);
225 | }
226 |
227 |
228 |
229 | @Override
230 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
231 | super.onSizeChanged(w, h, oldw, oldh);
232 | mPanelWidth = Math.min(w, h);
233 | //大手势点宽度,为单位宽高的0.6倍,显得更好看一些不会很满
234 | pieceWidth = (int) (mLineHeight * 0.6f);
235 | //小手势点宽度,同理
236 | pieceWidthSmall = (int) (mLineHeight * 0.15f);
237 | //画出对应手势点的大小
238 | selectedBitmap = Bitmap.createScaledBitmap(selectedBitmap, (int) pieceWidth, (int) pieceWidth, false);
239 | unSelectedBitmap = Bitmap.createScaledBitmap(unSelectedBitmap, (int) pieceWidth, (int) pieceWidth, false);
240 | selectedBitmapSmall = Bitmap.createScaledBitmap(selectedBitmapSmall, (int) pieceWidthSmall, (int) pieceWidthSmall, false);
241 | unSelectedBitmapSmall = Bitmap.createScaledBitmap(unSelectedBitmapSmall, (int) pieceWidthSmall, (int) pieceWidthSmall, false);
242 | }
243 |
244 |
245 | @Override
246 | protected void onDraw(Canvas canvas) {
247 | super.onDraw(canvas);
248 |
249 | //如果处于初始化状态
250 | if (stateFlag == STATE_REGISTER) {
251 | //绘制上面的提示点 不需要提示点
252 | drawTipsPoint(canvas);
253 | } else {
254 | //上面的是文字 点没了
255 | drawTipsText(canvas);
256 | }
257 |
258 | for (int i = 0; i < 3; i++) {
259 | for (int j = 0; j < 3; j++) {
260 | canvas.drawBitmap(unSelectedBitmap, (float) (mLineHeight * (j + 0.5) - pieceWidth / 2), (float) (mLineHeight * (i + 0.5) - pieceWidth / 2 + panelHeight), mPaint);
261 | }
262 | }
263 | //用于判断状态
264 | GestureBean firstGestrue = null;
265 | GestureBean currGestrue = null;
266 | if (!listDatas.isEmpty()) {
267 |
268 | firstGestrue = listDatas.get(0);
269 | //画连接线
270 | for (int i = 1; i < listDatas.size(); i++) {
271 | currGestrue = listDatas.get(i);
272 | canvas.drawLine((float) (mLineHeight * (firstGestrue.getX() + 0.5)), (float) (mLineHeight * (firstGestrue.getY() + 0.5) + panelHeight), (float) (mLineHeight * (currGestrue.getX() + 0.5)), (float) (mLineHeight * (currGestrue.getY() + 0.5) + panelHeight), mPaint);
273 | firstGestrue = currGestrue;
274 | }
275 | //最后一条线
276 | lastGestrue = listDatas.get(listDatas.size() - 1);
277 | canvas.drawLine((float) (mLineHeight * (lastGestrue.getX() + 0.5)), (float) (mLineHeight * (lastGestrue.getY() + 0.5) + panelHeight), currX, currY, mPaint);
278 |
279 | //遍历数组,把把选中的点更换图片
280 | for (GestureBean bean : listDatas) {
281 | canvas.drawBitmap(selectedBitmap, (float) (mLineHeight * (bean.getX() + 0.5) - pieceWidth / 2), (float) (mLineHeight * (bean.getY() + 0.5) + panelHeight - pieceWidth / 2), mPaint);
282 | }
283 | }
284 | }
285 |
286 |
287 | @Override
288 | public boolean onTouchEvent(MotionEvent event) {
289 | //失败情况 不允许操作
290 | if (mTimeOut) {
291 | switch (event.getAction()) {
292 | case MotionEvent.ACTION_DOWN:
293 | break;
294 | case MotionEvent.ACTION_MOVE:
295 | break;
296 | case MotionEvent.ACTION_UP:
297 | if (0 < leftTime && leftTime <= 30) {
298 | AlertUtil.t(mContext, "尝试次数达到最大," + leftTime + "s后重试");
299 | }
300 |
301 | return true;
302 | }
303 | }
304 |
305 | //判断手势点在大View内
306 | if (event.getY() >= ((mLineHeight * (0 + 0.5) - pieceWidth / 2 + panelHeight))) {
307 | //得到XY用于判断 手指处于哪个点
308 | int x = (int) ((event.getY() - panelHeight) / mLineHeight);
309 | int y = (int) (event.getX() / mLineHeight);
310 |
311 | //当前手指的坐标
312 | currX = event.getX();
313 | currY = event.getY();
314 |
315 |
316 | switch (event.getAction()) {
317 | case MotionEvent.ACTION_DOWN:
318 | lastGestrue = null;
319 |
320 | if (currX >= 0 && currX <= mPanelWidth && currY >= panelHeight && currY <= panelHeight + mPanelWidth) {
321 | if (currY <= (x + 0.5) * mLineHeight + pieceWidth / 2 + panelHeight && currY >= (x + 0.5) * mLineHeight - pieceWidth / 2 + panelHeight &&
322 | currX <= (y + 0.5) * mLineHeight + pieceWidth / 2 && currX >= (y + 0.5) * mLineHeight - pieceWidth / 2) {
323 | //判断当前手指处于哪个点范围内,如果点没存在listData,存进去,第一个点
324 | if (!listDatas.contains(new GestureBean(y, x))) {
325 | listDatas.add(new GestureBean(y, x));
326 | }
327 | }
328 | }
329 | //重绘一次,第一个点显示被选中了
330 | invalidate();
331 | break;
332 | case MotionEvent.ACTION_MOVE:
333 | //手指移动在大View范围内
334 | if (currX >= 0 && currX <= mPanelWidth && currY >= panelHeight && currY <= panelHeight + mPanelWidth) {
335 | //缩小响应范围 在此处需要注意的是 x跟currX在物理方向上是反的哦
336 | if (currY <= (x + 0.5) * mLineHeight + pieceWidth / 2 + panelHeight && currY >= (x + 0.5) * mLineHeight - pieceWidth / 2 + panelHeight &&
337 | currX <= (y + 0.5) * mLineHeight + pieceWidth / 2 && currX >= (y + 0.5) * mLineHeight - pieceWidth / 2) {
338 | //滑倒的店处于哪个点范围内,如果点没存在listData,存进去
339 | if (!listDatas.contains(new GestureBean(y, x))) {
340 | listDatas.add(new GestureBean(y, x));
341 | //
342 | }
343 | }
344 | }
345 | //重绘
346 | invalidate();
347 | break;
348 | case MotionEvent.ACTION_UP:
349 | if (lastGestrue != null) {
350 | currX = (float) ((lastGestrue.getX() + 0.5) * mLineHeight);
351 | currY = (float) ((lastGestrue.getY() + 0.5) * mLineHeight);
352 | }
353 |
354 | //如果View处于认证状态
355 | if (stateFlag == STATE_LOGIN) {
356 | //相同那么认证成功
357 | if (listDatas.equals(loadSharedPrefferenceData())) {
358 | mError = false;
359 | postListener(true);
360 | invalidate();
361 | listDatas.clear();
362 | return true;
363 | } else {
364 |
365 | if (--tempCount == 0) {//尝试次数达到上限
366 | mError = true;
367 | mTimeOut = true;
368 | listDatas.clear();
369 | Date date = new Date();
370 | PreferenceCache.putGestureTime(date.getTime());
371 | mTimerTask = new InnerTimerTask(handler);
372 | mTimer.schedule(mTimerTask, 0, 1000);
373 | invalidate();
374 | return true;
375 | }
376 | mError = true;
377 | AlertUtil.t(mContext, "手势错误,还可以再输入" + tempCount + "次");
378 | listDatas.clear();
379 | }
380 |
381 | }
382 | //View处于注册状态
383 | else if (stateFlag == STATE_REGISTER) {
384 | //第一次认证状态
385 | if (listDatasCopy == null || listDatasCopy.isEmpty()) {
386 | if (listDatas.size() < minPointNums) {
387 | listDatas.clear();
388 | mError = true;
389 | AlertUtil.t(mContext, "点数不能小于" + minPointNums + "个");
390 | invalidate();
391 | return true;
392 | }
393 | listDatasCopy.addAll(listDatas);
394 | listDatas.clear();
395 | mError = false;
396 | AlertUtil.t(mContext, "请再一次绘制");
397 | } else {
398 | //两次认证成功
399 | if (listDatas.equals(listDatasCopy)) {
400 | saveToSharedPrefference(listDatas);
401 | mError = false;
402 | stateFlag = STATE_LOGIN;
403 | postListener(true);
404 | saveState();
405 | } else {
406 | mError = true;
407 | AlertUtil.t(mContext, "与上次手势绘制不一致,请重新设置");
408 | }
409 | listDatas.clear();
410 | invalidate();
411 | return true;
412 | }
413 | }
414 | invalidate();
415 | break;
416 | }
417 | }
418 | return true;
419 | }
420 |
421 | //读取之前保存的List
422 | public List loadSharedPrefferenceData() {
423 | List list = new ArrayList<>();
424 | SharedPreferences mSharedPreference = mContext.getSharedPreferences("GESTURAE_DATA", Activity.MODE_PRIVATE);
425 | //取出点数
426 | int size = mSharedPreference.getInt("data_size", 0);
427 | //和坐标
428 | for (int i = 0; i < size; i++) {
429 | String str = mSharedPreference.getString("data_" + i, "0 0");
430 | list.add(new GestureBean(Integer.parseInt(str.split(" ")[0]), Integer.parseInt(str.split(" ")[1])));
431 | }
432 | return list;
433 | }
434 |
435 | //将点的xy list存入sp
436 | private boolean saveToSharedPrefference(List data) {
437 | SharedPreferences sp = mContext.getSharedPreferences("GESTURAE_DATA", Activity.MODE_PRIVATE);
438 | SharedPreferences.Editor edit = sp.edit();
439 | //存入多少个点
440 | edit.putInt("data_size", data.size()); /*sKey is an array*/
441 | //和每个店的坐标
442 | for (int i = 0; i < data.size(); i++) {
443 | edit.remove("data_" + i);
444 | edit.putString("data_" + i, data.get(i).getX() + " " + data.get(i).getY());
445 | }
446 | return edit.commit();
447 | }
448 |
449 |
450 |
451 |
452 | //绘制提示语
453 | private void drawTipsText(Canvas canvas) {
454 | float widthMiddleX = mPanelWidth / 2;
455 | mPaint.setStyle(Paint.Style.FILL);
456 | int widthStr1 = (int) mPaint.measureText("输入手势来解锁");
457 | float baseX = widthMiddleX - widthStr1 / 2;
458 | float baseY = panelHeight / 2 + 50;
459 | Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
460 | float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;
461 | float offY = fontTotalHeight / 2 - fontMetrics.bottom - 30;
462 | float newY = baseY + offY;
463 | canvas.drawText("输入手势来解锁", baseX, newY, mPaint);
464 | mPaint.setAntiAlias(true);
465 | mPaint.setDither(true);
466 | mPaint.setStrokeWidth(10);
467 | }
468 |
469 |
470 |
471 | //绘制提示点
472 | private void drawTipsPoint(Canvas canvas) {
473 | //宽度为View宽度的一半
474 | float widthMiddleX = mPanelWidth / 2;
475 | //确定好相关坐标,找出第一个点的中心点
476 | float firstX = widthMiddleX - pieceWidthSmall / 4 - pieceWidthSmall / 2 - pieceWidthSmall;
477 | float firstY = panelHeight / 2 - pieceWidthSmall / 2 - pieceWidthSmall - pieceWidthSmall / 4 - 10;
478 | //画点,由于没有选中,画9个未选中点
479 | for (int i = 0; i < 3; i++) {
480 | for (int j = 0; j < 3; j++) {
481 | canvas.drawBitmap(unSelectedBitmapSmall, (float) (firstX + j * (pieceWidthSmall * 1.25)), (float) (firstY + i * (pieceWidthSmall * 1.25)), mPaint);
482 | }
483 | }
484 | //第二次确认前的小手势密码·显示第一次划过的痕迹
485 | if (listDatasCopy != null && !listDatasCopy.isEmpty()) {
486 | for (GestureBean bean : listDatasCopy) {
487 | canvas.drawBitmap(selectedBitmapSmall, (float) (firstX + bean.getX() * (pieceWidthSmall * 1.25)), (float) (firstY + bean.getY() * (pieceWidthSmall * 1.25)), mPaint);
488 | }
489 | }
490 | //随着手指ActionMove来改变选中点的颜色
491 | else if (listDatas != null && !listDatas.isEmpty()) {
492 | for (GestureBean bean : listDatas) {
493 | canvas.drawBitmap(selectedBitmapSmall, (float) (firstX + bean.getX() * (pieceWidthSmall * 1.25)), (float) (firstY + bean.getY() * (pieceWidthSmall * 1.25)), mPaint);
494 | }
495 | }
496 | drawMessage(canvas, "绘制解锁图案", mError);
497 | }
498 |
499 | private void drawMessage(Canvas canvas, String message, boolean errorFlag) {
500 | float widthMiddleX = mPanelWidth / 2;
501 | //获取Y坐标显示在小View下面
502 | float firstY = (float) (panelHeight / 2 - pieceWidthSmall / 2 + pieceWidthSmall * 1.25 + 90);
503 |
504 | mPaint.setStrokeWidth(2);
505 | mPaint.setStyle(Paint.Style.FILL);
506 |
507 | //得到字体的宽度
508 | int widthStr1 = (int) mPaint.measureText(message);
509 | float baseX = widthMiddleX - widthStr1 / 2;
510 | float baseY = firstY + 40;
511 | Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
512 | float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;
513 | float offY = fontTotalHeight / 2 - fontMetrics.bottom - 30;
514 | float newY = baseY + offY;
515 | canvas.drawText(message, baseX, newY, mPaint);
516 | mPaint.setAntiAlias(true);
517 | mPaint.setDither(true);
518 | mPaint.setStrokeWidth(10);
519 | }
520 |
521 |
522 |
523 | //从SP中获取当前View处于什么状态,默认为初始化状态
524 | private int getState() {
525 | SharedPreferences mSharedPreference = mContext.getSharedPreferences("STATE_DATA", Activity.MODE_PRIVATE);
526 | return mSharedPreference.getInt("state", STATE_REGISTER);
527 | }
528 | //成功后保存状态
529 | private boolean saveState() {
530 | SharedPreferences sp = mContext.getSharedPreferences("STATE_DATA", Activity.MODE_PRIVATE);
531 | SharedPreferences.Editor edit = sp.edit();
532 | edit.putInt("state", stateFlag);
533 | return edit.commit();
534 | }
535 |
536 | //清除以前保存的状态,用于关闭View
537 | public boolean clearCache() {
538 | SharedPreferences sp = mContext.getSharedPreferences("STATE_DATA", Activity.MODE_PRIVATE);
539 | SharedPreferences.Editor edit = sp.edit();
540 | edit.putInt("state", STATE_REGISTER);
541 | stateFlag = STATE_REGISTER;
542 | invalidate();
543 | return edit.commit();
544 | }
545 | //用于更改手势密码,清除以前密码
546 | public boolean clearCacheLogin() {
547 | SharedPreferences sp = mContext.getSharedPreferences("STATE_DATA", Activity.MODE_PRIVATE);
548 | SharedPreferences.Editor edit = sp.edit();
549 | edit.putInt("state", STATE_LOGIN);
550 | stateFlag = STATE_LOGIN;
551 | invalidate();
552 | return edit.commit();
553 | }
554 |
555 |
556 | //定义一个内部TimerTask类用于记录,错误倒计时
557 | static class InnerTimerTask extends TimerTask{
558 | Handler handler;
559 |
560 | public InnerTimerTask(Handler handler) {
561 | this.handler = handler;
562 | }
563 |
564 | @Override
565 | public void run() {
566 | handler.sendMessage(handler.obtainMessage());
567 | }
568 | }
569 |
570 | //定义接口 ,传递View状态
571 | public interface GestureCallBack{
572 | void gestureVerifySuccessListener(int stateFlag, List data, boolean success);
573 | }
574 |
575 | //给接口传递数据
576 | private void postListener(boolean success) {
577 | if (gestureCallBack != null) {
578 | gestureCallBack.gestureVerifySuccessListener(stateFlag, listDatas, success);
579 | }
580 | }
581 |
582 | //定义Bean,来存储手势坐标
583 | public class GestureBean {
584 | private int x;
585 | private int y;
586 |
587 | @Override
588 | public String toString() {
589 | return "GestureBean{" +
590 | "x=" + x +
591 | ", y=" + y +
592 | '}';
593 | }
594 |
595 | public GestureBean(int x, int y) {
596 | this.x = x;
597 | this.y = y;
598 | }
599 |
600 | public int getX() {
601 | return x;
602 | }
603 |
604 | public void setX(int x) {
605 | this.x = x;
606 | }
607 |
608 | public int getY() {
609 | return y;
610 | }
611 |
612 | public void setY(int y) {
613 | this.y = y;
614 | }
615 |
616 | @Override
617 | public boolean equals(Object o) {
618 | return ((GestureBean) o).getX() == x && ((GestureBean) o).getY() == y;
619 | }
620 | }
621 | public void setGestureCallBack(GestureCallBack gestureCallBack) {
622 | this.gestureCallBack = gestureCallBack;
623 | }
624 |
625 |
626 |
627 | public int getMinPointNums() {
628 | return minPointNums;
629 | }
630 |
631 | public void setMinPointNums(int minPointNums) {
632 | if (minPointNums <= 3)
633 | this.minPointNums = 3;
634 | if (minPointNums >= 9)
635 | this.minPointNums = 9;
636 | }
637 | }
638 |
--------------------------------------------------------------------------------