如何在 React Native Android APP中实现短信验证码自动填充


本机用户短信验证

问题概述

在我的一个项目中,我的任务是运行包含自动填充功能的双因素身份验证流程,我遇到了 React Native 不支持 Android 开箱即用功能的问题。所以我搜索了 第三方解决方案,但只找到一个解决方法,但有时会不稳定并导致多个APP崩溃。此外,我还在其中看到一些架构上的问题。考虑到这一点,我的团队决定用自己的解决方案,而不是浪费大量时间调试它。我将解决方案做成一个开源库,如果再遇到相同问题大家都可以使用它。

本文探讨了我开发解决方案的经验,以及分享我为 React Native 创建开源 NPM 包的经验。

解决方案

如果你只是单纯地想解决问题,你可以跳转到GitHub 上的库寻找解决方案。如果你对更多信息和技术细节感兴趣,可以继续阅读。

第 1 部分 - 我们的方法

如何开始

为了实现 React Native Android 模块,开发人员必须具有原生 AndroidJava/Kotlin 经验。此外,对于 SMS 用户同意模块,开发人员需要学习其工作原理和使用方法 的官方教程概述实施)。

为了方便稍后进行阅读, 可以将其保存在日志中。

此外,要想将解决方案上传到 NPM,我们需使用 NPM CLI 包创建器 。这会在本教程的第 2 部分中会进行描述。

在这里,我们将了解该模块的运行原理。大多数人认为它是在APP中运行的,而不是作为外部包运行的。

步骤 1 — 设置模块

我按照 React Native 的官方教程添加了主要文件( ReactNativeSmsUserConsentModule.javaReactNativeSmsUserConsentPackage.java )。在本示例中,这些文件以及其他实现文件都位于 android/src/main/java/com/akvelon/reactnativesmsuserconsent 文件夹中。 ReactNativeSmsUserConsentModule.java 是具有聚合功能的主要文件,我们稍后会介绍一些有关它的方法。

第 2 步 - 实现原生 Android 部分

接下来,我按照官方 Android 教程运行了核心 SMS 用户同意功能,此过程不包括第 1 步,因为我们不需要用户的电话号码。在遵循本教程后,我们有了显示 SMS 用户同意模式并接收 SMS 文本的解决方案。

要查看实际完成的代码,具体参阅 ReactNativeSmsUserConsentModule.javasubscribe 法,其中也涉及 SmsBroadcastReceiver.javaSmsListener.java 文件。

现在我们有了解决方案的核心,但为了更好服务于现实生活,我们需要获得更多的控制和便利。因此,我们还有几个方法可以解决这个问题:

  • unsubscribe . 移除侦听器并在收到短信时停止显示短信用户同意模式。这个方法很重要,它适用于用户在收到短信之前离开代码输入屏幕等情况。

  • resubscribe . 由于 subscribe 方法一般只处理一条短信,因此我们每次都需要退订和重新订阅才能收到另一条短信。这个方法更容易和更安全,因为没有多余的空间容纳不调用 unsubscribe 和只调用 subscribe 等所出现的错误,它还会在这两种方法中捕获异常,更加安全。此外,在处理短信时会自动调用 resubscribe ,我们将在下一步中进行检查,因此包的用户不需要在每条短信后重新订阅。这太方便了,因为能简化在生活中 React 方面的问题,特别是它还能使最终的 API 变得更加简单。

第 3 步 - 将 Native 与 React 连接并创建包装器方法

为了将我们的方法公开给 React 端,我们将创建按照官方 React Native指南@ReactMethod 注释的方法,即 startNativeSmsListenerstopNativeSmsListener 。它们只不过是包装 subscribeunsubscribe 方法,它们使用 promise 作为将数据传递给 React 端的一种方式。

现在我们有一种方法可以从 React 端开始并停止侦听短信,但是我们没有办法在收到短信时获取短信内容。我们可以在 SmsListener.java接收短信文本。所以我们在 ReactNativeSmsUserConsentModule.java 中创建 handleSms 方法,并从 SmsListener.java 中调用它,以短信文本为参数。这就是我们的主类接收短信文本的方式。之后,我们从 sendSmsEventToJs 方法中使用 React Native 的标准原生事件发射器发出事件, sendSmsEventToJs 是专门为此目的创建的方法。这就是 React 端获取短信文本的方式。同样在 handleSms 方法中,我们调用 resubscribe ,我们的代码已准备好接收另一个 带有验证码的短信。

这是本部分的外观:


React Native 短信用户验证— 原生流程图

现在,在 JS 端,我们使用这些方法形成实际的 API,通常情况下,它可以是任何文件。在我们的包中,API 位于 src/ 文件夹中。对其中的重要文件的讲解具体如下:

  • index.android.js . 是聚合所有 API 方法并导出它们,但仅限Android 的入口点。

  • index.ios.js . 仅限 iOS 的入口点。由于该包仅适用于 Android,我们从这里导出无操作法为用户处理 iOS,这样他们就不必编写额外的代码来处理 iOS。

  • nativeApi.js . 核心文件,基本上是连接Native 和JS 的桥梁。它导入 NativeEventEmitterNativeModules 对象并对其进行处理,然后导出 ReactNativeSmsUserConsent (是包含我们使用 @ReactMethod 的文件)和被其他文件所使用的对象 eventEmitter

  • startSmsHandling.js . 另一个核心文件,它从 nativeApi.js 导入 ReactNativeSmsUserConsent 并包装其 startNativeSmsListenerstopNativeSmsListener 方法以在 JavaScript 中使用。

现在,通过我们创建的 startSmsHandling API 方法,用户可以向他们的APP添加自动填充功能:

