Android拾萃Android项目Android快速开发框架

Android开发 多语言、指纹登录、手势登录

2019-04-28  本文已影响602人  艾曼大山
简介

随着互联网的发展不光手机配置越来越高,app产品要求也越来越高了。现在做APP时产品都会让我们加上 多语言、指纹登录、手势登录等功能。下面代码完全适配Android8.0

其它文章

OkHttp3简单使用和封装使用
Retrofit2.0+RxJava2.0封装使用
Android使用IconFont阿里矢量图标
Android Studio 使用SVN 主干和分支合并代码

项目地址:https://github.com/pengjunshan/LanguageFingerprintGesture

效果图

多语言
多语言.gif
指纹登录
指纹登录.gif
手势登录
手势登录.gif
多语言

多语言可以实现国际化,但是并不是app上所有的地方都是用国际化语言,这个根据实际需求来做。这里做的是英语,适配8.0
1.改变app语言环境后需要重新加载资源文件
2.改变app语言环境后杀死进程重启仍是改变后的语言

1.第一步

首先在res资源文件下创建一个英语资源文件,res右键>New>Android Resource Directory(进入第二步)

第一步.png
2.第二步

选择Locale 然后点击箭头选择语言(进入第三步)

第二步.png
3.第三步

滑动Language滚动条可以查看所有支持的语言,然后选择en:English,点击OK(进入第四步)

第三步.png
4.第四步

进行完第三步后可以看到res文件夹下多了一个values-en文件夹,这个就是我们刚创建的英语资源文件,然后我们在此右键创建一个strings文件来存储英语资源。(名字一定要是strings)

第四步
5.第五步

把需要做国际化的资源文件在英语strings.xml中放入响应的资源。
大家看到中文中的资源比英文中的多,中文里会报错提示英文资源文件中少了这个资源,只是警告不影响编译。

资源文件.png
6.第六步

然后开始核心代码,布局中使用两个RadioButton来选择中文||英文。一个保存按钮来修改语言设置和保存到本地标识。
每次进入选择语言界面时先判断当前使用的是什么语言来设置哪个RadioButton为true。

修改语言后一定要重新加载资源,跳到主页面设置Flage为Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK杀死所有activity重新打开主页面 资源也就会重新加载

package com.kelin.languagefingerprintgesture;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatButton;
import android.text.TextUtils;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.kelin.languagefingerprintgesture.utils.LocaleManager;
import com.kelin.languagefingerprintgesture.utils.PreferenceUtils;
/**
 * @author:PengJunShan. 时间:On 2019-04-22.
 *
 * 描述:切换多语言
 */
public class LanguageActivity extends AppCompatActivity {

  @BindView(R.id.rbChinese)
  RadioButton rbChinese;
  @BindView(R.id.rbEnglish)
  RadioButton rbEnglish;
  @BindView(R.id.rgLanguages)
  RadioGroup rgLanguages;
  @BindView(R.id.commit)
  AppCompatButton commit;

  private String mLanguageType;
  private boolean languageType;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_language);
    ButterKnife.bind(this);
    initView();
  }

  private void initView() {
    /**
     * 初始化判断使用的是什么语言
     */
    if (PreferenceUtils.getBoolean("isChinese", true)) {
      rbChinese.setChecked(true);
    } else {
      rbEnglish.setChecked(true);
    }
    /**
     * 监听RadioGroup
     */
    rgLanguages.setOnCheckedChangeListener(new OnCheckedChangeListener() {
      @Override
      public void onCheckedChanged(RadioGroup group, int checkedId) {
        switch (checkedId) {
          case R.id.rbChinese:
            mLanguageType = LocaleManager.LANGUAGE_CHINESE;
            languageType = true;
            break;

          case R.id.rbEnglish:
            mLanguageType = LocaleManager.LANGUAGE_ENGLISH;
            languageType = false;
            break;
        }
      }
    });
  }

  @OnClick(R.id.commit)
  public void onViewClicked() {
    if (!TextUtils.isEmpty(mLanguageType)) {
      /**
       * 修改语言
       */
      LocaleManager.setNewLocale(LanguageActivity.this, mLanguageType);
      /**
       * 保存使用语言标识
       */
      PreferenceUtils.commitBoolean("isChinese", languageType);
      /**
       * 跳转到主页 杀死其它所有的页面 重新加载资源文件
       */
      Intent i = new Intent(LanguageActivity.this, MainActivity.class);
      startActivity(i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK));
      finish();
    }
  }

}

