android监控指纹信息变化,android监听指纹变化(解决反射思路在android10不生效的问题)...
前天偶尔运行代码,一个段异常映入眼帘,我擦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不生效的问题)...相关推荐
- web前端面试高频考点——Vue原理(理解MVVM模型、深度/监听data变化、监听数组变化、深入了解虚拟DOM)
系列文章目录 内容 参考链接 Vue基本使用 Vue的基本使用(一文掌握Vue最基础的知识点) Vue通信和高级特性 Vue组件间的通信及高级特性(多种组件间的通信.自定义v-model.nextTi ...
- js监听html页面大小变化,JS监听窗口变化实时获取浏览器窗口大小
原理:通过监听窗口的变化来动态获取窗口大小 用到的方法:addEventListener() 监听window的resize事件 js代码: // 定义事件侦听器函数 function watchWi ...
- Android 7.0 隐式广播-监听网络变化
Android7.0前,Android系统前网络切换时,会发广播,业务只要监听广播即可. public class NetChangeReceiver extends BroadcastReceive ...
- Android 第十九课 大喇叭--广播机制----动态注册监听网络变化与静态注册实现开机启动
为了便于进行 系统级别的消息通知,Android引入了一套广播消息机制. 1.广播机制简介: 因为Android中的每个应用程序都可以对自己感兴趣的广播尽心注册,这样程序只会接收自己所关心的广播内容, ...
- android 监听图库变化,Android ContentObserver 监听图库变化
电脑环境是XP,软件是gVim7.3,安装在C盘的 Program Files 下.如何设置gVim的字体和背景颜色:C---Program Files---Vim---_vimrc文件,用文本编辑器 ...
- 深入分析Android监听网络变化的坑
Android开发的同学都知道,在很多场景下我们需要监听网络变化,从而做一些业务逻辑比如刷新数据.于是我们会找到这样一个广播:ConnectivityManager.CONNECTIVITY_ACTI ...
- android 监听界面变化,Android之页面有变化用onWindowFocusChanged来监听权限是否开启...
1 问题 我们需要在Activity里面监听网络变化.热点是否开启和关闭.GPS服务是否开启.位置权限是否开启等一些列行为. 2 思路 方法一: 如果是需要启动activity进行权限申请,我们可以用 ...
- Android实现来电和去电的监听
写个实例实现Android中来电和去电的监听,来电可以使用PhoneStateListener对电话状态的改变进行监听,去电需要动态或者静态去注册广播接收器,对去电进行监听: 来电: 来电所对应的三种 ...
- Android 修改系统屏幕亮度及监听
效果 修改系统屏幕亮度这种操作还是挺常见的,一般在多媒体开发中都多少会涉及到. emmm 效果图好像看不出来变化..不过不是很重要.. 操作拆解 上图中可以看到,分别有加减按钮和seekbar来控制亮 ...
最新文章
- ​新型支架状电极允许人类思想操作计算机
- Deepin 解决google chrome卡顿的问题
- 机器学习分类算法_机器学习分类算法
- poj 1836 Alignment
- 信息学奥赛一本通 1006:A+B问题 | OpenJudge NOI 1.3 01
- cuSPARSE库:(六)cusparseMatrixType_t的说明
- 《IS-IS网络设计解决方案》一导读
- 4. ex 命令(1)
- 获取ul下li标签里点击的是哪一个li并获取li里a标签的值
- java前端传汉字到后端出现乱码解决办法
- padavan支持惠普打印服务器,Y1S 用了老毛子Padavan连接打印机问题
- 跟我学Python图像处理丨带你掌握傅里叶变换原理及实现
- Kmplayer的各种功能设置
- 中国英语学习论坛(3)
- Resnet网络中数字的含义以及连接方式
- 移动APP测试经验总结
- QCC512x QCC302x earbud工程 LED 配置
- 删除linux 中压缩文件
- java取当前周期、月初至月末、季度初至季度末日期
- 超高清视频体验-4K片源
热门文章
- 基于svm图像分类C语言,基于SVM的图像分类算法与实现.PDF
- C语言麻将递归,C++数据结构与算法——麻将胡牌算法(二:完全胡牌算法)
- CNN常用卷积方法一览
- Python应用实战-Clumper库 | Groupby具体案例用法
- 程序员有哪些可以写博客的网站?
- 【APICloud系列|33】移动应用软件加固步骤,适合所有的安卓应用市场
- cpu序列号唯一吗_怎么看电脑硬件是不是新的 有什么软件能检测吗?
- visa linux 串口 通信,使用visa进行串口通信
- php 正则 回溯,php 正则表达式效率 贪婪、非贪婪与回溯分析
- 模态对话框和全选反选