یکی از نیاز هایی که امروزه اغلب اپلیکیشن ها با آن رو به رو هستند ، احراز هویت کاربر با استفاده از پیامک است . برای اینکه بتوانیم تجربه کاربری بهتری داشته باشیم یک راه حل این است که فرآیند خواندن کد از داخل پیامک و وارد کردن آن درون اپلیکیشن به صورت خودکار اتفاق بیافتد و کاربر بدون زحمت اضافی و فقط با تایید دسترسی ساده فرآیند احراز هویت رو انجام دهد .
در این مقاله درباره راه حلی که به عنوان یه برنامه نویس اندروید برای پیاده سازی فرآیند بالا بدون گرفتن دسترسی اضافه داریم ، صحبت خواهیم کرد .
برای شروع لازم است ، کامپوننت Play Services auth رو به فایل build.gradle اضافه کنیم :
implementation 'com.google.android.gms:play-services-auth:17.0.0' implementation 'com.google.android.gms:play-services-auth-api-phone:17.4.0'
حالا هر زمان که درخواست دریافت کد ارسال شد ( برای مثال وقتی کار بر روی دکمه دریافت کد اعتبار سنجی کلیک کرد ) کافیه دستور زیر رو اجرا کنیم :
SmsRetriever.getClient(context).startSmsUserConsent(senderPhoneNumber)
مقدار senderPhoneNumber میتونه سرشماره ای باشه که منتظریم ازش پیامک دریافت بشه . اگه این مقدار مشخص نیست میتونیم مقدار null قرار دهیم .
بعد از اجرای دستور بالا برای مدت ۵ دقیقه وقتی گوشی کاربر پیامکی دریافت کند ، Play services یک Intent به اپ ارسال می کند تا از کاربر اجازه دسترسی لازم دریافت بشه . البته متن پیامک باید شرایط زیر را داشته باشد :
خوب همونجوری که گفتیم اگه شرایط بالا وجود داشته باشه ، زمانی که پیامک دریافت شود Play services مارو با ارسال Intent با خبر میکنه و ما نیاز داریم که با یک BroadcastReceiver این مقدار رو دریافت کنیم .
private val SMS_CONSENT_REQUEST = 2 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 -> { val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT) try { 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) }
و البته یادمون نمیره که هر زمان کارمون با این دوستمون smsVerificationReceiver تموم شد ، حتما اونو unregister کنیم :
override fun () { // ... unregisterReceiver(smsVerificationReceiver) }
در متد onActivityResult اکتیویتی می توانیم بازخورد کاربر به دیالوگ نمایش داده شده در مرحله قبل که برای دریافت اجازه خواندن پیامک، نمایش داده شده بود را بررسی کنیم . اگر مقدار RESULT_OK را داشته باشیم، کاربر به ما اجازه خواندن متن پیام رو داده و می توانیم متن پیام ارسال شده را از مقدار intent دریافت کنیم .
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { // ... SMS_CONSENT_REQUEST -> if (resultCode == Activity.RESULT_OK && data != null) { // Get SMS message content val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE) val oneTimeCode = parseOneTimeCode(message) // define this function } else { // Consent denied. User can type OTC manually. } } }
در انتها کافیست پیام دریافت شده را تجزیه کرده و مقدار کد تایید را بدست بیاوریم و فیلد مورد نظر خودمون را با کد دریافتی تکمیل کنیم یا مرحله احراز هویت را با موفقیت رد کنیم .