在BaseActivity中重写 @Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleManager.setLocale(base));
}
所有Activity都要继承BaseActivity每次初始化时都会设置Locale

  @Override
  protected void attachBaseContext(Context base) {
    super.attachBaseContext(LocaleManager.setLocale(base));
  }

每次运行app时都要初始化语言设置Locale,一般写在自定义的Application中。

package com.kelin.languagefingerprintgesture.base;

import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import com.kelin.languagefingerprintgesture.utils.LocaleManager;
import com.kelin.languagefingerprintgesture.utils.PreferenceUtils;

/**
 * 作者:PengJunShan.
 *
 * 时间:On 2019-04-22.
 *
 * 描述:
 */
public class MyApplication extends Application {

  public static Context context;

  @Override
  public void onCreate() {
    super.onCreate();
    context = getApplicationContext();
    /**
     * 初始化SP
     */
    PreferenceUtils.init(context, "TRIP");

    /**
     * 初始化语言
     */
    LocaleManager.setLocale(this);
  }

  @Override
  protected void attachBaseContext(Context base) {
    super.attachBaseContext(LocaleManager.setLocale(base));
  }

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    LocaleManager.setLocale(this);
  }

}

核心类LocaleManager类,主要是更新Locale,存取语言标识。代码中都有注释。
这里要说下8.0适配,刚开始写的时候app运行在8.0以下没有问题,8.0则不成功。在android o上,google改变了locale的规则。之前只存在一个locale,而后面是可以支持一个locale list。代码中时修改后的。

package com.kelin.languagefingerprintgesture.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.LocaleList;
import java.util.Locale;

public class LocaleManager {

    /**
     * 中文
     */
    public static final String LANGUAGE_CHINESE = "zh";

    /**
     * 英文
     */
    public static final String LANGUAGE_ENGLISH = "en";

    /**
     * 初始化语言设置
     */
    public static Context setLocale(Context c) {
        return updateResources(c, getLanguage());
    }

    /**
     * 设置语言
     * @param c
     * @param language
     * @return
     */
    public static Context setNewLocale(Context c, String language) {
        persistLanguage(language);
        return updateResources(c, language);
    }

    /**
     * 得到语言设置
     * @return
     */
    public static String getLanguage() {
        return PreferenceUtils.getString(Constants.LANGUAGE_KEY, LANGUAGE_CHINESE);
    }

    /**
     * 存储设置的语言
     * @param language
     */
    @SuppressLint("ApplySharedPref")
    private static void persistLanguage(String language) {
        PreferenceUtils.commitString(Constants.LANGUAGE_KEY, language);
    }

    /**
     * 更新Locale
     * 适配8.0
     * @param language
     * @return
     */
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        Resources res = context.getResources();
        Configuration configuration = res.getConfiguration();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            configuration.setLocale(locale);
            LocaleList localeList = new LocaleList(locale);
            LocaleList.setDefault(localeList);
            configuration.setLocales(localeList);
            context = context.createConfigurationContext(configuration);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            configuration.setLocale(locale);
            context = context.createConfigurationContext(configuration);
        }
        return context;
    }

}
指纹登录

指纹登录可以实现快捷登录,在Android6.0谷歌才提供统一指纹SDK接口,在6.0之前都是各个厂商自定义。
1.开启指纹登录时需验证你的指纹
2.关闭指纹登录时需弹出对话框确认

申请权限

<!-- 指纹权限 -->
  <uses-permission android:name="android.permission.USE_FINGERPRINT"/>

首先判断当前手机设备是否支持指纹解锁,然后判断是否添加过指纹至少添加一个指纹。

