SMS 인증 코드를 읽으려면 일회성 동의를 요청하세요.

이 페이지에서는 SMS User Consent API를 사용하여 단일 SMS 인증 메시지를 읽을 수 있도록 사용자 동의를 요청하는 방법을 설명합니다. 사용자가 동의하면 API가 메시지 텍스트를 반환하며, 이 텍스트로부터 인증 코드를 가져와서 인증 프로세스를 완료할 수 있습니다.

종속 항목 설치

앱의 build.gradle 파일에 Play 서비스 인증 구성요소를 포함합니다.

implementation 'com.google.android.gms:play-services-auth:17.0.0'
implementation 'com.google.android.gms:play-services-auth-api-phone:17.4.0'

1. 사용자의 전화번호 가져오기

사용자의 전화번호가 없으면 SMS 확인 흐름을 시작하기 전에 전화번호를 요청합니다.

앱에 적합한 방식으로 사용자의 전화번호를 가져올 수 있습니다. 사용자 계정을 만드는 데 정보가 필요하지 않은 경우 비밀번호 대용 Smart Lock 힌트 선택기를 사용하여 사용자가 전화번호를 입력할 수 있도록 하는 것이 좋습니다. 힌트 선택기를 사용하는 방법은 다음과 같습니다.

Kotlin

private val CREDENTIAL_PICKER_REQUEST = 1  // Set to an unused request code

// Construct a request for phone numbers and show the picker
private fun requestHint() {
    val hintRequest = HintRequest.Builder()
        .setPhoneNumberIdentifierSupported(true)
        .build()
    val credentialsClient = Credentials.getClient(this)
    val intent = credentialsClient.getHintPickerIntent(hintRequest)
    startIntentSenderForResult(
        intent.intentSender,
        CREDENTIAL_PICKER_REQUEST,
        null, 0, 0, 0
    )
}

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        CREDENTIAL_PICKER_REQUEST ->
            // Obtain the phone number from the result
            if (resultCode == Activity.RESULT_OK && data != null) {
                val credential = data.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
                // credential.getId();  <-- will need to process phone number string
            }
        // ...
    }
}

Java

private static final int CREDENTIAL_PICKER_REQUEST = 1;  // Set to an unused request code

// Construct a request for phone numbers and show the picker
private void requestHint() throws IntentSender.SendIntentException {
    HintRequest hintRequest = new HintRequest.Builder()
            .setPhoneNumberIdentifierSupported(true)
            .build();
    PendingIntent intent = Credentials.getClient(this).getHintPickerIntent(hintRequest);
    startIntentSenderForResult(intent.getIntentSender(),
            RESOLVE_HINT, null, 0, 0, 0);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case CREDENTIAL_PICKER_REQUEST:
            // Obtain the phone number from the result
            if (resultCode == RESULT_OK) {
                Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
                // credential.getId();  <-- will need to process phone number string
            }
            break;
        // ...
    }
}

2. 수신 메시지 리슨 시작

그런 다음 SMS User Consent API의 startSmsUserConsent() 메서드를 호출하여 수신 메시지 리슨을 시작합니다. SMS 메시지가 시작될 전화번호를 알고 있다면 전화번호를 지정합니다 (그렇지 않으면 null 전달). 이렇게 하면 SMS User Consent API가 이 번호에서 보낸 메시지에만 트리거됩니다.

듣기를 시작하려면 다음 단계를 따르세요.

Kotlin

// Start listening for SMS User Consent broadcasts from senderPhoneNumber
// The Task<Void> will be successful if SmsRetriever was able to start
// SMS User Consent, and will error if there was an error starting.
val task = SmsRetriever.getClient(context).startSmsUserConsent(senderPhoneNumber /* or null */)

Java

// Start listening for SMS User Consent broadcasts from senderPhoneNumber
// The Task<Void> will be successful if SmsRetriever was able to start
// SMS User Consent, and will error if there was an error starting.
Task<Void> task = SmsRetriever.getClient(context).startSmsUserConsent(senderPhoneNumber /* or null */);

수신된 SMS 메시지를 수신 대기하면 인증 시스템이 첫 번째 단계에서 받은 사용자의 전화번호로 인증 코드를 전송하도록 할 수 있습니다.

