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

이 페이지에서는 SMS 사용자 동의 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 확인 흐름을 시작하기 전에 전화번호를 요청하세요.

앱에 적합한 방식으로 사용자의 전화번호를 가져올 수 있습니다. 사용자의 계정을 만드는 데 이 정보가 필요하지 않은 경우 비밀번호용 스마트 잠금 힌트 선택기를 사용하여 사용자가 전화번호를 입력하도록 지원하는 것이 좋습니다. 힌트 선택기를 사용하려면 다음 단계를 따르세요.

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 사용자 동의 API의 startSmsUserConsent() 메서드를 호출하여 수신 메시지 수신을 시작합니다. SMS 메시지가 시작될 전화번호를 알고 있는 경우 이를 지정합니다 (그렇지 않으면 null 전달). 이렇게 하면 SMS 사용자 동의 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 */)

자바

// 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 인텐트에 응답하는 브로드캐스트 리시버로 이러한 브로드캐스트를 처리합니다. 브로드캐스트 리시버를 만들고 등록하려면 다음을 실행하세요.

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

자바

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

자바

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

메시지 텍스트가 있으면 인증 코드를 파싱하고 양식을 자동 완성하거나 다른 방법으로 인증 흐름을 완료할 수 있습니다.