当前位置: 首页 > news >正文

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 代码生成哈希值:可以在应用的 ActivityUtils 类中调用它

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 类似,可以使用正则表达式提取验证码。

总结

  1. SMS Retriever API 是更加推荐的方法,因为它不需要读取短信的权限,更加安全。
  2. 读取短信权限 方法需要申请敏感权限,使用较少。

相关文章:

Android 中获取和读取短信验证码

方法一&#xff1a;通过 SMS Retriever API SMS Retriever API 是 Google 提供的一种安全的方式&#xff0c;可以从系统中获取不需要权限的短信验证码。这种方式不需要请求 READ_SMS 权限&#xff0c;非常适合处理短信验证码的情况。 1. 在 build.gradle 中添加依赖 dependen…...

SQL语句高级查询(适用于新手)

SQL查询语句的下载脚本链接&#xff01;&#xff01;&#xff01; 【免费】SQL练习资源-具体练习操作可以查看我发布的文章资源-CSDN文库https://download.csdn.net/download/Z0412_J0103/89908378 本文旨在为那些编程基础相对薄弱的朋友们提供一份详尽的指南&#xff0c;特别聚…...

main.ts中引入App.vue报错,提示“Cannot find module ‘./App.vue’ or its corresponding type

原因 代码编辑器&#xff1a;vscode &#xff0c;使用vue3&#xff0c;所以安装了 Volar 插件&#xff0c;可以使 vue 代码高亮显示&#xff0c;不同颜色区分代码块&#xff0c;以及语法错误提示等 提示&#xff1a;如果使用的是vue2&#xff0c;则使用 Vetur 插件&#xff1…...

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 什么是路由守卫&#xff1f;5.2 路由…...

深入理解InnoDB底层原理:从数据结构到逻辑架构

💡 无论你是刚刚踏入编程世界的新人,还是希望进一步提升自己的资深开发者,在这里都能找到适合你的内容。我们共同探讨技术难题,一起进步,携手度过互联网行业的每一个挑战。 📣 如果你觉得我的文章对你有帮助,请不要吝啬你的点赞👍分享💕和评论哦! 让我们一起打造…...

Linux介绍及操作命令

Linux 是一种开源的操作系统,具有以下特点和优势: 一、稳定性和可靠性 内核稳定 Linux 内核经过多年的发展和优化,具有高度的稳定性。它能够长时间运行而不出现崩溃或故障,适用于服务器和关键任务应用。内核的稳定性得益于其严格的开发流程和质量控制,以及全球开发者社区…...

JS | 详解图片懒加载的6种实现方案

一、什么是懒加载&#xff1f; 懒加载是一种对网页性能优化的方式&#xff0c;比如&#xff0c;当访问一个网页的时候&#xff0c;优先显示可视区域的图片而不是一次加载全部的图片&#xff0c;当需要显示时&#xff0c;再发送请求加载图片。 懒加载 &#xff1a;延迟加载&…...

Java | Leetcode Java题解之第502题IPO

题目&#xff1a; 题解&#xff1a; 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&#xff08;Servlet&#xff09; 四、Filter&#xff08;过滤器&#xff09; 应用一&#xff1a;处理中文乱码 应用二&#xff1a;登录验证 五、监听器 六、JDBC 一、9大内置对象 PageCont…...

【含开题报告+文档+PPT+源码】基于SpringBoot的百货商城管理系统的设计与实现

开题报告 随着互联网技术的快速发展和电子商务的兴起&#xff0c;网上购物已成为人们日常生活中不可或缺的一部分。传统的实体店面由于时间和空间的限制&#xff0c;无法满足消费者对于便捷、快速、个性化购物体验的需求。在此背景下&#xff0c;基于 Java 的网上商城系统应运…...

Elasticsearch 实战应用与优化策略研究

一、引言 1.1 研究背景 在当今大数据时代&#xff0c;数据量呈爆炸式增长&#xff0c;对数据的存储、检索和分析提出了更高的要求。Elasticsearch 作为一款强大的分布式搜索和分析引擎&#xff0c;在这个时代背景下显得尤为重要。 随着数据密集型应用场景的不断增加&#xf…...

植物大战僵尸杂交版游戏分享

植物大战僵尸杂交版游戏下载&#xff1a;夸克网盘分享 无捆绑之类的隐形消费&#xff0c;下载即玩...

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. 如果该序列中的所有值都匹配给定的谓词&#xff08;Predicate&#xff09;&#xff0c;则发出一个布尔值…...

DORA 机器人中间件学习教程(6)——激光点云预处理

文章目录 1 移植思路2 代码输入输出说明3 编写CmakeList.txt文件4 编写yml文件5 编译并启动节点参考资料 在DORA中通过驱动获取激光雷达数据后&#xff0c;激光点云预处理部分代码是参考了autoware官方代码并对其进行裁剪得到的&#xff0c;点云预处理主要包含三个节点&#xf…...

