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

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里会受到广播

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python实现回归分析
  • QT事件过滤器(1)
  • <刷题笔记> 二叉搜索树与双向链表注意事项
  • 【AI写作】解释区块链技术的应用场景和优势
  • 【Git入门】使用 Git 进行项目管理:Word Count 程序开发与托管
  • 408算法题leetcode--第14天
  • 【CSS】变量的声明与使用
  • 【Linux基础IO】深入解析Linux基础IO缓冲区机制:提升文件操作效率的关键
  • Android数据序列化总结
  • Redis Bigkey
  • 从零到爆款:利用自养号测评打造Temu、亚马逊热销产品
  • 蠕虫病毒(网络安全小知识)
  • 【权限控制】一个通用的用户权限控制架构设计方案,可以适用于大多数应用场景
  • [数组计数法]#116. 开会时间
  • 戏曲多多 1.0.6.0 专为电视端设计的戏曲与生活内容APP,同样适用于安卓手机,方便老年人使用
  • Angular数据绑定机制
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • JS数组方法汇总
  • Redux 中间件分析
  • Selenium实战教程系列(二)---元素定位
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • Vue 重置组件到初始状态
  • Vultr 教程目录
  • Zsh 开发指南(第十四篇 文件读写)
  • 二维平面内的碰撞检测【一】
  • 分类模型——Logistics Regression
  • 技术:超级实用的电脑小技巧
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 我从编程教室毕业
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • Hibernate主键生成策略及选择
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • 关于Android全面屏虚拟导航栏的适配总结
  • 容器镜像
  • # 数论-逆元
  • #Ubuntu(修改root信息)
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • (02)vite环境变量配置
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (利用IDEA+Maven)定制属于自己的jar包
  • (十三)Maven插件解析运行机制
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • **python多态
  • ./configure、make、make install 命令
  • .NET Core中Emit的使用
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • @AliasFor注解
  • [2021 蓝帽杯] One Pointer PHP