17
17
package com.google.firebase.quickstart.auth.kotlin
18
18
19
19
import android.os.Bundle
20
- import android.util.Log
21
20
import android.view.LayoutInflater
22
21
import android.view.View
23
22
import android.view.ViewGroup
24
23
import android.widget.AdapterView
25
24
import 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
32
33
import com.google.firebase.quickstart.auth.R
33
34
import com.google.firebase.quickstart.auth.databinding.FragmentGenericIdpBinding
34
- import java.util.ArrayList
35
+ import kotlinx.coroutines.launch
35
36
36
37
/* *
37
38
* Demonstrate Firebase Authentication using a Generic Identity Provider (IDP).
38
39
*/
39
40
class GenericIdpFragment : BaseFragment () {
40
41
41
- private lateinit var auth : FirebaseAuth
42
+ private val viewModel by viewModels< GenericIdpViewModel >()
42
43
43
44
private var _binding : FragmentGenericIdpBinding ? = null
44
45
private val binding: FragmentGenericIdpBinding
@@ -53,112 +54,56 @@ class GenericIdpFragment : BaseFragment() {
53
54
54
55
override fun onViewCreated (view : View , savedInstanceState : Bundle ? ) {
55
56
super .onViewCreated(view, savedInstanceState)
56
- // Initialize Firebase Auth
57
- auth = Firebase .auth
58
57
59
58
// 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()
74
65
}
75
-
76
- override fun onNothingSelected (parent : AdapterView <* >) {}
77
66
}
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()
98
69
}
99
- }
100
70
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 )
119
100
}
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
+ }
143
102
}
144
103
}
145
104
146
- private fun showToast (message : String ) {
147
- Toast .makeText(context, message, Toast .LENGTH_SHORT ).show()
148
- }
149
-
150
105
override fun onDestroyView () {
151
106
super .onDestroyView()
152
107
_binding = null
153
108
}
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
- }
164
109
}
0 commit comments