前天偶尔运行代码,一个段异常映入眼帘,我擦android10上反射机制监听不到指纹id等数据了,原因是android10彻底抛弃了之前指纹的api。所以反射不到了。

怎么解决这个问题?我们换个思路当然反射依然可以,不过你需要在android9之前和之后的版本写不同的反射代码,首先之前的反射代码都是我抄的别人的,android10现在还没大神奉献,我也写不出来!!!!(这是关键)

所以我想到了,

根据当前指纹库创建一个密钥 判断秘钥状态来判断指纹库是否发生了改变。是不是很神奇,不是原创的,我也是看见别人给了这样一个思路。

我们设计一个吧!

1.设计一个初始化秘钥的方法(这个方法要可以重新生成和重复利用之前秘钥的功能,为什么?你问我为啥?因为要监听改变就要能获取上次的秘钥所以要可以重复利用秘钥,因为一旦指纹变化了,用户可能需要重置指纹重新设置指纹密码,那么就要重新生成新的秘钥。)

2,需要一个判断指纹是否改变的方法,使用cipher去验证刚才的key,如果指纹改变了会抛异常,捕获和这个异常就可以了。

不说废话了上代码:

package cn.lkk.lkk.util;

import android.content.Context;

import android.content.SharedPreferences;

import android.os.Build;

import android.security.keystore.KeyGenParameterSpec;

import android.security.keystore.KeyPermanentlyInvalidatedException;

import android.security.keystore.KeyProperties;

import android.support.annotation.RequiresApi;

import android.text.TextUtils;

import java.io.IOException;

import java.security.InvalidAlgorithmParameterException;

import java.security.InvalidKeyException;

import java.security.KeyStore;

import java.security.KeyStoreException;

import java.security.NoSuchAlgorithmException;

import java.security.NoSuchProviderException;

import java.security.UnrecoverableKeyException;

import java.security.cert.CertificateException;

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import javax.crypto.NoSuchPaddingException;

import javax.crypto.SecretKey;

/**

* @author lkk

* @date 2019/08/23 10:01

*/

@RequiresApi(api = Build.VERSION_CODES.M)

public class CipherHelper

{

private static CipherHelper instance;

private static final String DEFAULT_KEY_NAME = "defaultKey";

private static final String KEYSTORE_ALIAS = "keyStoreAlias";

private static final String HAS_FINGER_KEY = "hasFingerKey";

private KeyGenerator mKeyGenerator;

private KeyStore keyStore;

private CipherHelper()

{

try

{

keyStore = KeyStore.getInstance("AndroidKeyStore");

}

catch (KeyStoreException e)

{

e.printStackTrace();

}

try

{

mKeyGenerator = KeyGenerator

.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

}

catch (NoSuchAlgorithmException | NoSuchProviderException e)

{

throw new RuntimeException("Failed to get an instance of KeyGenerator", e);

}

}

publicstatic CipherHelper getInstance()

{

if (instance == null)

{

synchronized (CipherHelper.class)

{

if (instance == null)

{

instance = new CipherHelper();

}

}

}

return instance;

}

/**

* @des 创建cipher

* @author lkk

* @date 2019/08/23 10:05

*/

publicCipher createCipher()

{

try

{

return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"

+ KeyProperties.BLOCK_MODE_CBC + "/"

+ KeyProperties.ENCRYPTION_PADDING_PKCS7);

}

catch (NoSuchAlgorithmException | NoSuchPaddingException e)

{

e.printStackTrace();

}

return null;

}

/**

* @des 初始化Cipher ,并判断指纹库是否发生了变化

* @author lkk

* @date 2019/08/23 10:17

*/

publicboolean initCipher(Cipher cipher)

{

try

{

keyStore.load(null);

SecretKey key = (SecretKey) keyStore.getKey(KEYSTORE_ALIAS, null);

if (cipher == null)

{

cipher = createCipher();

}

cipher.init(Cipher.ENCRYPT_MODE, key);

return false;

}

catch (KeyPermanentlyInvalidatedException e)

{

return true;

}

catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException

| NoSuchAlgorithmException | InvalidKeyException e)

{

return false;

//throw new RuntimeException("Failed to init Cipher", e);

}

}

/**

* @param context

* @param createNewKey 是否创建新的密钥

* @des 根据当前指纹库创建一个密钥

* @author lkk

* @date 2019/08/23 10:30

*/

publicvoid createKey(Context context, boolean createNewKey)

{

if (context == null)

{

throw new RuntimeException("context can not be null");

}

SharedPreferences sharedPreferences = context.getSharedPreferences(DEFAULT_KEY_NAME, Context.MODE_PRIVATE);

try

{

//首先通过标志位判断用户之前是否创建了密钥,如果已经创建过了并且不需要重新创建就跳过

if (TextUtils.isEmpty(sharedPreferences.getString(HAS_FINGER_KEY, "")) || createNewKey)

{

//创建新密钥

KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(KEYSTORE_ALIAS,

KeyProperties.PURPOSE_ENCRYPT |

KeyProperties.PURPOSE_DECRYPT)

.setBlockModes(KeyProperties.BLOCK_MODE_CBC)

.setUserAuthenticationRequired(true)

.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)

{

builder.setInvalidatedByBiometricEnrollment(true);

}

mKeyGenerator.init(builder.build());

mKeyGenerator.generateKey();

sharedPreferences.edit().putString(HAS_FINGER_KEY, "KEY").apply();

}

}

