Android使用Google SMSRetrieverAPI监听短信

news/2024/11/16 21:45:34/

写在开头

google官方介绍
如果在没有读写短信权限的情况下获取用户的短信验证码呢?google为我们提供了SMSRetrieverAPI这个Api。解决了我们在用户收到短信后自动回填界面的需求。但是google为了安全性,短信格式需要时固定的,那么我们先来看下短信的固定格式!

短信格式

短信固定格式(#号可以不要,sha256一定需要)
<#> Your ExampleApp code is: 123ABC78
FA+9qCX9VSu

google要求我们的短信:

  • 不能超过140个字节
  • 包含一个11个字符的哈希字符串来标识您的应用(也就是上文的sha256)

sha256如何生成

网上通用的生成方式,总结了一个工具类AppSignatureHashHelper

	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;}
}

接下来我们要开始集成SMSRetrieverAPI了

首先我们要依赖google的两个库才能使用这个功能

dependencies {implementation 'com.google.android.gms:play-services-auth:19.2.0'implementation 'com.google.android.gms:play-services-auth-api-phone:17.5.1'
}

然后要通过google的系统广播的action–SmsRetriever.SMS_RETRIEVED_ACTION和SmsRetriever实现监听的需求

接下来第一步
先创建SMSReceiver这个BroadcastReceiver接收系统给我推送的SMS广播,并创建OTPReceiveListener接口来实现监听结果的返回,代码如下:

	public class SMSReceiver extends BroadcastReceiver {private OTPReceiveListener otpListener;public void setOTPListener(OTPReceiveListener otpListener) {this.otpListener = otpListener;}@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 (otpListener != null) {otpListener.onOTPReceived(message);}break;case CommonStatusCodes.TIMEOUT:if (otpListener != null) {otpListener.onOTPTimeOut();}break;case CommonStatusCodes.API_NOT_CONNECTED:if (otpListener != null) {otpListener.onOTPReceivedError("API NOT CONNECTED");}break;case CommonStatusCodes.NETWORK_ERROR:if (otpListener != null) {otpListener.onOTPReceivedError("NETWORK ERROR");}break;case CommonStatusCodes.ERROR:if (otpListener != null) {otpListener.onOTPReceivedError("SOME THING WENT WRONG");}break;}}}public interface SMSReceiveListener {void onSMSReceived(String otp);void onSMSTimeOut();void onSMSReceivedError(String error);}
}

第二步的话我们要主动开启这个监听:

private void startSMSListener() {try {smsReceiver = new SMSReceiver();smsReceiver.setOTPListener(this);//this指的是要在这个activity实现这个接口IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);this.registerReceiver(smsReceiver, intentFilter);SmsRetrieverClient client = SmsRetriever.getClient(this);Task<Void> task = client.startSmsRetriever();task.addOnSuccessListener(new OnSuccessListener<Void>() {@Overridepublic void onSuccess(Void aVoid) {//代表监听成功开始了}});task.addOnFailureListener(new OnFailureListener() {@Overridepublic void onFailure(@NonNull Exception e) {//代表监听失败了,后续也不会收到系统推送的SMS通知}});} catch (Exception e) {e.printStackTrace();}}

实现接口的方法获取结果:

	@Overridepublic void onSMSReceived(String otp) {//成功接收到结果}@Overridepublic void onSMSTimeOut() {//接收结果超时}@Overridepublic void onSMSReceivedError(String error) {//接收结果报错}

写在最后

这种方式不是一定会成功的,google告诉我们可以检测广播意图是使用短信API通过添加com.google.android.gms.auth.api.phone.permission.SEND允许你的接收SMS。此权限设置在 Google Play 服务 19.8.31 或更高版本中可用。也就是低于Google Play 服务 19.8.31 的手机是不能使用的,不过作为辅助功能,也可以了。。


http://www.ppmy.cn/news/966699.html

相关文章

短信发送详解

前言&#xff1a;关于短信的发送其实是很简单的&#xff0c;只需要调用一下API即可&#xff0c;本章博客用互亿无线给大家开发这个功能。 第一步&#xff1a;官网打开链接接口地址 网站中有个接口下载&#xff0c;下载后出现下面的文件夹 文件夹介绍&#xff1a;点开文件夹DE…

(转)android如何监听发送短信

转自&#xff1a;http://www.eoeandroid.com/thread-8990-1-1.html 回楼上&#xff1a;先写一个观察者&#xff1a; public class SmsObserver extends ContentObserver { private Context context; private static final String[] SMS_PROJECTION new …

短信接口被恶意调用?企业短信防火墙+【中昱维信】短信验证码【Java】

短信接口被恶意调用&#xff1f;企业短信防火墙【中昱维信】短信验证码【Java】 一、企业短信防火墙的实现1.1 简介1.2 第一步&#xff1a;获取防火墙帐号密钥1.3 第二步&#xff1a;下载防火墙服务器1.4 第三步&#xff1a;业务系统前后端接入1.5丰富可视化实时风险大盘&#…

android短信和彩信探秘threads

android源代码在 彩信sms 表和彩信 pdu表&#xff0c;增加了一个触发器 CREATE TRIGGER delete_obsolete_threads_pdu AFTER DELETE ON pdu BEGIN DELETE FROM threads WHERE _id old.thread_id AND _id NOT IN (SELECT thread_id FROM sms UNION SEL…

论文投稿指南——中国(中文EI)期刊推荐(第6期)

&#x1f680; EI是国际知名三大检索系统之一&#xff0c;在学术界的知名度和认可度仅次于SCI&#xff01;&#x1f384;&#x1f388; 【前言】 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊。其中&#xf…

关于网页版chatgpt喂投的一些讲解

ChatGPT云炬学长 喂投的定义及使用场景&#xff1a; 这一部分主要是解决这三个问题&#xff1a;啥是喂投。我们为什么要喂投。以及什么场景下面会用到喂投。 从AI专业名词的角度来说&#xff0c;并不存在“喂投”这么一个行为&#xff0c;这是一个不太专业化的俗称&#xff…

上海场:聚焦HR的未来发展,一起探索ChatGPT的“能”与“不能”

在4月20日的北京场“高管闭门会”圆满结束之后&#xff0c;我们于4月23日迎来了上海场的精彩讨论。 2023年4月23日&#xff0c;AI得贤招聘官与泛招聘求职领域内容人欧阳泽林联合举办的“HR高管闭门会”在上海圆满结束。本次座谈会关注HR的未来进展&#xff0c;重点研究ChatGPT在…

用ChatGPT4探索李清照的千古谜题寂寞寒窗空守寡的下联

试了试用大语言模型对千古才女易安居士李清照的绝联&#xff0c;看看会有什么惊喜 ^&^ 背景 北宋首都被大金攻占&#xff0c;李清照和丈夫也向南逃去。逃难的生活总归是苦的&#xff0c;他的丈夫赵明诚身子不好&#xff0c;不久在路上病逝了。 难得一遇的才女碰上如此称意…