├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── gradle.xml └── misc.xml ├── app ├── .gitignore ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── codingstuff │ │ └── phoneauthkt │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── codingstuff │ │ │ └── phoneauthkt │ │ │ ├── MainActivity.kt │ │ │ ├── OTPActivity.kt │ │ │ └── PhoneActivity.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── edit_text_bg.xml │ │ ├── ic_launcher_background.xml │ │ ├── otp_verification.jpg │ │ └── phone_auth.png │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_otpactivity.xml │ │ └── activity_phone.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── codingstuff │ └── phoneauthkt │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | id 'com.google.gms.google-services' 5 | } 6 | 7 | android { 8 | compileSdk 32 9 | 10 | defaultConfig { 11 | applicationId "com.codingstuff.phoneauthkt" 12 | minSdk 22 13 | targetSdk 32 14 | versionCode 1 15 | versionName "1.0" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | } 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | compileOptions { 27 | sourceCompatibility JavaVersion.VERSION_1_8 28 | targetCompatibility JavaVersion.VERSION_1_8 29 | } 30 | kotlinOptions { 31 | jvmTarget = '1.8' 32 | } 33 | } 34 | 35 | dependencies { 36 | 37 | implementation 'androidx.core:core-ktx:1.7.0' 38 | implementation 'androidx.appcompat:appcompat:1.4.2' 39 | implementation 'com.google.android.material:material:1.6.1' 40 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 41 | implementation 'com.google.firebase:firebase-auth:21.0.6' 42 | testImplementation 'junit:junit:4.13.2' 43 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 44 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 45 | } -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "602391208735", 4 | "project_id": "kotlinfirebase-23623", 5 | "storage_bucket": "kotlinfirebase-23623.appspot.com" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:602391208735:android:d85bb87b2d69faadeb062a", 11 | "android_client_info": { 12 | "package_name": "com.codingstuff.googlesignin_kt" 13 | } 14 | }, 15 | "oauth_client": [ 16 | { 17 | "client_id": "602391208735-em48qvt9eqcsg3mbpo4gun81hbnlu398.apps.googleusercontent.com", 18 | "client_type": 1, 19 | "android_info": { 20 | "package_name": "com.codingstuff.googlesignin_kt", 21 | "certificate_hash": "ed8aa85bfe44da15c2b2297c918dd5cfcad6a179" 22 | } 23 | }, 24 | { 25 | "client_id": "602391208735-6o2b7100a8dge82njudo3omrd75a6btm.apps.googleusercontent.com", 26 | "client_type": 3 27 | } 28 | ], 29 | "api_key": [ 30 | { 31 | "current_key": "AIzaSyC0MEvipnCpcaUAYQTU9-HJ1TV74tV9JCc" 32 | } 33 | ], 34 | "services": { 35 | "appinvite_service": { 36 | "other_platform_oauth_client": [ 37 | { 38 | "client_id": "602391208735-6o2b7100a8dge82njudo3omrd75a6btm.apps.googleusercontent.com", 39 | "client_type": 3 40 | } 41 | ] 42 | } 43 | } 44 | }, 45 | { 46 | "client_info": { 47 | "mobilesdk_app_id": "1:602391208735:android:551faa0956876be4eb062a", 48 | "android_client_info": { 49 | "package_name": "com.codingstuff.phoneauthkt" 50 | } 51 | }, 52 | "oauth_client": [ 53 | { 54 | "client_id": "602391208735-i11eadlqctqlmu7g5kf49vob8rgqlcf3.apps.googleusercontent.com", 55 | "client_type": 1, 56 | "android_info": { 57 | "package_name": "com.codingstuff.phoneauthkt", 58 | "certificate_hash": "ed8aa85bfe44da15c2b2297c918dd5cfcad6a179" 59 | } 60 | }, 61 | { 62 | "client_id": "602391208735-6o2b7100a8dge82njudo3omrd75a6btm.apps.googleusercontent.com", 63 | "client_type": 3 64 | } 65 | ], 66 | "api_key": [ 67 | { 68 | "current_key": "AIzaSyC0MEvipnCpcaUAYQTU9-HJ1TV74tV9JCc" 69 | } 70 | ], 71 | "services": { 72 | "appinvite_service": { 73 | "other_platform_oauth_client": [ 74 | { 75 | "client_id": "602391208735-6o2b7100a8dge82njudo3omrd75a6btm.apps.googleusercontent.com", 76 | "client_type": 3 77 | } 78 | ] 79 | } 80 | } 81 | } 82 | ], 83 | "configuration_version": "1" 84 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/codingstuff/phoneauthkt/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.codingstuff.phoneauthkt 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.codingstuff.phoneauthkt", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/phoneauthkt/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.codingstuff.phoneauthkt 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.widget.Button 6 | import androidx.appcompat.app.AppCompatActivity 7 | import com.google.firebase.auth.FirebaseAuth 8 | 9 | class MainActivity : AppCompatActivity() { 10 | 11 | private lateinit var auth: FirebaseAuth 12 | private lateinit var signOutBtn: Button 13 | 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | setContentView(R.layout.activity_main) 17 | 18 | auth = FirebaseAuth.getInstance() 19 | signOutBtn = findViewById(R.id.signOutBtn) 20 | 21 | signOutBtn.setOnClickListener { 22 | auth.signOut() 23 | startActivity(Intent(this, PhoneActivity::class.java)) 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/phoneauthkt/OTPActivity.kt: -------------------------------------------------------------------------------- 1 | package com.codingstuff.phoneauthkt 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.os.Handler 6 | import android.os.Looper 7 | import android.text.Editable 8 | import android.text.TextWatcher 9 | import android.util.Log 10 | import android.view.View 11 | import android.widget.* 12 | import androidx.appcompat.app.AppCompatActivity 13 | import com.google.firebase.FirebaseException 14 | import com.google.firebase.FirebaseTooManyRequestsException 15 | import com.google.firebase.auth.* 16 | import java.util.concurrent.TimeUnit 17 | 18 | class OTPActivity : AppCompatActivity() { 19 | 20 | private lateinit var auth: FirebaseAuth 21 | private lateinit var verifyBtn: Button 22 | private lateinit var resendTV: TextView 23 | private lateinit var inputOTP1: EditText 24 | private lateinit var inputOTP2: EditText 25 | private lateinit var inputOTP3: EditText 26 | private lateinit var inputOTP4: EditText 27 | private lateinit var inputOTP5: EditText 28 | private lateinit var inputOTP6: EditText 29 | private lateinit var progressBar: ProgressBar 30 | 31 | private lateinit var OTP: String 32 | private lateinit var resendToken: PhoneAuthProvider.ForceResendingToken 33 | private lateinit var phoneNumber: String 34 | 35 | override fun onCreate(savedInstanceState: Bundle?) { 36 | super.onCreate(savedInstanceState) 37 | setContentView(R.layout.activity_otpactivity) 38 | 39 | OTP = intent.getStringExtra("OTP").toString() 40 | resendToken = intent.getParcelableExtra("resendToken")!! 41 | phoneNumber = intent.getStringExtra("phoneNumber")!! 42 | 43 | init() 44 | progressBar.visibility = View.INVISIBLE 45 | addTextChangeListener() 46 | resendOTPTvVisibility() 47 | 48 | resendTV.setOnClickListener { 49 | resendVerificationCode() 50 | resendOTPTvVisibility() 51 | } 52 | 53 | verifyBtn.setOnClickListener { 54 | //collect otp from all the edit texts 55 | val typedOTP = 56 | (inputOTP1.text.toString() + inputOTP2.text.toString() + inputOTP3.text.toString() 57 | + inputOTP4.text.toString() + inputOTP5.text.toString() + inputOTP6.text.toString()) 58 | 59 | if (typedOTP.isNotEmpty()) { 60 | if (typedOTP.length == 6) { 61 | val credential: PhoneAuthCredential = PhoneAuthProvider.getCredential( 62 | OTP, typedOTP 63 | ) 64 | progressBar.visibility = View.VISIBLE 65 | signInWithPhoneAuthCredential(credential) 66 | } else { 67 | Toast.makeText(this, "Please Enter Correct OTP", Toast.LENGTH_SHORT).show() 68 | } 69 | } else { 70 | Toast.makeText(this, "Please Enter OTP", Toast.LENGTH_SHORT).show() 71 | } 72 | 73 | 74 | } 75 | } 76 | 77 | private fun resendOTPTvVisibility() { 78 | inputOTP1.setText("") 79 | inputOTP2.setText("") 80 | inputOTP3.setText("") 81 | inputOTP4.setText("") 82 | inputOTP5.setText("") 83 | inputOTP6.setText("") 84 | resendTV.visibility = View.INVISIBLE 85 | resendTV.isEnabled = false 86 | 87 | Handler(Looper.myLooper()!!).postDelayed(Runnable { 88 | resendTV.visibility = View.VISIBLE 89 | resendTV.isEnabled = true 90 | }, 60000) 91 | } 92 | 93 | private fun resendVerificationCode() { 94 | val options = PhoneAuthOptions.newBuilder(auth) 95 | .setPhoneNumber(phoneNumber) // Phone number to verify 96 | .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit 97 | .setActivity(this) // Activity (for callback binding) 98 | .setCallbacks(callbacks) 99 | .setForceResendingToken(resendToken)// OnVerificationStateChangedCallbacks 100 | .build() 101 | PhoneAuthProvider.verifyPhoneNumber(options) 102 | } 103 | 104 | private val callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() { 105 | 106 | override fun onVerificationCompleted(credential: PhoneAuthCredential) { 107 | // This callback will be invoked in two situations: 108 | // 1 - Instant verification. In some cases the phone number can be instantly 109 | // verified without needing to send or enter a verification code. 110 | // 2 - Auto-retrieval. On some devices Google Play services can automatically 111 | // detect the incoming verification SMS and perform verification without 112 | // user action. 113 | signInWithPhoneAuthCredential(credential) 114 | } 115 | 116 | override fun onVerificationFailed(e: FirebaseException) { 117 | // This callback is invoked in an invalid request for verification is made, 118 | // for instance if the the phone number format is not valid. 119 | 120 | if (e is FirebaseAuthInvalidCredentialsException) { 121 | // Invalid request 122 | Log.d("TAG", "onVerificationFailed: ${e.toString()}") 123 | } else if (e is FirebaseTooManyRequestsException) { 124 | // The SMS quota for the project has been exceeded 125 | Log.d("TAG", "onVerificationFailed: ${e.toString()}") 126 | } 127 | progressBar.visibility = View.VISIBLE 128 | // Show a message and update the UI 129 | } 130 | 131 | override fun onCodeSent( 132 | verificationId: String, 133 | token: PhoneAuthProvider.ForceResendingToken 134 | ) { 135 | // The SMS verification code has been sent to the provided phone number, we 136 | // now need to ask the user to enter the code and then construct a credential 137 | // by combining the code with a verification ID. 138 | // Save verification ID and resending token so we can use them later 139 | OTP = verificationId 140 | resendToken = token 141 | } 142 | } 143 | 144 | private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) { 145 | auth.signInWithCredential(credential) 146 | .addOnCompleteListener(this) { task -> 147 | if (task.isSuccessful) { 148 | // Sign in success, update UI with the signed-in user's information 149 | 150 | Toast.makeText(this, "Authenticate Successfully", Toast.LENGTH_SHORT).show() 151 | sendToMain() 152 | } else { 153 | // Sign in failed, display a message and update the UI 154 | Log.d("TAG", "signInWithPhoneAuthCredential: ${task.exception.toString()}") 155 | if (task.exception is FirebaseAuthInvalidCredentialsException) { 156 | // The verification code entered was invalid 157 | } 158 | // Update UI 159 | } 160 | progressBar.visibility = View.VISIBLE 161 | } 162 | } 163 | 164 | private fun sendToMain() { 165 | startActivity(Intent(this, MainActivity::class.java)) 166 | } 167 | 168 | private fun addTextChangeListener() { 169 | inputOTP1.addTextChangedListener(EditTextWatcher(inputOTP1)) 170 | inputOTP2.addTextChangedListener(EditTextWatcher(inputOTP2)) 171 | inputOTP3.addTextChangedListener(EditTextWatcher(inputOTP3)) 172 | inputOTP4.addTextChangedListener(EditTextWatcher(inputOTP4)) 173 | inputOTP5.addTextChangedListener(EditTextWatcher(inputOTP5)) 174 | inputOTP6.addTextChangedListener(EditTextWatcher(inputOTP6)) 175 | } 176 | 177 | private fun init() { 178 | auth = FirebaseAuth.getInstance() 179 | progressBar = findViewById(R.id.otpProgressBar) 180 | verifyBtn = findViewById(R.id.verifyOTPBtn) 181 | resendTV = findViewById(R.id.resendTextView) 182 | inputOTP1 = findViewById(R.id.otpEditText1) 183 | inputOTP2 = findViewById(R.id.otpEditText2) 184 | inputOTP3 = findViewById(R.id.otpEditText3) 185 | inputOTP4 = findViewById(R.id.otpEditText4) 186 | inputOTP5 = findViewById(R.id.otpEditText5) 187 | inputOTP6 = findViewById(R.id.otpEditText6) 188 | } 189 | 190 | 191 | inner class EditTextWatcher(private val view: View) : TextWatcher { 192 | override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { 193 | 194 | } 195 | 196 | override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { 197 | 198 | } 199 | 200 | override fun afterTextChanged(p0: Editable?) { 201 | 202 | val text = p0.toString() 203 | when (view.id) { 204 | R.id.otpEditText1 -> if (text.length == 1) inputOTP2.requestFocus() 205 | R.id.otpEditText2 -> if (text.length == 1) inputOTP3.requestFocus() else if (text.isEmpty()) inputOTP1.requestFocus() 206 | R.id.otpEditText3 -> if (text.length == 1) inputOTP4.requestFocus() else if (text.isEmpty()) inputOTP2.requestFocus() 207 | R.id.otpEditText4 -> if (text.length == 1) inputOTP5.requestFocus() else if (text.isEmpty()) inputOTP3.requestFocus() 208 | R.id.otpEditText5 -> if (text.length == 1) inputOTP6.requestFocus() else if (text.isEmpty()) inputOTP4.requestFocus() 209 | R.id.otpEditText6 -> if (text.isEmpty()) inputOTP5.requestFocus() 210 | 211 | } 212 | } 213 | 214 | } 215 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codingstuff/phoneauthkt/PhoneActivity.kt: -------------------------------------------------------------------------------- 1 | package com.codingstuff.phoneauthkt 2 | 3 | import android.content.Intent 4 | import androidx.appcompat.app.AppCompatActivity 5 | import android.os.Bundle 6 | import android.util.Log 7 | import android.view.View 8 | import android.widget.Button 9 | import android.widget.EditText 10 | import android.widget.ProgressBar 11 | import android.widget.Toast 12 | import com.google.firebase.FirebaseException 13 | import com.google.firebase.FirebaseTooManyRequestsException 14 | import com.google.firebase.auth.* 15 | import java.util.concurrent.TimeUnit 16 | 17 | class PhoneActivity : AppCompatActivity() { 18 | 19 | private lateinit var sendOTPBtn : Button 20 | private lateinit var phoneNumberET : EditText 21 | private lateinit var auth : FirebaseAuth 22 | private lateinit var number : String 23 | private lateinit var mProgressBar : ProgressBar 24 | 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(savedInstanceState) 27 | setContentView(R.layout.activity_phone) 28 | 29 | init() 30 | sendOTPBtn.setOnClickListener { 31 | number = phoneNumberET.text.trim().toString() 32 | if (number.isNotEmpty()){ 33 | if (number.length == 10){ 34 | number = "+91$number" 35 | mProgressBar.visibility = View.VISIBLE 36 | val options = PhoneAuthOptions.newBuilder(auth) 37 | .setPhoneNumber(number) // Phone number to verify 38 | .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit 39 | .setActivity(this) // Activity (for callback binding) 40 | .setCallbacks(callbacks) // OnVerificationStateChangedCallbacks 41 | .build() 42 | PhoneAuthProvider.verifyPhoneNumber(options) 43 | 44 | }else{ 45 | Toast.makeText(this , "Please Enter correct Number" , Toast.LENGTH_SHORT).show() 46 | } 47 | }else{ 48 | Toast.makeText(this , "Please Enter Number" , Toast.LENGTH_SHORT).show() 49 | 50 | } 51 | } 52 | } 53 | 54 | private fun init(){ 55 | mProgressBar = findViewById(R.id.phoneProgressBar) 56 | mProgressBar.visibility = View.INVISIBLE 57 | sendOTPBtn = findViewById(R.id.sendOTPBtn) 58 | phoneNumberET = findViewById(R.id.phoneEditTextNumber) 59 | auth = FirebaseAuth.getInstance() 60 | } 61 | 62 | private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) { 63 | auth.signInWithCredential(credential) 64 | .addOnCompleteListener(this) { task -> 65 | if (task.isSuccessful) { 66 | // Sign in success, update UI with the signed-in user's information 67 | Toast.makeText(this , "Authenticate Successfully" , Toast.LENGTH_SHORT).show() 68 | sendToMain() 69 | } else { 70 | // Sign in failed, display a message and update the UI 71 | Log.d("TAG", "signInWithPhoneAuthCredential: ${task.exception.toString()}") 72 | if (task.exception is FirebaseAuthInvalidCredentialsException) { 73 | // The verification code entered was invalid 74 | } 75 | // Update UI 76 | } 77 | mProgressBar.visibility = View.INVISIBLE 78 | } 79 | } 80 | 81 | private fun sendToMain(){ 82 | startActivity(Intent(this , MainActivity::class.java)) 83 | } 84 | private val callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() { 85 | 86 | override fun onVerificationCompleted(credential: PhoneAuthCredential) { 87 | // This callback will be invoked in two situations: 88 | // 1 - Instant verification. In some cases the phone number can be instantly 89 | // verified without needing to send or enter a verification code. 90 | // 2 - Auto-retrieval. On some devices Google Play services can automatically 91 | // detect the incoming verification SMS and perform verification without 92 | // user action. 93 | signInWithPhoneAuthCredential(credential) 94 | } 95 | 96 | override fun onVerificationFailed(e: FirebaseException) { 97 | // This callback is invoked in an invalid request for verification is made, 98 | // for instance if the the phone number format is not valid. 99 | 100 | if (e is FirebaseAuthInvalidCredentialsException) { 101 | // Invalid request 102 | Log.d("TAG", "onVerificationFailed: ${e.toString()}") 103 | } else if (e is FirebaseTooManyRequestsException) { 104 | // The SMS quota for the project has been exceeded 105 | Log.d("TAG", "onVerificationFailed: ${e.toString()}") 106 | } 107 | mProgressBar.visibility = View.VISIBLE 108 | // Show a message and update the UI 109 | } 110 | 111 | override fun onCodeSent( 112 | verificationId: String, 113 | token: PhoneAuthProvider.ForceResendingToken 114 | ) { 115 | // The SMS verification code has been sent to the provided phone number, we 116 | // now need to ask the user to enter the code and then construct a credential 117 | // by combining the code with a verification ID. 118 | // Save verification ID and resending token so we can use them later 119 | val intent = Intent(this@PhoneActivity , OTPActivity::class.java) 120 | intent.putExtra("OTP" , verificationId) 121 | intent.putExtra("resendToken" , token) 122 | intent.putExtra("phoneNumber" , number) 123 | startActivity(intent) 124 | mProgressBar.visibility = View.INVISIBLE 125 | } 126 | } 127 | 128 | 129 | override fun onStart() { 130 | super.onStart() 131 | if (auth.currentUser != null){ 132 | startActivity(Intent(this , MainActivity::class.java)) 133 | } 134 | } 135 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit_text_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/otp_verification.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingSTUFF070/Phone-Auth-Firebase-Kotlin/0dbb90ce67ec5eb9d53e693e5f96d18de9f20835/app/src/main/res/drawable/otp_verification.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/phone_auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodingSTUFF070/Phone-Auth-Firebase-Kotlin/0dbb90ce67ec5eb9d53e693e5f96d18de9f20835/app/src/main/res/drawable/phone_auth.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |