Flutter package for listening SMS code on Android, suggesting phone number, email, saving a credential.
If you need pin code input like shown below, take a look at the Pinput package.
Features:
- Android SMS Autofill
- Credential Manager API
- Get saved passwords and passkeys -
getCredential - Save a password -
createPasswordCredential - Create a passkey -
createPublicKeyCredential - Speed up the account selector on Android 14+ -
prepareGetCredential,getPreparedCredential - Clear the credential state on sign out -
clearCredentialState
- Get saved passwords and passkeys -
- Showing Phone number hints API
Support
Discord Channel
Don't forget to give it a star ⭐
If you want to contribute to this project, please read the contribution guide.
Requirements
Flutter 3.44 or above, the plugin is tested with Flutter 3.47.
Android build tools
AGP, Gradle and Kotlin versions are dictated by your Flutter version. Flutter checks them when
building and tells you what to upgrade, and a project created with flutter create already has
them. For example Flutter 3.47 requires:
| Tool | Minimum |
|---|---|
| Android Gradle Plugin (AGP) | 8.11.1 (Flutter will move to 9.0.1) |
| Gradle | 8.14 (Flutter will move to 9.1.0) |
| Kotlin | 2.2.20 (Flutter will move to 2.3.20) |
The plugin also works with AGP 9, where Kotlin is built in, see the
migration guide.
With AGP 9 you don't need the kotlin-gradle-plugin classpath or the org.jetbrains.kotlin.android
plugin, and kotlinOptions is deprecated.
Requirements added by this package
| Requirement | Minimum |
|---|---|
compileSdk |
35 or above |
| JDK that runs Gradle | 17 or above, JDK 25 doesn't work with Gradle 8.14 |
| Java source and target version | 11 or above |
compileSdk is the API your app is compiled against, it doesn't drop any devices.
The Android Credential Manager dependency requires 35, and older AGP versions only officially
support up to 34.
// android/app/build.gradle
android {
compileSdk = 35
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
Supported Android devices
- Android 7.0 (API 24) or above, the minimum of Flutter 3.44 apps.
- Google Play services is required for the SMS Retriever, SMS User Consent and phone number hint APIs, and for the Credential Manager on Android 13 and below.
prepareGetCredentialandgetPreparedCredentialneed Android 14 (API 34) or above, they fail withUNSUPPORTEDon older versions.
Migrating from 2.x to 3.x
| 2.x | 3.x |
|---|---|
SmartAuth() |
SmartAuth.instance |
getSmsCode() returning SmsCodeResult |
getSmsWithRetrieverApi() / getSmsWithUserConsentApi() returning SmartAuthResult<SmartAuthSms> |
res.succeed && res.codeFound, res.code |
res.hasData, res.data?.code |
getAppSignature() returning String? |
returns SmartAuthResult<String>, read the value with res.data |
removeSmsListener() |
removeSmsRetrieverApiListener() / removeUserConsentApiListener() |
See the example for full usage.
Getting Started
Create instance of SmartAuth
final smartAuth = SmartAuth.instance;
Credential Manager - Docs
Get, save and clear passwords and passkeys with the Android Credential Manager.
Every method returns a SmartAuthResult, isCanceled is true when the user dismisses the dialog.
// Show saved passwords and passkeys
final result = await smartAuth.getCredential(
passwordOption: SmartAuthPasswordOption(),
publicKeyOptions: [SmartAuthPublicKeyOption(requestJson: requestJsonFromServer)],
);
final credential = result.data;
// credential.type is password or publicKey
// password: credential.id, credential.password
// passkey: credential.authenticationResponseJson
// Save a password
await smartAuth.createPasswordCredential(id: 'user@example.com', password: 'secret');
// Create a passkey, send registrationResponseJson to your server
final created = await smartAuth.createPublicKeyCredential(requestJson: requestJsonFromServer);
// Android 14+: fetch the data first to show the account selector faster
final prepared = await smartAuth.prepareGetCredential(passwordOption: SmartAuthPasswordOption());
if (prepared.hasData) {
final credential = await smartAuth.getPreparedCredential();
}
// On sign out
await smartAuth.clearCredentialState();
Notes:
prepareGetCredentialandgetPreparedCredentialneed Android 14 or higher, below that they fail withUNSUPPORTED.- Only privileged apps can see which credentials
prepareGetCredentialfound, thehas*fields ofSmartAuthPreparedCredentialarenullfor other apps. It still makes the nextgetPreparedCredentialfaster. - Failed results contain one of these codes in
error:
| Code | Meaning |
|---|---|
NO_CREDENTIAL |
Nothing to show, the user has no matching saved credentials |
INVALID_REQUEST |
The request is incomplete, e.g. getCredential without any option |
NO_ACTIVITY |
There is no foreground activity to show the dialog on |
UNSUPPORTED |
The method needs a newer Android version |
NO_PREPARED_CREDENTIAL |
getPreparedCredential was called before prepareGetCredential |
GET_CREDENTIAL_FAILED, CREATE_CREDENTIAL_FAILED, PREPARE_GET_CREDENTIAL_FAILED, CLEAR_CREDENTIAL_STATE_FAILED |
The Credential Manager reported an error |
Request phone number hint - Docs
The Phone Number Hint API, a library powered by Google Play services, provides a frictionless way to show a user’s (SIM-based) phone numbers as a hint.
The benefits to using Phone Number Hint include the following:
- No additional permission requests are needed
- Eliminates the need for the user to manually type in the phone number
- No Google account is needed
- Not directly tied to sign in/up workflows
- Wider support for Android versions compared to Autofill
void requestPhoneNumberHint() async {
final res = await smartAuth.requestPhoneNumberHint();
if (res.hasData) {
// Use the phone number
} else {
// Handle error
}
}
Get SMS with User Consent API
The SMS User Consent API complements the SMS Retriever API by allowing an app to prompt the user to grant access to the content of a single SMS message. When a user gives consent, the app will then have access to the entire message body to automatically complete SMS verification. The verification flow looks like this:
- A user initiates SMS verification in your app. Your app might prompt the user to provide a phone
number manually or request the phone number hint by calling
requestPhoneNumberHintmethod. - Your app makes a request to your server to verify the user's phone number. Depending on what information is available in your user database, this request might include the user's ID, the user's phone number, or both.
- At the same time, your app calls the
getSmsWithUserConsentApito show the user a dialog to grant access to the SMS message. - Your server sends an SMS message to the user that includes a one-time code to be sent back to your server.
- When the user's device receives the SMS message, the
getSmsWithUserConsentApiwill extract the one-time code from the message text and you have to send it back to your server. - Your server receives the one-time code from your app, verifies the code, and finally records that the user has successfully verified their account.
void getSmsWithUserConsentApi() async {
final res = await smartAuth.getSmsWithUserConsentApi();
if (res.hasData) {
final code = res.requireData.code;
/// The code can be null if the SMS was received but the code was not extracted from it
if (code == null) return;
// Use the code
} else if (res.isCanceled) {
// User canceled the dialog
} else {
// handle the error
}
}
Get SMS with SMS Retriever API
With the SMS Retriever API, you can perform SMS-based user verification in your Android app automatically, without requiring the user to manually type verification codes, and without requiring any extra app permissions. When you implement automatic SMS verification in your app, the verification flow looks like this:
- A user initiates SMS verification in your app. Your app might prompt the user to provide a phone
number manually or request the phone number hint by calling
requestPhoneNumberHintmethod. - Your app makes a request to your server to verify the user's phone number. Depending on what information is available in your user database, this request might include the user's ID, the user's phone number, or both.
- At the same time, your app calls the
getSmsWithRetrieverApito begin listening for an SMS response from your server. - Your server sends an SMS message to the user that includes a one-time code to be sent back to your server, and a hash that identifies your app.
- When the user's device receives the SMS message, Google Play services uses the app hash to determine that the message is intended for your app, and makes the message text available to your app through the SMS Retriever API.
- The
getSmsWithRetrieverApiwill extract the one-time code from the message text and you have to send it back to your server. - Your server receives the one-time code from your app, verifies the code, and finally records that the user has successfully verified their account.
void getSmsWithRetrieverApi() async {
final res = await smartAuth.getSmsWithRetrieverApi();
if (res.hasData) {
final code = res.requireData.code;
/// The code can be null if the SMS was received but the code was not extracted from it
if (code == null) return;
// Use the code
} else {
// handle the error
}
}
Dispose
The plugin automatically removes listeners after receiving the code, if not you can remove them by
calling the removeUserConsentApiListener or removeSmsRetrieverApiListener method.
void removeSmsListener() {
smartAuth.removeUserConsentApiListener();
// or
smartAuth.removeSmsRetrieverApiListener();
}
Libraries
- smart_auth
- Flutter package for listening SMS code on Android, suggesting phone number, email, saving a credential.