import React, { useEffect, useState } from 'react';
import { TextInput } from 'react-native';

import { startSmsHandling } from '@eabdullazyanov/react-native-sms-user-consent';

function retrieveVerificationCode(sms) {
  const codeRegExp = /\d{6}/m;
  const code = sms?.match(codeRegExp)?.[0];
  return code ?? null;
}
  
const Example = () => {
  const [code, setCode] = useState();
  
  useEffect(() => {
    const stopSmsHandling = startSmsHandling((event) => {
      const retrievedCode = retrieveVerificationCode(event?.sms);
      setCode(retrievedCode);
    });
    return stopSmsHandling;
  }, []);
  
  return <TextInput value={code} onChangeText={setCode} />;
};

尽管这仍然不是最佳选择,但我们将在下一步(也就是最后一步)对此进行检查。

第 4 步 - 实施便捷方法

我们为用户提提供充分的 startSmsHandling 方法,可以将自动填充功能添加到他们的 2FA 屏幕上,但我们还能搞得更容易。

两个方面:

  1. 由于短信用户验证API 提供了整个短信文本,我们只需要从中获取代码,因此解析短信(在示例中的 retrieveVerificationCode ) 中的代码是必备功能,我们要代替用户实现它并将其作为util 方法提供,这样他们就避免很多麻烦,用户可以传递第二个参数来指定代码长度,默认为 6。

  2. 最后,有了我们对本机和 JS 部分所做的所有加强,我们可以利用用户必须编写到一行的代码。由于这是可预测的,并且没有太多的可变空间,我们可以通过实现能控制一切的 React 钩子来提取整个样板,并在收到验证码后只提供验证码。实际上,这正是我在寻找解决方案时所寻找的,因为 useSmsUserConsent 钩子是对用户来说是最方便、最简单的方法。它提供了我们在之前步骤中实现的所有强大的功能,并将所有复杂性压缩到一个简单的 React 钩子调用中:
    const code = useSmsUserConsent();

现在,我们可以通过以下方式使用该包:

import React, { useEffect, useState } from 'react';
import { TextInput } from 'react-native';

import { useSmsUserConsent } from '@eabdullazyanov/react-native-sms-user-consent';

const Example = () => {
  const [code, setCode] = useState();
  const retrievedCode = useSmsUserConsent();

  useEffect(() => {
    if (retrievedCode) setCode(retrievedCode);
  }, [retrievedCode]);
  
  return <TextInput value={code} onChangeText={setCode} />;
};

这是一个简单的显示流程的图表:


React Native短信用户同意流程图

第 2 部分 - 如何营销

在这一部分中,我们将研究如何准备解决方案并将其发布为NPM包。这也可以被视为如何创建 React Native NPM 包的一般指南。

第 1 步 - 创建一个虚拟的 React Native 包

为此,我们可以使用React Native docs 中所述的react-native-builder-bobcreate-react-native-module。对于这个项目,我使用了“create-react-native-module”并遵循了它的“没有视图的示例模块”指南。一切都进展很顺利除了一件事。生成包并将其安装到检测APP后,我遇到了APP崩溃的问题。我在生成包时使用 --example-file-linkage 参数解决了这个问题。

因此,“create-react-native-module”生成了一个最小的包,该包已经可以上传到 NPM 并开始使用。它添加了所有必要的文件,包括 package.json 、Android 创建配置和原生以及JS 端的虚拟实现文件。

第 2 步 - 添加实现

“create-react-native-module”创建器为我们在 ndroid/src/main/java/com/akvelon/reactnativesmsuserconsent 目录中创建了基础的本地文件,这是我们放置本文第 1 部分中介绍的 Android 端实现的地方。确保目录中的每个文件都有与文件夹结构匹配的正确包名称,例如:
package com.akvelon.reactnativesmsuserconsent;

我建议在 Android Studio 中编辑文件,以便你可以看到它出现的所有警告并进行修复。

一旦我们添加了原生文件,我们就应该添加 React 侧文件。 index.js 是入口点,所以我们基于它添加js文件。还有一件事是确保移除在 package.json 中的所有必要文件,具体请参阅package.json 文档

添加完所有实现文件并填充元信息后,我们可以通过将其安装到示例APP来测试该包。考虑到示例APP位于我们包内的文件夹中,安装命令为:

yarn install file:../

这是提供 QA 并确保在你使用已安装的软件包时一切正常的好时机。此外,最好编写一个信息丰富的 README 文件,描述如何使用你的包、它的 API 等。

之后,就可以发布包了。

第 3 步——出版

发布是本教程中最简单的事情,它包括三个简单的步骤:

  1. 如果你尚未注册,请在NPM 上注册;
  2. 从终端运行 npm login 并输入你的 NPM 凭据;
  3. 从包的根目录运行命令 npm publish —-access public

要发布更多版本,要使用该 npm version 命令,然后运行 npm publish .

发布包后,你可以通过从 NPM 安装上传的包来测试它。此外,将其源代码放在 GitHub 上也是一个好主意,这样用户就可以学习它、提出问题、打开问题、做出贡献等。

下一步

在本文中,我尝试分享我创建 React Native SMS User Consent NPM 包的经验。我希望它能帮助有兴趣了解有关 SMS 代码自动填充并发布到 NPM 的更多详细信息的人。当然,我希望软件包本身能够帮助许多正在寻找 SMS 代码自动填充问题的解决方案的开发人员。

现在正处于维护模式,期待你的反馈,欢迎评论。

原文作者 Eldar Abdullazyanov

原文链接 https://e-abdullazyanov.medium.com/how-to-implement-sms-verification-codes-auto-fill-in-react-native-android-apps-c082be1de01d