Android 中获取和读取短信验证码
方法一:通过
SMS Retriever API
SMS Retriever API 是 Google 提供的一种安全的方式,可以从系统中获取不需要权限的短信验证码。这种方式不需要请求 READ_SMS 权限,非常适合处理短信验证码的情况。
1. 在 build.gradle 中添加依赖
dependencies {implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.1'
}
2. 获取应用的哈希值
Google 的 SMS Retriever API 会通过一个特定的哈希值来验证短信的来源。获取这个哈希值后,将其附加在发送的短信中。
private String getAppHashKey() {try {PackageInfo info = getPackageManager().getPackageInfo(getPackageName(),PackageManager.GET_SIGNATURES);for (Signature signature : info.signatures) {MessageDigest md = MessageDigest.getInstance("SHA");md.update(signature.toByteArray());return Base64.encodeToString(md.digest(), Base64.NO_WRAP).substring(0, 9);}} catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {e.printStackTrace();}return null;
}
3. 开启 SMS Retriever
SmsRetrieverClient client = SmsRetriever.getClient(this);
Task<Void> task = client.startSmsRetriever();
task.addOnSuccessListener(new OnSuccessListener<Void>() {@Overridepublic void onSuccess(Void aVoid) {// 成功启动 SMS Retriever}
});
task.addOnFailureListener(new OnFailureListener() {@Overridepublic void onFailure(@NonNull Exception e) {// 启动失败}
});
4. 接收短信
注册一个 BroadcastReceiver 来监听 SMS Retriever API 的广播
public class MySmsBroadcastReceiver extends BroadcastReceiver {private SmsReceiverListener listener;public void setSmsReceiverListener(SmsReceiverListener listener) {this.listener = listener;}@Overridepublic void onReceive(Context context, Intent intent) {if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {Bundle extras = intent.getExtras();Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);switch (status.getStatusCode()) {case CommonStatusCodes.SUCCESS:// 获取短信String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);if (listener != null) {listener.onSmsReceived(message);}break;case CommonStatusCodes.TIMEOUT:// 超时break;}}}
}
5. 处理短信中的验证码
使用正则表达式提取验证码
Pattern pattern = Pattern.compile("\\d{6}");
Matcher matcher = pattern.matcher(message);
if (matcher.find()) {String code = matcher.group(0);// 使用验证码
}
短信格式:
通过 SMS Retriever API,需要确保短信的格式包含应用的哈希值,例如:
Your verification code is 123456.
<#> Your App Name: Use this code to verify your phone number.
abc123xyz (Your App's hash key)
在使用 SMS Retriever API 获取短信验证码时,短信必须包含应用的哈希值,这样 Android 系统才能识别出该短信是由你应用发送的,并自动从系统短信中提取该短信
abc123xyz 是通过应用的签名生成的哈希值
哈希值用于验证短信的来源,确保是从与你应用关联的服务器发送的短信,而不是其他来源伪造的。系统通过这个哈希值自动识别和提取短信内容,不需要用户手动输入验证码。
6.哈希值生成步骤
-
获取应用的签名证书:应用的哈希值是根据应用的签名证书生成的。在 Android 中,每个应用都有一个签名证书,用来唯一标识应用。
SMS Retriever API通过应用的签名证书来生成哈希值。 -
使用 Java 代码生成哈希值:可以在应用的
Activity或Utils类中调用它
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.Base64;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class AppSignatureHelper {private static final String HASH_TYPE = "SHA-256";private static final int NUM_HASHED_BYTES = 9;private static final int NUM_BASE64_CHAR = 11;public static String getAppHashKey(Context context) {try {// 获取应用包的信息PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),PackageManager.GET_SIGNATURES);// 遍历签名信息for (Signature signature : packageInfo.signatures) {byte[] signatureBytes = signature.toByteArray();// 通过SHA-256进行哈希计算MessageDigest md = MessageDigest.getInstance(HASH_TYPE);md.update(signatureBytes);byte[] digest = md.digest();// 将哈希值编码为Base64格式,取前11位作为哈希值return Base64.encodeToString(digest, Base64.NO_WRAP).substring(0, NUM_BASE64_CHAR);}} catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {e.printStackTrace();}return null;}
}
-
调用哈希值生成方法
在应用启动时或者短信发送前调用此方法,获取哈希值。这个哈希值需要包含在发送的短信中
String hashKey = AppSignatureHelper.getAppHashKey(context);
Log.d("AppHashKey", "Hash Key: " + hashKey);
-
将哈希值添加到短信内容中
将生成的哈希值附加到短信的末尾
Your verification code is 123456.
<#> MyApp: Use this code to verify your phone number.
abc123xyz (Your App's hash key)
方法二:通过读取短信权限 (
READ_SMS)
这种方法需要获取读取短信的权限,但由于隐私和安全问题,Google 对读取短信的权限要求非常严格,并且 Android 6.0 以上的版本还需要动态申请权限。
1. 在 AndroidManifest.xml 中添加权限
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
2. 动态申请权限(针对 Android 6.0 及以上)
public class SmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {Bundle bundle = intent.getExtras();if (bundle != null) {Object[] pdus = (Object[]) bundle.get("pdus");for (Object pdu : pdus) {SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu);String sender = message.getDisplayOriginatingAddress();String content = message.getMessageBody();// 处理短信内容,提取验证码}}}}
}
3. 注册一个 BroadcastReceiver 来监听收到的短信
public class SmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {Bundle bundle = intent.getExtras();if (bundle != null) {Object[] pdus = (Object[]) bundle.get("pdus");for (Object pdu : pdus) {SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu);String sender = message.getDisplayOriginatingAddress();String content = message.getMessageBody();// 处理短信内容,提取验证码}}}}
}
4. 提取短信验证码
与 SMS Retriever API 类似,可以使用正则表达式提取验证码。
总结
SMS Retriever API是更加推荐的方法,因为它不需要读取短信的权限,更加安全。- 读取短信权限 方法需要申请敏感权限,使用较少。
相关文章:
Android 中获取和读取短信验证码
方法一:通过 SMS Retriever API SMS Retriever API 是 Google 提供的一种安全的方式,可以从系统中获取不需要权限的短信验证码。这种方式不需要请求 READ_SMS 权限,非常适合处理短信验证码的情况。 1. 在 build.gradle 中添加依赖 dependen…...
SQL语句高级查询(适用于新手)
SQL查询语句的下载脚本链接!!! 【免费】SQL练习资源-具体练习操作可以查看我发布的文章资源-CSDN文库https://download.csdn.net/download/Z0412_J0103/89908378 本文旨在为那些编程基础相对薄弱的朋友们提供一份详尽的指南,特别聚…...
main.ts中引入App.vue报错,提示“Cannot find module ‘./App.vue’ or its corresponding type
原因 代码编辑器:vscode ,使用vue3,所以安装了 Volar 插件,可以使 vue 代码高亮显示,不同颜色区分代码块,以及语法错误提示等 提示:如果使用的是vue2,则使用 Vetur 插件࿱…...
Android15音频进阶之组音量调试(九十)
简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+…...
【Java】常用方法合集
以 DemoVo 为实体 import lombok.Data; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;Data ExcelIgnoreUnannotated public class ExportPromoteUnitResult {private String id;ExcelProperty(value &qu…...
深入了解Vue Router:基本用法、重定向、动态路由与路由守卫的性能优化
文章目录 1. 引言2. Vue Router的基本用法2.1 基本配置 3. 重定向和命名路由的使用3.1 重定向3.2 命名路由 4. 在Vue Router中如何处理动态路由4.1 动态路由的概念4.2 如何处理动态路由4.3 动态路由的懒加载 5. 路由守卫的实现与性能影响5.1 什么是路由守卫?5.2 路由…...
深入理解InnoDB底层原理:从数据结构到逻辑架构
💡 无论你是刚刚踏入编程世界的新人,还是希望进一步提升自己的资深开发者,在这里都能找到适合你的内容。我们共同探讨技术难题,一起进步,携手度过互联网行业的每一个挑战。 📣 如果你觉得我的文章对你有帮助,请不要吝啬你的点赞👍分享💕和评论哦! 让我们一起打造…...
Linux介绍及操作命令
Linux 是一种开源的操作系统,具有以下特点和优势: 一、稳定性和可靠性 内核稳定 Linux 内核经过多年的发展和优化,具有高度的稳定性。它能够长时间运行而不出现崩溃或故障,适用于服务器和关键任务应用。内核的稳定性得益于其严格的开发流程和质量控制,以及全球开发者社区…...
JS | 详解图片懒加载的6种实现方案
一、什么是懒加载? 懒加载是一种对网页性能优化的方式,比如,当访问一个网页的时候,优先显示可视区域的图片而不是一次加载全部的图片,当需要显示时,再发送请求加载图片。 懒加载 :延迟加载&…...
Java | Leetcode Java题解之第502题IPO
题目: 题解: class Solution {public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {int n profits.length;int curr 0;int[][] arr new int[n][2];for (int i 0; i < n; i) {arr[i][0] capital[i];arr[i][1] profi…...
JavaWeb学习(3)
目录 一、9大内置对象 二、JavaBean 三、MVC三层架构 Model View Controller(Servlet) 四、Filter(过滤器) 应用一:处理中文乱码 应用二:登录验证 五、监听器 六、JDBC 一、9大内置对象 PageCont…...
【含开题报告+文档+PPT+源码】基于SpringBoot的百货商城管理系统的设计与实现
开题报告 随着互联网技术的快速发展和电子商务的兴起,网上购物已成为人们日常生活中不可或缺的一部分。传统的实体店面由于时间和空间的限制,无法满足消费者对于便捷、快速、个性化购物体验的需求。在此背景下,基于 Java 的网上商城系统应运…...
Elasticsearch 实战应用与优化策略研究
一、引言 1.1 研究背景 在当今大数据时代,数据量呈爆炸式增长,对数据的存储、检索和分析提出了更高的要求。Elasticsearch 作为一款强大的分布式搜索和分析引擎,在这个时代背景下显得尤为重要。 随着数据密集型应用场景的不断增加…...
植物大战僵尸杂交版游戏分享
植物大战僵尸杂交版游戏下载:夸克网盘分享 无捆绑之类的隐形消费,下载即玩...
ProteinMPNN中DecLayer类介绍
PositionWiseFeedForward 类的代码 class PositionWiseFeedForward(nn.Module):def __init__(self, num_hidden, num_ff):super(PositionWiseFeedForward, self).__init__()self.W_in = nn.Linear(num_hidden, num_ff, bias=True)self.W_out = nn.Linear(num_ff, num_hidden, …...
Flux.all 使用说明书
all public final Mono<Boolean> all(Predicate<? super T> predicate)Emit a single boolean true if all values of this sequence match the Predicate. 如果该序列中的所有值都匹配给定的谓词(Predicate),则发出一个布尔值…...
DORA 机器人中间件学习教程(6)——激光点云预处理
文章目录 1 移植思路2 代码输入输出说明3 编写CmakeList.txt文件4 编写yml文件5 编译并启动节点参考资料 在DORA中通过驱动获取激光雷达数据后,激光点云预处理部分代码是参考了autoware官方代码并对其进行裁剪得到的,点云预处理主要包含三个节点…...
搜维尔科技:TechViz将您的协同项目评审提升到一个全新的高度
TechViz将您的协同项目评审提升到一个全新的高度 搜维尔科技: TechViz将您的协同项目评审提升到一个全新的高度...
Dinky 字段模式演变 PIPELINE 同步MySQL到Doris
背景 用Dinky数据平台 FlinkCDC收集Mysql BinLog 至 Doris 搭建实时数仓 问题 用Dinky CDCSOURCE 字段模式演变 整库同步Mysql到Doris 字段新增删除不生效 组件信息 Flink 1.17 FlinkCDC 3.1 dinky 1.1 Doris 2.1.6 Mysql 8.0Dinky MySQLCDC 整库到 Doris需要的依赖 Flink/…...
【Docker】Harbor 私有仓库和管理
目录 一、搭建本地私有仓库 二、harbor简介(特性、构成、架构的数据流向) 2.1 什么是Harbor 2.2 Harbor的特性 2.3 Harbor的构成 2.4 Harbor的工作原理(运行流程) 三、harbor部署以及配置文件 1. 部署 Docker-Compose 服…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