FingerprintManagerCompat提供了三个方法:
 /**
   *判断是否支持指纹识别
   */
  public static boolean supportFingerprint(Context mContext) {
    if (VERSION.SDK_INT < 23) {
//      MyToast.showToast("您的系统版本过低,不支持指纹功能");
      return false;
    } else {
      KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
      FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(mContext);
      if (!fingerprintManager.isHardwareDetected()) {
        MyToast.showToast("您的手机不支持指纹功能");
        return false;
      } else if (!keyguardManager.isKeyguardSecure()) {
        MyToast.showToast("您还未设置锁屏,请先设置锁屏并添加一个指纹");
        return false;
      } else if (!fingerprintManager.hasEnrolledFingerprints()) {
        MyToast.showToast("您至少需要在系统设置中添加一个指纹");
        return false;
      }
    }
    return true;
  }

生成一个对称加密的key (下载demo在ToolUtils中)

  @TargetApi(23)
  public static void initKey() {
    try {
      keyStore = KeyStore.getInstance("AndroidKeyStore");
      keyStore.load(null);
      KeyGenerator keyGenerator = KeyGenerator
          .getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
      Builder builder = new Builder(DEFAULT_KEY_NAME,
          KeyProperties.PURPOSE_ENCRYPT |
              KeyProperties.PURPOSE_DECRYPT)
          .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
          .setUserAuthenticationRequired(true)
          .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);
      keyGenerator.init(builder.build());
      keyGenerator.generateKey();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

生成一个Cipher对象,(下载demo在ToolUtils中)

  @TargetApi(23)
  public static Cipher initCipher() {
    try {
      SecretKey key = (SecretKey) keyStore.getKey(DEFAULT_KEY_NAME, null);
      cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
          + KeyProperties.BLOCK_MODE_CBC + "/"
          + KeyProperties.ENCRYPTION_PADDING_PKCS7);
      cipher.init(Cipher.ENCRYPT_MODE, key);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return cipher;
  }

创建FingerprintManagerCompat指纹管理工具类,谷歌已经不推荐使用FingerprintManager类。

FingerprintManagerCompat fingerprintManagerCompat =  FingerprintManagerCompat.from(mActivity);

拿到FingerprintManagerCompat对象后就可以调authenticate方法进行指纹识别了,先看下官网给的参数。

图片.png
 FingerprintManagerCompat.CryptoObject cryptoObject = new FingerprintManagerCompat.CryptoObject(cipher);
CancellationSignal mCancellationSignal = new CancellationSignal();
//识别过程中可以手动取消指纹识别
// mCancellationSignal.cancel();
 public class MyCallBack extends FingerprintManagerCompat.AuthenticationCallback {

        // 当出现错误的时候回调此函数,比如多次尝试都失败了的时候,errString是错误信息
        @Override
        public void onAuthenticationError(int errMsgId, CharSequence errString) {
            if (!isSelfCancelled) {
                errorMsg.setText(errString);
                Log.e("TAG", "errMsgId="+errMsgId);
                Toast.makeText(mActivity, "errMsgId="+errMsgId, Toast.LENGTH_SHORT).show();
                if (errMsgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) {
                    Log.e("TAG", ""+errString);
                    dismiss();
                }
            }
        }

        // 当指纹验证失败的时候会回调此函数,失败之后允许多次尝试,失败次数过多会停止响应一段时间然后再停止sensor的工作
        @Override
        public void onAuthenticationFailed() {
            errorMsg.setText("指纹认证失败,请再试一次");
            Log.e("TAG", "onAuthenticationFailed");
        }

        //错误时提示帮助,比如说指纹错误,我们将显示在界面上 让用户知道情况
        @Override
        public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
            errorMsg.setText(helpString);
            Log.e("TAG", "helpString="+helpString);
        }

        // 当验证的指纹成功时会回调此函数,然后不再监听指纹sensor
        @Override
        public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
            if(onFingerprintSetting!=null) {
                onFingerprintSetting.onFingerprint(true);
            }
            dismiss();
        }
    }

这里就要介绍的是上面提到的FingerprintManagerCompat.AuthenticationCallback了,因为扫描指纹和认证的过程都是在另外一个进程中完成的,所以我们需要采取异步的方式,等操作完成之后,让系统回调给我们,回调方法就是AuthenticationCallback类中的4个方法了

手势解锁

