返回

Flutter短信自动填充失效?问题排查与解决方案

Android

Flutter 应用中短信自动填充功能失效的问题排查

在 Flutter 应用中集成短信自动填充功能,能大幅提升用户体验。然而,即使应用拥有读取短信的必要权限,有时自动填充功能也会失效,让人感到困扰。以下将探讨此问题的常见原因,并提供相应的解决方案。

codeUpdated 方法未被调用

首先,当codeUpdated回调没有被触发时,通常的问题出在监听器设置或短信格式上。sms_autofill 库通过监听特定的短信模式来工作,并从短信中提取验证码。

  1. 确认监听器是否正确启动: 确保SmsAutoFill().listenForCode();在合适的时机调用,并且只调用一次。多次调用可能会导致不可预测的行为。通常应该在 initState 方法内进行监听。
  2. 检查 signature: 某些情况下,你可能需要应用的应用签名以使 sms_autofill 在 Android 设备上正常工作。 使用下面的指令获取您的应用签名:
    keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
    
    注意 :根据您使用的密钥类型, 您可能需要更改alias,或者更改~/.android/debug.keystore为实际路径。复制输出中 “SHA1” 指纹对应的字符串。 接着,调用 SmsAutoFill().getAppSignature 获取应用的签名。将 appSignature打印出来并和前面获取的值进行比对,若不一致请设置正确的appSignature
       appSignature = await SmsAutoFill().getAppSignature;
        print("App signature is $appSignature");
       SmsAutoFill().listenForCode(signature:appSignature);
    
  3. 检查短信格式: 验证短信验证码的格式是否与sms_autofill库的默认预期相符。标准短信格式需要类似 xxxxxx 的验证码,或者带有Your OTP code is xxxxxx.Your verification code is xxxxxx. 的语句。检查您的服务器是否发送这种标准格式的短信。你可能需要配置短信模板,使其能被自动填充识别。库可能会尝试匹配短信中数字模式,如果匹配不上,那么则不会回调codeUpdated方法。 你可以查看一下这个包的github的文档, 关于它的匹配算法逻辑的详细。

"Reading a NULL string not supported here" 错误

该错误消息通常与 Android 系统本身有关,表示尝试读取的短信内容为空,而不是应用或sms_autofill库的问题。以下是一些常见的原因和解决方法:

  1. 后台进程干扰: 某些后台进程或应用可能会在 SMS 内容处理过程中,与应用进程冲突。 可以通过尝试停止不必要的后台服务来进行测试,看看是否能够解决这个问题。
  2. Android版本和API: 不同版本的Android在读取短信的处理机制上会有不同,这个错误或许是和具体设备或 Android 系统版本相关联。确保在兼容的不同版本上进行充分的测试,例如可以在多台不同的安卓设备上尝试你的应用,以此排查问题根因。
  3. 短信拦截: 某些安全或清理类应用会干扰正常的短信读取流程。 暂时禁用此类应用,确认问题是否由此产生。检查是否启用了手机的安全设置拦截或限制了应用的读取权限,如果有的话将其暂时禁用看看。
  4. 应用权限和签名 : 部分第三方安卓rom对于权限的管理可能更加严格,特别是自启动,后台服务,通知,和访问特定API方面的管理,如果签名有问题也会有问题,可以通过adb 查看是否报出signature error 类型的log,来定位是不是这方面的问题。
  5. 应用权限 :尽管已经请求了 SMS 读取权限,也要检查在应用设置中,对应的权限是否开启,有些rom可能会要求您手动进行打开。您也可以先尝试把权限卸载再重装APP试试看。

正确实现短信自动填充的步骤

遵循以下步骤能确保在Flutter应用中正确实现短信自动填充:

  1. 权限请求: 启动时请求 sms 权限,但如果已有权限无需再次请求。使用 permission_handler 库方便地请求运行时权限:
import 'package:permission_handler/permission_handler.dart';
...
  Future<void> requestSMSPermissions() async {
    if (await Permission.sms.request().isGranted) {
      print("SMS permissions are granted.");
    }
     else{
       print("SMS permissions are not granted.");
    }

  }
  1. 启动监听器: 在合适的生命周期启动sms_autofill监听,并添加应用签名(如有必要):

    @override
    

void initState() {
super.initState();
requestSMSPermissions();
_listenForSms();

}

void _listenForSms() async {
appSignature = await SmsAutoFill().getAppSignature;
print("App signature is $appSignature");
SmsAutoFill().listenForCode(signature:appSignature);
}

@override
void dispose() {
SmsAutoFill().unregisterListener();
super.dispose();
}

@override

void codeUpdated() {
if (code != null && code!.isNotEmpty) {
print("Received OTP Code: $code");
setState(() {
ctrlNumber.text = code!;
widget.valueChange(code!);
});
} else {
print("No code received or code is empty");
}

}

3. **处理自动填充:**  实现 `codeUpdated` 方法,当收到验证码时自动填充到相应的输入框。
4.  **短信格式标准化:**   如上所述,请尽可能使短信的验证码符合标准的格式,并且可以进行灵活的正则表达式匹配。

## 安全建议

自动填充功能虽然提升用户体验,但也需要注意一些安全事项:

* **防止滥用:**  使用验证码进行二次验证等方式确保只有授权的用户可以操作敏感行为。
*  **处理过期验证码:**  在处理短信验证码时添加验证机制, 以防止使用已过期的验证码进行操作。
*  **加密通信:**   应用应使用HTTPS传输短信验证码等敏感信息,保障用户隐私。

解决 SMS 自动填充问题往往需要结合系统、设备、和应用本身来共同分析。请务必检查所有的可能性,找到导致问题的根源。希望以上内容对您有所帮助!