Android 短信验证码自动填充
本文主要介绍国外google上线的app 短信自动填充方案。
本方案主要是使用google提出的,防止开发者使用SMS相关权限造成的用户信息泄露
目录
注意点:
1、本方式不适合华为手机,华为有自己的获取方式
2、本方式不需要添加任何短信权限
3、项目版本
开发成本:
Android代码
1、导库
1)在项目根目录的build.gradle中添加下面代码
2)项目级build.gradle引用库
2、注册广播
1)静态注册
2)动态注册
3、启动监听
4、广播代码
其他开发成本
短信模板 (短信后i按加上11位哈市值)
1)命令(mac 命令)
2)代码,放入项目中运行,打包、启动app(注意debug签名与正是签名包的不同,正式的hashcode 需要正式打包,然后打印出来))
注意点:
1、本方式不适合华为手机,华为有自己的获取方式
2、本方式不需要添加任何短信权限
3、项目版本
compileSdkVersion>=34
minSdkVersion>=19
开发成本:
app需要集成两个google库,后端只需要改短信模板,在短信后面添加11位hash值,hash值生成方式在下面链接可以看到
google开发地址(国内需要翻墙)
Android代码
1、导库
1)在项目根目录的build.gradle中添加下面代码
buildscript {repositories {...google()mavenCentral()}
}allprojects {repositories { google()mavenCentral()}
}
2)项目级build.gradle引用库
dependencies {implementation 'com.google.android.gms:play-services-auth:21.2.0'implementation 'com.google.android.gms:play-services-auth-api-phone:18.1.0'
}
2、注册广播
1)静态注册
<receiverandroid:name="<路径>.MySMSBroadcastReceiver"android:exported="true"android:permission="com.google.android.gms.auth.api.phone.permission.SEND"><intent-filter><action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" /></intent-filter></receiver>
2)动态注册
if(smsBrod==null){smsBrod= MySMSBroadcastReceiver(this,null)}val intentFilter = IntentFilter();intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {this@TestAlendActivity.registerReceiver(smsBrod,intentFilter,SmsRetriever.SEND_PERMISSION,null, Context.RECEIVER_EXPORTED)}
3、启动监听
fun googleMSM() {val client = SmsRetriever.getClient(this)val task: Task<Void> = client.startSmsRetriever()task.addOnSuccessListener(OnSuccessListener<Void?> {Log.i("SMS_CON", "googleMSM addOnSuccessListener")if(smsBrod==null){smsBrod= MySMSBroadcastReceiver(this,null)}val intentFilter = IntentFilter();intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {this@TestAlendActivity.registerReceiver(smsBrod,intentFilter,SmsRetriever.SEND_PERMISSION,null, Context.RECEIVER_EXPORTED)}})task.addOnFailureListener(OnFailureListener {Log.i("SMS_CON", "googleMSM addOnFailureListener")})}
4、广播代码
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.Status;import org.json.JSONException;
import org.json.JSONObject;import java.lang.ref.SoftReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** BroadcastReceiver to wait for SMS messages. This can be registered either* in the AndroidManifest or at runtime. Should filter Intents on* SmsRetriever.SMS_RETRIEVED_ACTION.*/
public class MySMSBroadcastReceiver extends BroadcastReceiver {public MySMSBroadcastReceiver() {}@Overridepublic void onReceive(Context context, Intent intent) {Log.i("SMS_CON", "googleMSM MySMSBroadcastReceiver action=" + intent.getAction());if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {Bundle extras = intent.getExtras();Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);Log.i("SMS_CON", "status =" + status);if(status!=null){switch (status.getStatusCode()) {case CommonStatusCodes.SUCCESS:// (Optional) Get SMS Sender address - only available in// GMS version 24.20 onwards, else it will return null
// String senderAddress = extras.getString(SmsRetriever.EXTRA_SMS_ORIGINATING_ADDRESS);// Get SMS message contentsString message = extras.getString(SmsRetriever.EXTRA_SMS_MESSAGE);// Extract one-time code from the message and complete verification// by sending the code back to your server.Log.i("SMS_CON", "message =" + message);if (message != null) {Pattern code = Pattern.compile("(\\d{6})");Matcher matcher = code.matcher(message);String otp = "";if (matcher.find()) {otp = matcher.group(0);} else {otp = message;}Log.i("SMS_CON", "otp =" + otp);Toast.makeText(context,"otp=\n"+otp,Toast.LENGTH_LONG).show();}break;case CommonStatusCodes.TIMEOUT:// Waiting for SMS timed out (5 minutes)// Handle the error ...Log.i("SMS_CON", "TIMEOUT =");break;}}}}
}
其他开发成本
短信模板 (短信后i按加上11位哈市值)
Hash值生成方式
1)命令(mac 命令)
keytool -exportcert -keystore keystory名称.jks -storepass 你的密码 -alias 别名 | xxd -p | tr -d "[:space:]" | echo -n 你的包名 `cat` | shasum -a 256 | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11
2)代码,放入项目中运行,打包、启动app(注意debug签名与正是签名包的不同,正式的hashcode 需要正式打包,然后打印出来))
aab文件也可以通过命令安装到手机,网上搜一下 bundletool.jar 这个工具
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.Base64;
import android.util.Log;import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;public class AppSignatureHashHelper extends ContextWrapper {public static final String TAG = AppSignatureHashHelper.class.getSimpleName();private static final String HASH_TYPE = "SHA-256";public static final int NUM_HASHED_BYTES = 9;public static final int NUM_BASE64_CHAR = 11;public AppSignatureHashHelper(Context context) {super(context);}public ArrayList<String> getAppSignatures() {ArrayList<String> appSignaturesHashs = new ArrayList<>();try {String packageName = getPackageName();PackageManager packageManager = getPackageManager();Signature[] signatures = packageManager.getPackageInfo(packageName,PackageManager.GET_SIGNATURES).signatures;for (Signature signature : signatures) {String hash = hash(packageName, signature.toCharsString());if (hash != null) {appSignaturesHashs.add(String.format("%s", hash));}}} catch (Exception e) {Log.e(TAG, "Package not found", e);}return appSignaturesHashs;}@TargetApi(19)private static String hash(String packageName, String signature) {String appInfo = packageName + " " + signature;try {MessageDigest messageDigest = MessageDigest.getInstance(HASH_TYPE);messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));byte[] hashSignature = messageDigest.digest();hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);return base64Hash;} catch (NoSuchAlgorithmException e) {Log.e(TAG, "No Such Algorithm Exception", e);}return null;}
}
调用方式
String hashcodeStr= AppSignatureHashHelper(this).getAppSignatures()
上面会生成11位hash值,放在短信后面就行了
***以上是获取短信,短信自动填充代码就不写了,拿到字符串 设置到输入框就行,推荐按使用动态注册,可以给广播传入回调接口,处理返回的验证码(otp)
到这里就完成了,上面获取命令的方式是通过自己签名的方式,如果是让google生成签名,则需要去看链接里的步骤,比较详细
测试的话 可以让别人发短信给你 ,在app里会受到广播
相关文章:
Android 短信验证码自动填充
本文主要介绍国外google上线的app 短信自动填充方案。 本方案主要是使用google提出的,防止开发者使用SMS相关权限造成的用户信息泄露 目录 注意点: 1、本方式不适合华为手机,华为有自己的获取方式 2、本方式不需要添加任何短信权限 3、…...
数据库 MySQL 是否需要容器化?
容器的定义:容器是为了解决“在切换运行环境时,如何保证软件能够正常运行”这一问题。 目前,容器和 Docker 依旧是技术领域最热门的词语,无状态的服务容器化已经是大势所趋,同时也带来了一个热点问题被大家所争论不以…...
Kettle的安装及简单使用
Kettle的安装及简单使用一、kettle概述二、kettle安装部署和使用Windows下安装案例1:MySQL to MySQL案例2:使用作业执行上述转换,并且额外在表stu2中添加一条数据案例3:将hive表的数据输出到hdfs案例4:读取hdfs文件并将…...
Golang | Leetcode Golang题解之第420题强密码检验器
题目: 题解: func strongPasswordChecker(password string) int {hasLower, hasUpper, hasDigit : 0, 0, 0for _, ch : range password {if unicode.IsLower(ch) {hasLower 1} else if unicode.IsUpper(ch) {hasUpper 1} else if unicode.IsDigit(ch)…...
面试金典题3
URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。 示例 1: 输入:"Mr John Smith ", 13 输出:"Mr%20John%20Smith&…...
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
Android早期的MediaPlayer控件对于网络视频的兼容性很差,所以后来单独推出了Exoplayer库增强支持网络视频,在《Android Studio开发实战:从零基础到App上线(第3版)》一书第14章的“14.3.3 新型播放器ExoPlayer”就详细介绍了Exoplayer库的详细…...
Python使用总结之py-docx将word文件中的图片保存,并将内容返回
Python使用总结之py-docx将word文件中的图片保存,并将内容返回 使用py-docx读取word文档的内容,其中包含标题、文本和图片等信息。该方法将标题和内容返回,并将文件中的图片保存到指定的文件夹中。 实现步骤 加载文件内容读取文件的段落对文…...
Radware 报告 Web DDoS 攻击活动
新一代 HTTPS 洪水攻击的频率和强度急剧增加,攻击者引入的复杂程度也在迅速提高。2024 年上半年,Web 分布式拒绝服务 (DDoS) 攻击的频率和强度显著增加。其中很大一部分活动可以归因于受政治紧张局势驱使的黑客活动分子。 众所周知,当今的黑…...
OpenCV运动分析和目标跟踪(2)累积操作函数accumulateSquare()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将源图像的平方加到累积器图像中。 该函数将输入图像 src 或其选定区域提升到2的幂次方,然后加到累积器 dst 中: dst ( …...
PCIe进阶之TL:Common Packet Header Fields TLPs with Data Payloads Rules
1 Transaction Layer Protocol - Packet Definition TLP有四种事务类型:Memory、I/O、Configuration 和 Messages,两种地址格式:32bit 和 64bit。 构成 TLP 时,所有标记为 Reserved 的字段(有时缩写为 R)都必须全为0。接收者Rx必须忽略此字段中的值,PCIe Switch 必须对…...
Linux之实战命令01:xargs应用实例(三十五)
简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【…...
Redisson实现分布式锁(看门狗机制)
目录 可重入锁: 锁重试和看门狗机制: 主从一致性: 首先引入依赖,配置好信息 3.使用Redisson的分布式锁 可重入锁: 可重入锁实现是通过redsi中的hash实现的,key依旧是业务名称加id,然后第一个…...
记录一次显卡驱动安装
1. 驱动安装 1.1. 查看适合的版本 apt-get update ubuntu-drivers devices输出结果: 1.2. 安装合适的驱动版本 根据上面输出的内容 apt-get install nvidia-driver-545完成后重启 reboot查看新的驱动 nvidia-smi2. 安装/升级cuda 在nvidia-smi中显示的CUDA…...
nginx的作用是什么
Nginx是一个轻量级、高性能的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,它的作用广泛且重要。以下是Nginx的主要作用: 1. 作为Web服务器 高效处理静态文件:Nginx对静态文件(如HTML、图片…...
【全网最全】2024年华为杯研赛B题成品论文获取入口(后续会更新)
您的点赞收藏是我继续更新的最大动力! 一定要点击如下的卡片,那是获取资料的入口! 点击链接加入【2024华为杯研赛资料汇总】:https://qm.qq.com/q/hMgWngXvcQhttps://qm.qq.com/q/hMgWngXvcQ你是否在寻找数学建模比赛的突破点&a…...
计算机网络(八) —— Udp协议
目录 一,再谈端口号 1.1 端口号 1.2 netsta命令 二,UDP协议 2.1 关于UDP 2.2 Udp协议格式 2.3 Udp协议特点 2.4 Udp的缓冲区 一,再谈端口号 http协议本质是“请求 - 响应”形式的协议,但是应用层需要先将数据交给传输层&…...
【Linux篇】TCP/IP协议(笔记)
目录 一、TCP/IP协议族体系结构 1. 数据链路层 (1)介绍 (2)常用协议 ① ARP协议(Address Resolve Protocol,地址解析协议) ② RARP协议(Reverse Address Resolve Protocol&…...
std::pair和std::tuple
提示:文章 文章目录 前言一、背景二、 2.1 2.2 总结 前言 前期疑问: 本文目标: 一、背景 最近 std::pair和std::tuple 二、用法 1.1 创建 看代码规范,提到:通过std::pair 和std::tuple ,函数可以同…...
Access denied for user ‘root‘@‘114.254.154.110‘ (using password: YES)
navicat 连接远程服务器报错 1045 - Access denied for user root114.254.154.110 (using password: YES)报错解释: 这个错误表示客户端从IP地址114.254.154.110尝试以用户’root’身份连接到MySQL服务器时,被拒绝访问。原因可能是密码错误、用户’roo…...
深度学习03-神经网络01-什么是神经网络?
神经网络的基本概念 人工神经网络(Artificial Neural Network,ANN): 是一种模仿生物神经网络的计算模型。由多个神经元(或称为节点)组成,这些节点通过不同的连接来传递信息。 每个神经元可以接…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
2025.6.9总结(利与弊)
凡事都有两面性。在大厂上班也不例外。今天找开发定位问题,从一个接口人不断溯源到另一个 接口人。有时候,不知道是谁的责任填。将工作内容分的很细,每个人负责其中的一小块。我清楚的意识到,自己就是个可以随时替换的螺丝钉&…...