catch (InvalidAlgorithmParameterException e)

{

//throw new RuntimeException(e);

}

}

}

怎么使用呢?

开始监听

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

mCipher = CipherHelper.getInstance().createCipher();

CipherHelper.getInstance().createKey(getActivity(), false);

}

监听判断

if (CipherHelper.getInstance().initCipher(mCipher)){

//关闭指纹登录

//弹窗告知用户

}

重置监听Key

CipherHelper.getInstance().createKey(getActivity(), true);

android监控指纹信息变化,android监听指纹变化(解决反射思路在android10不生效的问题)...相关推荐

  1. web前端面试高频考点——Vue原理(理解MVVM模型、深度/监听data变化、监听数组变化、深入了解虚拟DOM)

    系列文章目录 内容 参考链接 Vue基本使用 Vue的基本使用(一文掌握Vue最基础的知识点) Vue通信和高级特性 Vue组件间的通信及高级特性(多种组件间的通信.自定义v-model.nextTi ...

  2. js监听html页面大小变化,JS监听窗口变化实时获取浏览器窗口大小

    原理:通过监听窗口的变化来动态获取窗口大小 用到的方法:addEventListener() 监听window的resize事件 js代码: // 定义事件侦听器函数 function watchWi ...

  3. Android 7.0 隐式广播-监听网络变化

    Android7.0前,Android系统前网络切换时,会发广播,业务只要监听广播即可. public class NetChangeReceiver extends BroadcastReceive ...

  4. Android 第十九课 大喇叭--广播机制----动态注册监听网络变化与静态注册实现开机启动

    为了便于进行 系统级别的消息通知,Android引入了一套广播消息机制. 1.广播机制简介: 因为Android中的每个应用程序都可以对自己感兴趣的广播尽心注册,这样程序只会接收自己所关心的广播内容, ...

  5. android 监听图库变化,Android ContentObserver 监听图库变化

    电脑环境是XP,软件是gVim7.3,安装在C盘的 Program Files 下.如何设置gVim的字体和背景颜色:C---Program Files---Vim---_vimrc文件,用文本编辑器 ...

  6. 深入分析Android监听网络变化的坑

    Android开发的同学都知道,在很多场景下我们需要监听网络变化,从而做一些业务逻辑比如刷新数据.于是我们会找到这样一个广播:ConnectivityManager.CONNECTIVITY_ACTI ...

  7. android 监听界面变化,Android之页面有变化用onWindowFocusChanged来监听权限是否开启...

    1 问题 我们需要在Activity里面监听网络变化.热点是否开启和关闭.GPS服务是否开启.位置权限是否开启等一些列行为. 2 思路 方法一: 如果是需要启动activity进行权限申请,我们可以用 ...

  8. Android实现来电和去电的监听

    写个实例实现Android中来电和去电的监听,来电可以使用PhoneStateListener对电话状态的改变进行监听,去电需要动态或者静态去注册广播接收器,对去电进行监听: 来电: 来电所对应的三种 ...

  9. Android 修改系统屏幕亮度及监听

    效果 修改系统屏幕亮度这种操作还是挺常见的,一般在多媒体开发中都多少会涉及到. emmm 效果图好像看不出来变化..不过不是很重要.. 操作拆解 上图中可以看到,分别有加减按钮和seekbar来控制亮 ...

最新文章

  1. ​新型支架状电极允许人类思想操作计算机
  2. Deepin 解决google chrome卡顿的问题
  3. 机器学习分类算法_机器学习分类算法
  4. poj 1836 Alignment
  5. 信息学奥赛一本通 1006:A+B问题 | OpenJudge NOI 1.3 01
  6. cuSPARSE库:(六)cusparseMatrixType_t的说明
  7. 《IS-IS网络设计解决方案》一导读
  8. 4. ex 命令(1)
  9. 获取ul下li标签里点击的是哪一个li并获取li里a标签的值
  10. java前端传汉字到后端出现乱码解决办法
  11. padavan支持惠普打印服务器,Y1S 用了老毛子Padavan连接打印机问题
  12. 跟我学Python图像处理丨带你掌握傅里叶变换原理及实现
  13. Kmplayer的各种功能设置
  14. 中国英语学习论坛(3)
  15. Resnet网络中数字的含义以及连接方式
  16. 移动APP测试经验总结
  17. QCC512x QCC302x earbud工程 LED 配置
  18. 删除linux 中压缩文件
  19. java取当前周期、月初至月末、季度初至季度末日期
  20. 超高清视频体验-4K片源

热门文章

  1. 基于svm图像分类C语言,基于SVM的图像分类算法与实现.PDF
  2. C语言麻将递归,C++数据结构与算法——麻将胡牌算法(二:完全胡牌算法)
  3. CNN常用卷积方法一览
  4. Python应用实战-Clumper库 | Groupby具体案例用法
  5. 程序员有哪些可以写博客的网站?
  6. 【APICloud系列|33】移动应用软件加固步骤,适合所有的安卓应用市场
  7. cpu序列号唯一吗_怎么看电脑硬件是不是新的 有什么软件能检测吗?
  8. visa linux 串口 通信,使用visa进行串口通信
  9. php 正则 回溯,php 正则表达式效率 贪婪、非贪婪与回溯分析
  10. 模态对话框和全选反选