Key Points
- The Automatic SMS Retriever API helps Android apps automatically read verification codes from SMS without user permission, improving user experience.
- The SMS User Consent API, likely what “consent mode” refers to, prompts users for permission to read a specific SMS, offering a fallback option.
- In Kotlin Multiplatform (KMP) projects, these APIs are implemented in the Android module, with shared logic for verification handled across platforms.
- Research suggests integrating these APIs in KMP involves defining platform-specific interfaces, with examples provided for both automatic and user consent flows.
What is the Automatic SMS Retriever API?
The Automatic SMS Retriever API, part of Google Play Services, lets your Android app automatically grab verification codes from SMS messages without needing the user to grant SMS permissions. This means users don’t have to manually type in OTPs, making the process smoother and faster. It works by checking for a specific SMS format that includes an app hash, ensuring only your app can read the message.
How Does Consent Mode Fit In?
It seems likely that “consent mode” refers to the SMS User Consent API, which complements the Retriever API. This API prompts the user to allow your app to read a single SMS if automatic retrieval fails, like if the SMS format isn’t right or there’s a timeout. It’s a handy fallback, especially when you don’t control the SMS format.
Using These APIs in KMP Projects
For Kotlin Multiplatform (KMP) projects, you implement these APIs in the Android part, as they’re Android-specific. You can share the verification logic, like sending requests to a server or parsing OTPs, across platforms. This involves creating an interface in the common code and implementing it in the Android module, with examples showing how to start both automatic and user consent flows.
Unexpected Detail: KMP Integration
An interesting aspect is how KMP lets you share business logic while keeping platform-specific code separate. For instance, you might not expect that you can define a shared flow for OTP handling, making the integration feel seamless across Android and other platforms like iOS, even though iOS uses different methods for SMS verification.
Survey Note: Detailed Analysis of Automatic SMS Retriever API with Consent Mode for Android and KMP
Introduction and Context
As of March 30, 2025, the landscape of mobile app development continues to evolve, with a strong emphasis on enhancing user experience through seamless authentication methods. One such method is automatic SMS verification, which is particularly relevant for Android applications using Kotlin, especially within Kotlin Multiplatform (KMP) projects. This note explores the Automatic SMS Retriever API, its integration with what appears to be the SMS User Consent API (referred to as “consent mode” in the query), and how these can be implemented in both standard Android apps and KMP projects using the latest Kotlin version, identified as 2.1.20 from recent documentation (Kotlin releases | Kotlin Documentation).
The Automatic SMS Retriever API, part of Google Play Services, enables apps to automatically retrieve SMS messages containing verification codes without requiring SMS permissions, thus improving user convenience by eliminating manual OTP entry. The SMS User Consent API, on the other hand, allows apps to prompt users for permission to read a specific SMS, serving as a fallback when automatic retrieval isn’t possible. Given the query’s focus on “consent mode,” it seems likely this refers to the SMS User Consent API, though initial research didn’t find direct references to “consent mode” within the API documentation, suggesting it might be a colloquial or contextual term.
For KMP, which facilitates code sharing across platforms like Android and iOS, integrating these Android-specific APIs requires careful structuring of platform-specific and shared code. The latest KMP version, 2.1.20, supports such integrations, and this note will provide detailed implementation examples, considering the current date and ensuring compatibility with recent Android and Kotlin updates.
Understanding the Automatic SMS Retriever API
The SMS Retriever API, detailed in the official Google documentation (Automatic SMS Verification with the SMS Retriever API | Credential Verification | Google for Developers), is designed for automatic SMS-based user verification. It operates by listening for SMS messages that follow a specific format, starting with “<#>” and including an 11-character app hash generated from the app’s signing certificate. This ensures security, as only the intended app can retrieve the message. The API is available on Android devices with Play Services version 10.2 and newer, and it doesn’t require the READ_SMS permission, aligning with modern privacy standards.
The process involves the app starting a listener via SmsRetriever.getClient(context).startSmsRetriever()
, which then broadcasts the SMS content to a registered receiver when a matching message arrives. The receiver parses the message to extract the OTP, typically a one-time code, and sends it to the server for verification. This flow is ideal for apps like Uber or WhatsApp, where seamless onboarding is crucial.
Implementing the SMS Retriever API in Android
To implement this in an Android app using Kotlin, you first need to add the dependency to your build.gradle
:
dependencies {
implementation 'com.google.android.gms:play-services-auth:21.3.0'
}
The version 21.3.0 was identified as the latest for play-services-auth from the Maven repository (Maven Repository: com.google.android.gms » play-services-auth), ensuring compatibility as of December 2024, likely still current in March 2025.
Here’s a sample implementation:
import com.google.android.gms.auth.api.phone.SmsRetriever
import com.google.android.gms.tasks.Task
val client = SmsRetriever.getClient(this)
val task: Task<Void> = client.startSmsRetriever()
task.addOnSuccessListener {
// Successfully started retriever, expect broadcast intent
}.addOnFailureListener {
// Failed to start retriever
}
You then need a broadcast receiver to handle the SMS:
class SmsRetrieverReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
val extras = intent.extras
val status = extras?.get(SmsRetriever.EXTRA_STATUS) as Status
when (status.statusCode) {
CommonStatusCodes.SUCCESS -> {
val message = extras.get(SmsRetriever.EXTRA_SMS_MESSAGE) as String
val otp = parseOtpFromMessage(message)
verifyOtp(otp)
}
CommonStatusCodes.TIMEOUT -> {
// Handle timeout, perhaps fall back to user consent
}
}
}
}
private fun parseOtpFromMessage(message: String): String {
return message.split(" ").last() // Example: assumes OTP is last word
}
private fun verifyOtp(otp: String) {
// Send to server for verification
}
}
Register this receiver in your manifest or dynamically, and ensure the SMS format includes the app hash, generated via:
fun getAppHash(context: Context): String {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES)
val signature = packageInfo.signatures[0]
val md = MessageDigest.getInstance("SHA")
md.update(signature.toByteArray())
val bytes = md.digest()
val base64 = Base64.encodeToString(bytes, Base64.NO_WRAP)
return base64.substring(0, 11)
}
The server must include this hash in the SMS, like <#> Your verification code is 123456 AppHashHere
, ensuring Google Play Services recognizes it.
Exploring the SMS User Consent API
Given the query’s mention of “consent mode,” it seems likely this refers to the SMS User Consent API, detailed in (One-tap SMS verification with the SMS User Consent API | Credential Verification | Google for Developers). This API is used when automatic retrieval isn’t feasible, prompting the user to grant permission to read a single SMS. It’s useful for scenarios where you don’t control the SMS format, such as financial apps verifying phone numbers.
The implementation steps, from the documentation, are:
Step | Description |
---|---|
0 | App calls SMS User Consent API to begin listening for SMS response. SMS received before starting will not be forwarded. |
1 | App requests server to verify user’s phone number via SMS. |
2 | Upon receiving SMS with one-time code, Google Play services shows message to user and asks for consent to share with app. |
3 | If user consents, entire SMS message is made available to app. |
4 | App parses one-time code from message and sends it to server. |
To implement, start with:
val client = SmsRetriever.getClient(this)
val task = client.startSmsUserConsent(null) // null for any sender
task.addOnSuccessListener {
// Started successfully
}.addOnFailureListener {
// Failed to start
}
Set up a receiver to handle the consent intent:
class SmsConsentReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
val extras = intent.extras
val status = extras?.get(SmsRetriever.EXTRA_STATUS) as Status
when (status.statusCode) {
CommonStatusCodes.SUCCESS -> {
val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
try {
(context as Activity).startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
} catch (e: ActivityNotFoundException) {
// Handle exception
}
}
CommonStatusCodes.TIMEOUT -> {
// Handle timeout
}
}
}
}
}
In the activity, handle the result:
private val SMS_CONSENT_REQUEST = 1001
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == SMS_CONSENT_REQUEST && resultCode == Activity.RESULT_OK && data != null) {
val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
val otp = parseOtpFromMessage(message)
verifyOtp(otp)
} else {
// Consent denied, handle manually
}
}
This flow ensures users are prompted, maintaining privacy while offering convenience.
Integrating with Kotlin Multiplatform (KMP)
KMP, as described in (Kotlin Multiplatform | Kotlin Documentation), allows sharing code across platforms, with version 2.1.20 being the latest as of recent updates. For the SMS APIs, which are Android-specific, you use the expect/actual mechanism to define platform-specific implementations.
Define an interface in commonMain:
expect class SmsVerificationService {
fun startSmsRetrieval(onOtpReceived: (String) -> Unit)
fun startSmsUserConsent(onOtpReceived: (String) -> Unit)
}
In androidMain, implement it:
actual class SmsVerificationService actual constructor(private val context: Context) {
private var callback: ((String) -> Unit)? = null
actual fun startSmsRetrieval(onOtpReceived: (String) -> Unit) {
callback = onOtpReceived
val client = SmsRetriever.getClient(context)
client.startSmsRetriever().addOnSuccessListener {
// Handle success
}.addOnFailureListener {
// Handle failure
}
// Set up receiver to call callback when OTP received
}
actual fun startSmsUserConsent(onOtpReceived: (String) -> Unit) {
callback = onOtpReceived
val client = SmsRetriever.getClient(context)
client.startSmsUserConsent(null).addOnSuccessListener {
// Handle success
}.addOnFailureListener {
// Handle failure
}
// Set up receiver for consent
}
}
In shared code, use this service to handle verification, ensuring business logic like server communication is shared, while SMS retrieval remains platform-specific.
Example Use Case and Best Practices
Consider a login screen: the user enters a phone number, the app requests verification, and starts SMS retrieval. If automatic retrieval fails, it falls back to user consent. In KMP, the repository pattern can manage this, with the Android module handling SMS and the common module managing server calls.
Best practices include:
- Ensure SMS format compliance for security.
- Handle timeouts (5 minutes for Retriever API) with user consent as fallback.
- Check for Google Play Services availability, as some devices (e.g., Amazon Kindle) lack it.
- Test thoroughly, as app hash generation and receiver setup can be error-prone.
Conclusion
This detailed exploration shows how to implement automatic SMS verification using the SMS Retriever API and SMS User Consent API in Android with Kotlin, extending to KMP projects for shared logic. By leveraging these APIs, developers can enhance user experience, ensuring seamless and secure verification processes, especially in cross-platform applications as of March 2025.
Key Citations:
- Automatic SMS Verification with the SMS Retriever API overview Google for Developers
- One-tap SMS verification with the SMS User Consent API overview Google for Developers
- Kotlin Multiplatform documentation Kotlin Documentation
- Kotlin releases documentation Kotlin Documentation
- Maven Repository play-services-auth latest version