앞으로 5분 동안 기기에서 일회성 코드가 포함된 SMS 메시지를 수신하면 Play 서비스는 사용자에게 메시지를 읽을 수 있는 권한을 요청하는 인텐트를 앱에 브로드캐스트합니다. 메시지는 다음 기준을 충족하는 경우에만 브로드캐스트를 트리거합니다.

  • 메시지에는 하나 이상의 숫자가 포함된 4~10자리 영숫자 문자열이 포함됩니다.
  • 발신자의 전화번호를 지정하면 해당 번호로 메시지가 전송됩니다.

SEND_PERMISSION 권한이 있고 SMS_RETRIEVED_ACTION 인텐트에 응답하는 broadcast receiver를 사용하여 이러한 브로드캐스트를 처리합니다. broadcast receiver를 만들고 등록하려면 다음 단계를 따르세요.

Kotlin

private val SMS_CONSENT_REQUEST = 2  // Set to an unused request code
private val smsVerificationReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
            val extras = intent.extras
            val smsRetrieverStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as Status

            when (smsRetrieverStatus.statusCode) {
                CommonStatusCodes.SUCCESS -> {
                    // Get consent intent
                    val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
                    try {
                        // Start activity to show consent dialog to user, activity must be started in
                        // 5 minutes, otherwise you'll receive another TIMEOUT intent
                        startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
                    } catch (e: ActivityNotFoundException) {
                        // Handle the exception ...
                    }
                }
                CommonStatusCodes.TIMEOUT -> {
                    // Time out occurred, handle the error.
                }
            }
        }
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    // ...

    val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
    registerReceiver(smsVerificationReceiver, SmsRetriever.SEND_PERMISSION, intentFilter)
}

Java

private static final int SMS_CONSENT_REQUEST = 2;  // Set to an unused request code
private final BroadcastReceiver smsVerificationReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
            Bundle extras = intent.getExtras();
            Status smsRetrieverStatus = (Status) extras.get(SmsRetriever.EXTRA_STATUS);

            switch (smsRetrieverStatus.getStatusCode()) {
                case CommonStatusCodes.SUCCESS:
                    // Get consent intent
                    Intent consentIntent = extras.getParcelable(SmsRetriever.EXTRA_CONSENT_INTENT);
                    try {
                        // Start activity to show consent dialog to user, activity must be started in
                        // 5 minutes, otherwise you'll receive another TIMEOUT intent
                        startActivityForResult(consentIntent, SMS_CONSENT_REQUEST);
                    } catch (ActivityNotFoundException e) {
                        // Handle the exception ...
                    }
                    break;
                case CommonStatusCodes.TIMEOUT:
                    // Time out occurred, handle the error.
                    break;
            }
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // ...

    IntentFilter intentFilter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION);
    registerReceiver(smsVerificationReceiver, SmsRetriever.SEND_PERMISSION, intentFilter);
}

EXTRA_CONSENT_INTENT 활동을 시작하면 사용자에게 메시지 내용을 읽을 수 있는 일회성 권한을 요청하는 메시지가 표시됩니다.

3. 메시지에서 인증 코드 받기

onActivityResult() 메서드에서 권한 요청에 대한 사용자의 응답을 처리합니다. RESULT_OK의 결과 코드를 가져오면 사용자가 메시지의 콘텐츠를 읽을 수 있는 권한을 부여했으며 개발자는 인텐트에서 메시지 텍스트를 가져올 수 있습니다.

Kotlin

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        // ...
        SMS_CONSENT_REQUEST ->
            // Obtain the phone number from the result
            if (resultCode == Activity.RESULT_OK && data != null) {
                // Get SMS message content
                val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
                // Extract one-time code from the message and complete verification
                // `message` contains the entire text of the SMS message, so you will need
                // to parse the string.
                val oneTimeCode = parseOneTimeCode(message) // define this function

                // send one time code to the server
            } else {
                // Consent denied. User can type OTC manually.
            }
    }
}

Java

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        // ...
        case SMS_CONSENT_REQUEST:
            if (resultCode == RESULT_OK) {
                // Get SMS message content
                String message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE);
                // Extract one-time code from the message and complete verification
                // `sms` contains the entire text of the SMS message, so you will need
                // to parse the string.
                String oneTimeCode = parseOneTimeCode(message); // define this function

                // send one time code to the server
            } else {
                // Consent canceled, handle the error ...
            }
            break;
    }
}

메시지 텍스트가 있으면 인증 코드를 파싱하여 양식을 자동으로 작성하거나 인증 과정을 완료할 수 있습니다.