手势登录就是保存手势设置的密码,解锁时进行对比。
我的这个手势解锁是用的别人写好的我拿来稍稍修改一下,大神项目连接GestureLockView
我的demo中使用思路:
1.设置手势密码时,两次手势不同时手势路径变红+震动,可以重置。
2.修改密码时,需验证是否是本人。
3.解锁时,手势错误时手势路径变红+震动。

震动权限

<!-- 震动权限 -->
  <uses-permission android:name="android.permission.VIBRATE"/>

设置手势密码布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  >
  <android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    >
    <!--设置手势解锁时提示view-->
 <com.kelin.languagefingerprintgesture.gesture.GestureLockDisplayView
      android:id="@+id/display_view"
      android:layout_width="50dp"
      android:layout_height="50dp"
      android:layout_gravity="center_horizontal"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      />

    <TextView
      android:id="@+id/setting_hint"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center_horizontal"
      android:layout_marginTop="10dp"
      android:text="绘制解锁图案"
      app:layout_constraintTop_toBottomOf="@+id/display_view"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      />

    <TextView
      android:id="@+id/hintTV"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="与第一次设置密码不同,请再次设置"
      android:textColor="#FC6265"
      android:textSize="14sp"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/setting_hint"
      android:layout_marginTop="10dp"
      android:visibility="invisible"
      />

    <!--手势解锁view-->
    <com.kelin.languagefingerprintgesture.gesture.GestureLockLayout
      android:id="@+id/gesture_view"
      android:layout_width="300dp"
      android:layout_height="300dp"
      app:layout_constraintTop_toBottomOf="@+id/hintTV"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      />


    <TextView
      android:id="@+id/reSet"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="重新设置"
      app:layout_constraintTop_toBottomOf="@+id/gesture_view"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      android:textSize="16sp"
      android:textColor="#333333"
      android:layout_marginTop="10dp"
      />
  </android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>

设置手势密码,activity中初始化控件,监听手势密码

package com.kelin.languagefingerprintgesture;

import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.kelin.languagefingerprintgesture.gesture.GestureLockDisplayView;
import com.kelin.languagefingerprintgesture.gesture.GestureLockLayout;
import com.kelin.languagefingerprintgesture.gesture.GestureLockLayout.OnLockResetListener;
import com.kelin.languagefingerprintgesture.utils.Constants;
import com.kelin.languagefingerprintgesture.utils.PreferenceUtils;
import com.kelin.languagefingerprintgesture.utils.ToolUtils;
import java.util.ArrayList;
import java.util.List;

/**
 * @author:PengJunShan.

 * 时间:On 2019-04-22.

 * 描述:手势登录
 */
public class SetGestureLockActivity extends AppCompatActivity {

