Skip to content

Commit

Permalink
Add basic phone number auth 👤
Browse files Browse the repository at this point in the history
  • Loading branch information
andraantariksa committed Apr 3, 2022
1 parent e03de99 commit bb1d83b
Show file tree
Hide file tree
Showing 17 changed files with 452 additions and 28 deletions.
5 changes: 4 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 9 additions & 8 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id "com.android.application"
id "kotlin-android"
id "kotlin-kapt"
id "dagger.hilt.android.plugin"
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
id "com.google.gms.google-services"
id "com.google.firebase.crashlytics"
id "androidx.navigation.safeargs.kotlin"
}

apply from: 'script/versioning.gradle'
Expand Down Expand Up @@ -70,6 +71,8 @@ dependencies {

// Serializer & deserializer
implementation "com.squareup.moshi:moshi:$moshiVersion"
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion"

// Hilt
Expand All @@ -82,11 +85,9 @@ dependencies {
// Logger
implementation 'com.jakewharton.timber:timber:5.0.1'


implementation 'com.google.firebase:firebase-appcheck-safetynet:16.0.0-beta05'
implementation "androidx.core:core-splashscreen:1.0.0-beta02"

implementation "com.airbnb.android:lottie:$lottieVersion"

implementation "androidx.preference:preference-ktx:1.2.0"

// debugImplementation "com.midtrans:uikit:1.31.0-SANDBOX"
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/kotlin/id/shaderboi/koffie/KoffieApplication.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package id.shaderboi.koffie

import android.app.Application
import com.google.firebase.FirebaseApp
import com.google.firebase.appcheck.FirebaseAppCheck
import com.google.firebase.appcheck.safetynet.SafetyNetAppCheckProviderFactory
import dagger.hilt.android.HiltAndroidApp
import id.shaderboi.koffie.util.logger.ReleaseTree
import timber.log.Timber
Expand All @@ -9,10 +12,17 @@ import timber.log.Timber
class KoffieApplication : Application() {
override fun onCreate() {
super.onCreate()

if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
} else {
Timber.plant(ReleaseTree())
}

FirebaseApp.initializeApp(this)
val firebaseAppCheck = FirebaseAppCheck.getInstance()
firebaseAppCheck.installAppCheckProviderFactory(
SafetyNetAppCheckProviderFactory.getInstance()
)
}
}
15 changes: 13 additions & 2 deletions app/src/main/kotlin/id/shaderboi/koffie/ui/auth/AuthActivity.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
package id.shaderboi.koffie.ui.auth

import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import dagger.hilt.android.AndroidEntryPoint
import id.shaderboi.koffie.databinding.ActivityAuthBinding
import id.shaderboi.koffie.ui.auth.view_model.SignInViewModel

@AndroidEntryPoint
class AuthActivity: AppCompatActivity() {
class AuthActivity : AppCompatActivity() {
private var _binding: ActivityAuthBinding? = null
val binding get() = _binding!!

private val signInViewModel by viewModels<SignInViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

_binding = ActivityAuthBinding.inflate(layoutInflater)

setContentView(binding.root)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package id.shaderboi.koffie.ui.auth

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import com.google.firebase.auth.FirebaseAuth
import dagger.hilt.android.AndroidEntryPoint
import id.shaderboi.koffie.databinding.FragmentRegistrationBinding
import id.shaderboi.koffie.databinding.FragmentSigninBinding
import id.shaderboi.koffie.databinding.FragmentVerifyBinding
import id.shaderboi.koffie.ui.auth.view_model.SignInEvent
import id.shaderboi.koffie.ui.auth.view_model.SignInViewModel
import javax.inject.Inject

@AndroidEntryPoint
class RegistrationFragment : Fragment() {
private var _binding: FragmentRegistrationBinding? = null
val binding get() = _binding!!

@Inject
lateinit var firebaseAuth: FirebaseAuth

private val signInViewModel by activityViewModels<SignInViewModel>()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentRegistrationBinding.inflate(inflater, container, false)

setupView()

return binding.root
}

private fun setupView() {
val navController = binding.root.findNavController()

binding.buttonSignIn.setOnClickListener {
val phoneNumber = binding.editTextPhone.text.toString()
signInViewModel.onEvent(SignInEvent.Verify(phoneNumber, requireActivity(), navController))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,60 @@
package id.shaderboi.koffie.ui.auth

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.google.firebase.FirebaseException
import com.google.firebase.auth.*
import dagger.hilt.android.AndroidEntryPoint
import id.shaderboi.koffie.databinding.FragmentSigninBinding
import id.shaderboi.koffie.ui.auth.view_model.SignInEvent
import id.shaderboi.koffie.ui.auth.view_model.SignInViewModel
import id.shaderboi.koffie.ui.main.MainActivity
import java.util.concurrent.TimeUnit
import javax.inject.Inject

@AndroidEntryPoint
class SignInFragment: Fragment() {
class SignInFragment : Fragment() {
private var _binding: FragmentSigninBinding? = null
val binding get() = _binding!!

@Inject
lateinit var firebaseAuth: FirebaseAuth

private val signInViewModel by activityViewModels<SignInViewModel>()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentSigninBinding.inflate(inflater)

setupView()

return binding.root
}

private fun setupView() {
val navController = findNavController()
binding.buttonSignIn.setOnClickListener {
val phoneNumber = binding.editTextPhone.text.toString()
signInViewModel.onEvent(
SignInEvent.SignIn(
phoneNumber,
requireActivity()
) {
val action =
SignInFragmentDirections.actionNavigationAuthSigninToNavigationAuthVerify()
navController.navigate(action)
}
)
}
}
}
49 changes: 49 additions & 0 deletions app/src/main/kotlin/id/shaderboi/koffie/ui/auth/VerifyFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package id.shaderboi.koffie.ui.auth

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.google.firebase.auth.FirebaseAuth
import dagger.hilt.android.AndroidEntryPoint
import id.shaderboi.koffie.databinding.FragmentSigninBinding
import id.shaderboi.koffie.databinding.FragmentVerifyBinding
import id.shaderboi.koffie.ui.auth.view_model.SignInEvent
import id.shaderboi.koffie.ui.auth.view_model.SignInViewModel
import javax.inject.Inject

@AndroidEntryPoint
class VerifyFragment : Fragment() {
private var _binding: FragmentVerifyBinding? = null
val binding get() = _binding!!

@Inject
lateinit var firebaseAuth: FirebaseAuth

private val signInViewModel by activityViewModels<SignInViewModel>()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentVerifyBinding.inflate(inflater, container, false)

setupView()

return binding.root
}

private fun setupView() {
val navController = findNavController()

binding.buttonSignIn.setOnClickListener {
val phoneNumber = binding.editTextPhone.text.toString()
signInViewModel.onEvent(SignInEvent.Verify(phoneNumber, requireActivity(), navController))
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package id.shaderboi.koffie.ui.auth.view_model

import android.app.Activity
import androidx.navigation.NavController

sealed class SignInEvent {
class SignIn(val phoneNumber: String, val activity: Activity, val onSent: () -> Unit) :
SignInEvent()

class Verify(
val phoneNumber: String,
val activity: Activity,
val navController: NavController
) : SignInEvent()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package id.shaderboi.koffie.ui.auth.view_model

import android.app.Activity
import android.content.Intent
import androidx.lifecycle.ViewModel
import androidx.navigation.NavController
import com.google.firebase.FirebaseException
import com.google.firebase.auth.*
import dagger.hilt.android.lifecycle.HiltViewModel
import id.shaderboi.koffie.ui.auth.SignInFragmentDirections
import id.shaderboi.koffie.ui.main.MainActivity
import java.util.concurrent.TimeUnit
import javax.inject.Inject

@HiltViewModel
class SignInViewModel @Inject constructor() : ViewModel() {
@Inject
lateinit var firebaseAuth: FirebaseAuth
private var verificationId: String? = null

fun onEvent(event: SignInEvent) {
when (event) {
is SignInEvent.SignIn -> signIn(event.phoneNumber, event.activity, event.onSent)
is SignInEvent.Verify -> verificationId?.let { verificationId ->
val credential = PhoneAuthProvider.getCredential(verificationId, event.phoneNumber)
signInWithPhoneAuthCredential(credential, event.activity)
}
}
}

private fun signIn(phoneNumber: String, activity: Activity, onSent: () -> Unit) {
val options = PhoneAuthOptions
.newBuilder(firebaseAuth)
.setPhoneNumber(phoneNumber)
.setTimeout(60L, TimeUnit.SECONDS)
.setActivity(activity)
.setCallbacks(
object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
override fun onVerificationCompleted(credential: PhoneAuthCredential) {
signInWithPhoneAuthCredential(credential, activity)
}

override fun onVerificationFailed(exception: FirebaseException) {
exception
}

override fun onCodeSent(
_verificationId: String,
forceResendingToken: PhoneAuthProvider.ForceResendingToken
) {
verificationId = _verificationId

onSent()
}
}
)
.build()
PhoneAuthProvider.verifyPhoneNumber(options)
}

private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential, activity: Activity) {
firebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(activity) { task ->
if (task.isSuccessful) {
val intent = Intent(activity, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
activity.startActivity(intent)
} else {
if (task.exception is FirebaseAuthInvalidCredentialsException) {
}
}
}
}
}
12 changes: 9 additions & 3 deletions app/src/main/res/layout/activity_auth.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
<androidx.fragment.app.FragmentContainerView xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:id="@+id/fragmentContainerViewMain"
android:name="androidx.navigation.fragment.NavHostFragment"

</androidx.constraintlayout.widget.ConstraintLayout>
app:defaultNavHost="true"
app:navGraph="@navigation/navigation_auth"
tools:context=".ui.auth.AuthActivity" />
Loading

0 comments on commit bb1d83b

Please sign in to comment.