搜维尔科技:TechViz将您的协同项目评审提升到一个全新的高度

TechViz将您的协同项目评审提升到一个全新的高度 搜维尔科技&#xff1a; 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简介&#xff08;特性、构成、架构的数据流向&#xff09; 2.1 什么是Harbor 2.2 Harbor的特性 2.3 Harbor的构成 2.4 Harbor的工作原理&#xff08;运行流程&#xff09; 三、harbor部署以及配置文件 1. 部署 Docker-Compose 服…...

【具身智能06】具身智能多模态感知与传感器融合:从看见到理解

06_具身智能多模态感知与传感器融合 关键词 多模态感知,传感器融合,触觉传感器,力觉传感器,时空对齐,环境建模,IMU,视觉-触觉融合,深度感知一、引言&#xff1a;从单模态感知到多模态融合的必然之路 具身智能机器人的本质是在物理世界中行动,而行动的前提是感知。传统的工业机器…...

企业级前端基建:如何将离线npm包(tgz)安全迁移到Nexus 3私库?

企业级前端基建&#xff1a;如何将离线npm包&#xff08;tgz&#xff09;安全迁移到Nexus 3私库&#xff1f; 当企业面临安全合规审计或网络隔离需求时&#xff0c;如何将分散在各处的npm离线包&#xff08;tgz格式&#xff09;安全、高效地迁移至Nexus私有仓库&#xff0c;成为…...

SAM 3实操手册:分割掩码生成STL网格用于3D打印前处理

SAM 3实操手册&#xff1a;分割掩码生成STL网格用于3D打印前处理 1. 引言 你是否遇到过这样的问题&#xff1a;想要3D打印一个实物&#xff0c;但手头只有一张照片&#xff1f;或者想要从复杂的背景中提取出特定物体进行三维重建&#xff1f;传统的方法需要手动抠图、建模&am…...

SlopeCraft终极指南:如何轻松将任何图片转换为Minecraft立体地图画

SlopeCraft终极指南&#xff1a;如何轻松将任何图片转换为Minecraft立体地图画 【免费下载链接】SlopeCraft Map Pixel Art Generator for Minecraft 项目地址: https://gitcode.com/gh_mirrors/sl/SlopeCraft 你是否曾梦想将心爱的照片、动漫角色或艺术作品搬进Minecra…...

ncmdumpGUI+解决网易云音乐NCM文件跨设备播放痛点

ncmdumpGUI解决网易云音乐NCM文件跨设备播放痛点 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 问题场景&#xff1a;被加密的音乐自由 想象这样的场景&…...

K8s CronJob配置避坑指南:从并发策略到历史记录,这些细节你注意了吗?

K8s CronJob生产环境实战&#xff1a;避开那些让你夜不能寐的配置陷阱 凌晨三点&#xff0c;告警铃声刺破夜空——你的数据库备份任务已经连续三次未能执行&#xff0c;而监控面板上堆积的Job数量正在以肉眼可见的速度增长。这不是第一次了&#xff0c;每次CronJob出问题都像一…...

C语言字符串操作的高效实现与优化

1. C语言字符串操作的高效实现方法 1.1 标准字符串函数的效率问题 在C语言开发中&#xff0c; <string.h> 头文件提供的字符串处理函数是日常开发的基础工具。其中&#xff0c;字符串复制和连接函数使用最为频繁&#xff0c;但它们的效率问题往往被开发者忽视。 标准…...

解决k8s集群中containerd运行时拉取HTTP私有Harbor镜像的配置难题

1. 为什么需要配置HTTP私有Harbor镜像拉取 最近在帮客户部署Kubernetes集群时&#xff0c;遇到了一个典型问题&#xff1a;使用containerd作为容器运行时&#xff0c;无法从内网HTTP协议的Harbor私有仓库拉取镜像。这个问题其实很常见&#xff0c;特别是很多企业内网环境中&…...

4步精通OpenCore EFI制作:OpCore-Simplify智能配置引擎全解析

4步精通OpenCore EFI制作&#xff1a;OpCore-Simplify智能配置引擎全解析 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在黑苹果技术领域&#xff0…...

从零解析:富斯i6遥控器与STM32的IBUS协议通信实战

1. 为什么选择富斯i6遥控器与STM32通信 对于很多刚接触机器人或者智能小车开发的爱好者来说&#xff0c;无线控制模块的选择往往是个头疼的问题。市面上常见的方案要么价格昂贵&#xff0c;要么配置复杂&#xff0c;而富斯i6遥控器配合iA6B接收机恰好提供了一个低成本、高可靠性…...