  @BindView(R.id.display_view)
  GestureLockDisplayView mLockDisplayView;
  @BindView(R.id.setting_hint)
  TextView mSettingHintText;
  @BindView(R.id.gesture_view)
  GestureLockLayout mGestureLockLayout;
  @BindView(R.id.reSet)
  TextView reSet;
  @BindView(R.id.hintTV)
  TextView hintTV;
  private Animation animation;
  private Context mContext;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_gesture_login);
    ButterKnife.bind(this);
    initView();
  }

  private void initView() {
    mContext = this;
    //设置提示view 每行每列点的个数
    mLockDisplayView.setDotCount(3);
    //设置提示view 选中状态的颜色
    mLockDisplayView.setDotSelectedColor(Color.parseColor("#01367A"));
    //设置提示view 非选中状态的颜色
    mLockDisplayView.setDotUnSelectedColor(Color.parseColor("#999999"));
    //设置手势解锁view 每行每列点的个数
    mGestureLockLayout.setDotCount(3);
    //设置手势解锁view 最少连接数
    mGestureLockLayout.setMinCount(4);
    //设置手势解锁view 模式为重置密码模式
    mGestureLockLayout.setMode(GestureLockLayout.RESET_MODE);

    //初始化动画
    animation = AnimationUtils.loadAnimation(this, R.anim.shake);
    initEvents();
  }

  private void initEvents() {

    mGestureLockLayout.setOnLockResetListener(new OnLockResetListener() {
      @Override
      public void onConnectCountUnmatched(int connectCount, int minCount) {
        //连接数小于最小连接数时调用
        mSettingHintText.setText("最少连接" + minCount + "个点");
        resetGesture();
      }

      @Override
      public void onFirstPasswordFinished(List<Integer> answerList) {
        //第一次绘制手势成功时调用
        Log.e("TAG","第一次密码=" + answerList);
        mSettingHintText.setText("确认解锁图案");
        //将答案设置给提示view
        mLockDisplayView.setAnswer(answerList);
        //重置
        resetGesture();
      }

      @Override
      public void onSetPasswordFinished(boolean isMatched, List<Integer> answerList) {
        //第二次密码绘制成功时调用
        Log.e("TAG","第二次密码=" + answerList.toString());
        if (isMatched) {
          //两次答案一致,保存
          PreferenceUtils.commitString(Constants.GESTURELOCK_KEY, answerList.toString());
          setResult(RESULT_OK);
          finish();
        } else {
          hintTV.setVisibility(View.VISIBLE);
          ToolUtils.setVibrate(mContext);
          hintTV.startAnimation(animation);
          mGestureLockLayout.startAnimation(animation);
          resetGesture();
        }
      }
    });
  }

  /**
   * 重置手势布局(只是布局)
   */
  private void resetGesture() {
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        mGestureLockLayout.resetGesture();
      }
    }, 300);
  }

  /**
   * 重置手势布局(布局加逻辑)
   */
  @OnClick(R.id.reSet)
  public void onViewClicked() {
    mGestureLockLayout.setOnLockResetListener(null);
    mSettingHintText.setText("绘制解锁图案");
    mLockDisplayView.setAnswer(new ArrayList<Integer>());
    mGestureLockLayout.resetGesture();
    mGestureLockLayout.setMode(GestureLockLayout.RESET_MODE);
    hintTV.setVisibility(View.INVISIBLE);
    initEvents();
  }

}

录制GIF

手势解锁+指纹解锁布局,一般解锁时手势和指纹在一个activity中显示。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  >

  <android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    >
    <TextView
      android:id="@+id/name"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="152****2877 下午好"
      android:textColor="#333"
      android:textStyle="bold"
      android:textSize="18sp"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      android:visibility="invisible"
      />

    <TextView
      android:id="@+id/hintTV"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="您还有5次机会"
      android:textColor="#FC6265"
      android:textSize="14sp"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/name"
      android:layout_marginTop="30dp"
      android:visibility="invisible"
      />

    <com.kelin.languagefingerprintgesture.gesture.GestureLockLayout
      android:id="@+id/gestureLock"
      android:layout_width="300dp"
      android:layout_height="300dp"
      android:layout_gravity="center_horizontal"
      android:layout_marginTop="20dp"
      app:layout_constraintTop_toBottomOf="@+id/hintTV"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      />

    <android.support.constraint.Group
      android:id="@+id/group"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:constraint_referenced_ids="name,gestureLock"
      android:visibility="visible"
      />
  </android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>

手势解锁 activity中初始化控件 监听手势信息

package com.kelin.languagefingerprintgesture;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.constraint.Group;
import android.text.TextUtils;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.kelin.languagefingerprintgesture.FingerprintDialogFragment.OnFingerprintSetting;
import com.kelin.languagefingerprintgesture.base.BaseActivity;
import com.kelin.languagefingerprintgesture.gesture.GestureLockLayout;
import com.kelin.languagefingerprintgesture.gesture.GestureLockLayout.OnLockVerifyListener;
import com.kelin.languagefingerprintgesture.utils.Constants;
import com.kelin.languagefingerprintgesture.utils.MyToast;
import com.kelin.languagefingerprintgesture.utils.PreferenceUtils;
import com.kelin.languagefingerprintgesture.utils.ToolUtils;
import javax.crypto.Cipher;
/**
 * @author:PengJunShan.

 * 时间:On 2019-04-26.

 * 描述:解锁
 */
