IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android使用Google SMSRetrieverAPI监听短信 -> 正文阅读

[移动开发]Android使用Google SMSRetrieverAPI监听短信

写在开头

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

    @Override
    public 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>() {
                @Override
                public void onSuccess(Void aVoid) {
                	//代表监听成功开始了
                }
            });

            task.addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                	//代表监听失败了,后续也不会收到系统推送的SMS通知
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

	@Override
    public void onSMSReceived(String otp) {
    	//成功接收到结果
    }

    @Override
    public void onSMSTimeOut() {
        //接收结果超时
    }

    @Override
    public 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 的手机是不能使用的,不过作为辅助功能,也可以了。。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-20 18:30:36  更:2021-11-20 18:32:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:00:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码