1717package com.google.firebase.quickstart.auth.kotlin
1818
1919import android.os.Bundle
20- import android.util.Log
2120import android.view.LayoutInflater
2221import android.view.View
2322import android.view.ViewGroup
2423import android.widget.AdapterView
2524import android.widget.ArrayAdapter
26- import android.widget.Toast
27- import com.google.firebase.auth.FirebaseAuth
28- import com.google.firebase.auth.FirebaseUser
29- import com.google.firebase.auth.ktx.auth
30- import com.google.firebase.auth.ktx.oAuthProvider
31- import com.google.firebase.ktx.Firebase
25+ import androidx.core.view.isGone
26+ import androidx.fragment.app.viewModels
27+ import androidx.lifecycle.DefaultLifecycleObserver
28+ import androidx.lifecycle.Lifecycle
29+ import androidx.lifecycle.LifecycleOwner
30+ import androidx.lifecycle.lifecycleScope
31+ import androidx.lifecycle.repeatOnLifecycle
32+ import com.google.android.material.snackbar.Snackbar
3233import com.google.firebase.quickstart.auth.R
3334import com.google.firebase.quickstart.auth.databinding.FragmentGenericIdpBinding
34- import java.util.ArrayList
35+ import kotlinx.coroutines.launch
3536
3637/* *
3738 * Demonstrate Firebase Authentication using a Generic Identity Provider (IDP).
3839 */
3940class GenericIdpFragment : BaseFragment () {
4041
41- private lateinit var auth : FirebaseAuth
42+ private val viewModel by viewModels< GenericIdpViewModel >()
4243
4344 private var _binding : FragmentGenericIdpBinding ? = null
4445 private val binding: FragmentGenericIdpBinding
@@ -53,112 +54,56 @@ class GenericIdpFragment : BaseFragment() {
5354
5455 override fun onViewCreated (view : View , savedInstanceState : Bundle ? ) {
5556 super .onViewCreated(view, savedInstanceState)
56- // Initialize Firebase Auth
57- auth = Firebase .auth
5857
5958 // Set up button click listeners
60- binding.genericSignInButton.setOnClickListener { signIn() }
61- binding.signOutButton.setOnClickListener {
62- auth.signOut()
63- updateUI(null )
64- }
65-
66- // Spinner
67- val providers = ArrayList (PROVIDER_MAP .keys)
68- spinnerAdapter = ArrayAdapter (requireContext(), R .layout.item_spinner_list, providers)
69- binding.providerSpinner.adapter = spinnerAdapter
70- binding.providerSpinner.onItemSelectedListener = object : AdapterView .OnItemSelectedListener {
71- override fun onItemSelected (parent : AdapterView <* >, view : View , position : Int , id : Long ) {
72- binding.genericSignInButton.text =
73- getString(R .string.generic_signin_fmt, spinnerAdapter.getItem(position))
59+ binding.genericSignInButton.setOnClickListener {
60+ val providerName = spinnerAdapter.getItem(binding.providerSpinner.selectedItemPosition)
61+ if (providerName != null ) {
62+ viewModel.signIn(requireActivity(), providerName)
63+ } else {
64+ Snackbar .make(requireView(), " No provider selected" , Snackbar .LENGTH_SHORT ).show()
7465 }
75-
76- override fun onNothingSelected (parent : AdapterView <* >) {}
7766 }
78- binding.providerSpinner.setSelection(0 )
79- }
80-
81- override fun onStart () {
82- super .onStart()
83- // Check if user is signed in (non-null) and update UI accordingly.
84- val currentUser = auth.currentUser
85- updateUI(currentUser)
86-
87- // Look for a pending auth result
88- val pending = auth.pendingAuthResult
89- if (pending != null ) {
90- pending.addOnSuccessListener { authResult ->
91- Log .d(TAG , " checkPending:onSuccess:$authResult " )
92- updateUI(authResult.user)
93- }.addOnFailureListener { e ->
94- Log .w(TAG , " checkPending:onFailure" , e)
95- }
96- } else {
97- Log .d(TAG , " checkPending: null" )
67+ binding.signOutButton.setOnClickListener {
68+ viewModel.signOut()
9869 }
99- }
10070
101- private fun signIn () {
102- // Could add custom scopes here
103- val customScopes = ArrayList <String >()
104-
105- // Examples of provider ID: apple.com (Apple), microsoft.com (Microsoft), yahoo.com (Yahoo)
106- val providerId = getProviderId()
107-
108- auth.startActivityForSignInWithProvider(requireActivity(),
109- oAuthProvider(providerId, auth) {
110- scopes = customScopes
111- })
112- .addOnSuccessListener { authResult ->
113- Log .d(TAG , " activitySignIn:onSuccess:${authResult.user} " )
114- updateUI(authResult.user)
115- }
116- .addOnFailureListener { e ->
117- Log .w(TAG , " activitySignIn:onFailure" , e)
118- showToast(getString(R .string.error_sign_in_failed))
71+ viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
72+ override fun onStart (owner : LifecycleOwner ) {
73+ super .onStart(owner)
74+ viewModel.showSignedInUser()
75+ }
76+ })
77+
78+ lifecycleScope.launch {
79+ viewLifecycleOwner.repeatOnLifecycle(Lifecycle .State .STARTED ) {
80+ viewModel.uiState.collect { uiState ->
81+ binding.status.text = uiState.status
82+ binding.detail.text = uiState.detail
83+
84+ binding.genericSignInButton.isGone = ! uiState.isSignInVisible
85+ binding.signOutButton.isGone = uiState.isSignInVisible
86+ binding.spinnerLayout.isGone = ! uiState.isSignInVisible
87+
88+ // Spinner
89+ spinnerAdapter = ArrayAdapter (requireContext(), R .layout.item_spinner_list, uiState.providerNames)
90+ binding.providerSpinner.adapter = spinnerAdapter
91+ binding.providerSpinner.onItemSelectedListener = object : AdapterView .OnItemSelectedListener {
92+ override fun onItemSelected (parent : AdapterView <* >, view : View , position : Int , id : Long ) {
93+ binding.genericSignInButton.text =
94+ getString(R .string.generic_signin_fmt, spinnerAdapter.getItem(position))
95+ }
96+
97+ override fun onNothingSelected (parent : AdapterView <* >) {}
98+ }
99+ binding.providerSpinner.setSelection(0 )
119100 }
120- }
121-
122- private fun getProviderId (): String {
123- val providerName = spinnerAdapter.getItem(binding.providerSpinner.selectedItemPosition)
124- return PROVIDER_MAP [providerName!! ] ? : error(" No provider selected" )
125- }
126-
127- private fun updateUI (user : FirebaseUser ? ) {
128- hideProgressBar()
129- if (user != null ) {
130- binding.status.text = getString(R .string.generic_status_fmt, user.displayName, user.email)
131- binding.detail.text = getString(R .string.firebase_status_fmt, user.uid)
132-
133- binding.spinnerLayout.visibility = View .GONE
134- binding.genericSignInButton.visibility = View .GONE
135- binding.signOutButton.visibility = View .VISIBLE
136- } else {
137- binding.status.setText(R .string.signed_out)
138- binding.detail.text = null
139-
140- binding.spinnerLayout.visibility = View .VISIBLE
141- binding.genericSignInButton.visibility = View .VISIBLE
142- binding.signOutButton.visibility = View .GONE
101+ }
143102 }
144103 }
145104
146- private fun showToast (message : String ) {
147- Toast .makeText(context, message, Toast .LENGTH_SHORT ).show()
148- }
149-
150105 override fun onDestroyView () {
151106 super .onDestroyView()
152107 _binding = null
153108 }
154-
155- companion object {
156- private const val TAG = " GenericIdp"
157- private val PROVIDER_MAP = mapOf (
158- " Apple" to " apple.com" ,
159- " Microsoft" to " microsoft.com" ,
160- " Yahoo" to " yahoo.com" ,
161- " Twitter" to " twitter.com"
162- )
163- }
164109}
0 commit comments