public class GestureLockActivity extends BaseActivity {
  @BindView(R.id.gestureLock)
  GestureLockLayout mGestureLockLayout;
  @BindView(R.id.hintTV)
  TextView hintTV;
  @BindView(R.id.name)
  TextView name;
  @BindView(R.id.group)
  Group group;
  private Context mContext;
  private Animation animation;

  /**
   * 最大解锁次数
   */
  private int mNumber = 5;
  /**
   * change:修改手势  login:登录
   */
  private String type;

  /**
   * true:设置   false:未设置
   */
  private Boolean isFingerprint, isGesture;

  private FingerprintDialogFragment dialogFragment;
  private Cipher cipher;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_gesture_lock);
    ButterKnife.bind(this);
    initView();
  }

  protected void initView() {
    mContext = this;
    type = getIntent().getStringExtra("type");
    isGesture = PreferenceUtils.getBoolean(Constants.ISGESTURELOCK_KEY, false);
    isFingerprint = PreferenceUtils.getBoolean(Constants.ISFINGERPRINT_KEY, false);
    if (isGesture) {
      group.setVisibility(View.VISIBLE);
      setGestureListener();
    }

    if ("login".equals(type) && isFingerprint) {
      setFingerprint();
    }

  }

  private void setFingerprint() {
    if (ToolUtils.supportFingerprint(this)) {
      ToolUtils.initKey(); //生成一个对称加密的key
      //生成一个Cipher对象
      cipher = ToolUtils.initCipher();
    }
    if (cipher != null) {
      showFingerPrintDialog(cipher);
    }
  }

  private void showFingerPrintDialog(Cipher cipher) {
    dialogFragment = new FingerprintDialogFragment();
    dialogFragment.setCipher(cipher);
    dialogFragment.show(getSupportFragmentManager(), "fingerprint");

    dialogFragment.setOnFingerprintSetting(new OnFingerprintSetting() {
      @Override
      public void onFingerprint(boolean isSucceed) {
        if (isSucceed) {
          MyToast.showToastLong("指纹解锁成功!");
          startActivity(MainActivity.class);
          finish();
        } else {
          MyToast.showToastLong("指纹解锁失败!");
        }
      }
    });
  }

  private void setGestureListener() {
    String gestureLockPwd = PreferenceUtils.getString(Constants.GESTURELOCK_KEY, "");
    if (!TextUtils.isEmpty(gestureLockPwd)) {
      mGestureLockLayout.setAnswer(gestureLockPwd);
    } else {
      MyToast.showToast("没有设置过手势密码");
    }
    mGestureLockLayout.setDotCount(3);
    mGestureLockLayout.setMode(GestureLockLayout.VERIFY_MODE);
    //设置手势解锁最大尝试次数 默认 5
    mGestureLockLayout.setTryTimes(5);
    animation = AnimationUtils.loadAnimation(this, R.anim.shake);
    mGestureLockLayout.setOnLockVerifyListener(new OnLockVerifyListener() {
      @Override
      public void onGestureSelected(int id) {
        //每选中一个点时调用
      }

      @Override
      public void onGestureFinished(boolean isMatched) {
        //绘制手势解锁完成时调用
        if (isMatched) {
          if ("change".equals(type)) {
            startActivity(SetGestureLockActivity.class);
          } else if ("login".equals(type)) {
            startActivity(MainActivity.class);
          }
          finish();
        } else {
          hintTV.setVisibility(View.VISIBLE);
          mNumber = --mNumber;
          hintTV.setText("你还有" + mNumber + "次机会");
          hintTV.startAnimation(animation);
          mGestureLockLayout.startAnimation(animation);
          ToolUtils.setVibrate(mContext);
        }
        resetGesture();
      }

      @Override
      public void onGestureTryTimesBoundary() {
        //超出最大尝试次数时调用
        mGestureLockLayout.setTouchable(false);
      }
    });
  }

  /**
   * 重置手势布局(只是布局)
   */
  private void resetGesture() {
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        mGestureLockLayout.resetGesture();
      }
    }, 300);
  }

}

项目地址:https://github.com/pengjunshan/LanguageFingerprintGesture

点击下方喜欢收藏,万一后期项目用得到呢
谢谢进入我的博客,请多多点评
上一篇下一篇

猜你喜欢

热点阅读