티스토리 뷰
앱 서비스 이용하다 보면 인증번호 입력하는 부분이 자동으로 입력 처리되는 서비스들을 많이 경험해보셨을겁니다.
그 기능은 sms autofill 이라고 많이 불립니다.
sms autofill 구현 과정을 자세히 적어보았습니다.
먼저, 관련한 키워드 들을 먼저 살펴볼게요!
- Apple Keyboard QuickType
: apple 소프트웨어 키보드로, SMS로 전달받은 인증번호를 자동으로 캐치해주고 상단에 붙여넣기를 할 수 있도록 OS 단에서 자동으로 기능을 제공해준다.
- AppSignature
: Android 앱 서명값으로 Android 에서 특정 앱을 위한 문자인지 확인하기 위한 수단으로 활용된다.
iOS Solution
일단, ios 에서는 문자의 내용을 읽어올 수 있는 기능을 구현할 수 없습니다.
다만 QuickType 이라는 기능을 이용해서 자체적으로 인증번호를 붙여넣기를 할 수 있도록 시스템을 활용할 수 있습니다.
apple developer 사이트에는 권장하는 가이드라인이 존재하니 참고해도 됩니다.
권장하는 가이드라인
- iOS 12 이상부터 지원
- 메시지 형식은 단순해야하며, 코드가 메시지의 마지막 부분에 있어야 함
Your Example code is 123456.
하지만, 저는 아래처럼 작업을 해보았습니다. 다행히 잘 인식합니다.
[내 서비스 인증번호 발급]
내 서비스에 가입해 주셔서 감사합니다.
회원님의 고유 인증번호가 발급되었습니다.
> 인증번호 : 12345678
Android Solution
Android는 문자 메시지의 내용을 읽어올 수 있습니다.
단, 모든 앱에서 문자 메시지 정보를 읽어오면 보안에 문제가 생기니, AppSignature 값이 매칭된 메시지만 읽어올 수 있습니다.
사용한 flutter 라이브러리는 sms_autofill 입니다.
https://pub.dev/packages/sms_autofill
문자메시지 가이드라인은 다음과 같습니다.
1. 시작에는 # 문자가 있어야 한다.
2. 마지막 문자엔 AppSignature 값을 넣는다.
<#> [내 서비스 인증번호 발급]
내 서비스에 가입해 주셔서 감사합니다.
회원님의 고유 인증번호가 발급되었습니다.
> 인증번호 : 12345678
KdQ911xYz
위에 문자의 마지막 텍스트인 KdQ911xYz 가 AppSignature 라고 보면 됩니다. (임의의 숫자를 넣었고 진짜 AppSignature 는 아닙니다😆)
문자 메시지에 시작시 #을 추가하고, 마지막에 AppSignature 값인 KdQ911xYz 를 포함하도록 문자메시지 기능을 구현하는 백엔드 팀에게 공유해줘야겠죠?
Q) AppSignature 값은 어떻게 알아내나요?
A) SmsAutoFill().getAppSignature 함수를 이용하면 됩니다.
() async {
final signature = await SmsAutoFill().getAppSignature;
talker.log("appSignature: $signature");
}();
자, 그럼 이제 인증번호를 읽어내는 로직 작업을 해 봅시다.
언제 인증 문자가 들어올지 모르니 listener 등록을 하고 update 리스너에서 데이터를 읽어와야 합니다.
위의 기능을 담당하는 SmsCodeHandler를 만들어봤습니다.
import 'package:mora_care/utils/extensions/ObjectExtensions.dart';
import 'package:sms_autofill/sms_autofill.dart';
import '../main.dart';
class SmsCodeHandler with CodeAutoFill {
final Function(String) onCodeReceived;
SmsCodeHandler(this.onCodeReceived);
String _getRegex(int codeLength) => '\\b\\d{$codeLength}\\b';
@override
void codeUpdated() {
talker.log("codeUpdated code: $code");
code?.let((_code) => onCodeReceived(_code));
}
void startListening({required int codeLength}) {
listenForCode(smsCodeRegexPattern: _getRegex(codeLength));
}
void stopListening() {
cancel();
}
}
sms_autofill 라이브러리에서 제공해주는 함수인 listenForCode를 이용해서 리스너 등록을 시작하면 됩니다.
파라미터로 smsCodeRegexPattern 이라는 정규식을 넣을 수 있는데, 원하는 정규식을 뽑아올 수 있습니다.
파라미터를 넣지 않으면 기본적으로는 6자리 숫자 를 뽑아옵니다.
예를들어 숫자 10자리 인증번호를 사용하는 서비스라면 정규식으로 10자리 숫자를 받아오도록 정규식을 입력할 수 있도록 Handler를 만들어 놓았습니다.
그리고 codeUpdate 함수를 상속받아서 원하는 조건의 인증번호를 받으면 됩니다!
@RoutePage()
class LoginScreen extends HookConsumerWidget {
LoginScreen({super.key});
final TextEditingController codeController = TextEditingController();
@override
Widget build(BuildContext context, WidgetRef ref) {
() async {
final signature = await SmsAutoFill().getAppSignature;
talker.log("appSignature: $signature");
}();
if (Platform.isAndroid) {
final handler = useMemoized(() => SmsCodeHandler((code) {
codeController.text = code;
}));
useEffect(() {
handler.startListening(codeLength: 10);
return () {
handler.stopListening();
};
}, [handler]);
}
... 생략 ...
EvTextField(
title: '식별코드',
hintText: '식별코드를 입력해 주세요.',
idController: codeController,
enableObscure: true,
limitInputLength: 100,
isDigitsOnly: true,
currentFocusNode: secondFocusNode,
onValueChanged: (text) {
code.value = text;
},
),
... 생략 ...
}
}
위의 코드의 특징을 몇개 짚어보자.
1. CodeHandler는 Widget이 Rebuild 시점마다 계속 생성될 필요가 없습니다.
따라서 Widget 생명주기에서 딱 한번만 CodeHandler를 생성하도록 flutter_hooks의 useMemoized 를 활용했습니다.
2. 플랫폼중 Android 에만 해당하는 기능이기 때문에 Platform.isAndroid 플래그 안에서만 CodeHandler 동작이 진행됩니다.
마무리
Flutter에서 sms autofill 기능은 처음 구현해보았네요!
생각보다 빠르게 문제 해결을 할 수 있었습니다.
처음 구현하시는 분들은 제 글을 보고 우여곡절을 줄였으면 합니다.
그럼 굿럭!
'flutter' 카테고리의 다른 글
Flutter FCM push 적용기 (2) | 2024.12.17 |
---|---|
Flutter Webview 연동하기 (0) | 2024.09.24 |
Flutter Mvvm Clean Architecture Guide (0) | 2024.09.13 |
flutter go_router vs auto_route (0) | 2024.09.11 |
flutter thread 분석 (0) | 2024.06.05 |
- Total
- Today
- Yesterday
- rxjava
- Spinner
- changenotifier
- provider
- MVP
- SpinnerAdapter
- Flutter
- flutter fcm push message background foreground killed
- multi api
- Kotlin
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |