55import android .content .Intent ;
66import android .os .Bundle ;
77import android .text .TextUtils ;
8+ import android .util .Log ;
89
910import com .firebase .ui .auth .AuthUI ;
1011import com .firebase .ui .auth .ErrorCodes ;
2425import com .firebase .ui .auth .util .data .ProviderUtils ;
2526import com .firebase .ui .auth .viewmodel .RequestCodes ;
2627import com .firebase .ui .auth .viewmodel .SignInViewModelBase ;
27- import com .google .android .gms .auth .api .credentials .Credential ;
28- import com .google .android .gms .auth .api .credentials .CredentialRequest ;
29- import com .google .android .gms .auth .api .credentials .CredentialRequestResponse ;
3028import com .google .android .gms .common .api .ApiException ;
3129import com .google .android .gms .common .api .CommonStatusCodes ;
3230import com .google .android .gms .common .api .ResolvableApiException ;
33- import com .google .android .gms .tasks .OnCompleteListener ;
34- import com .google .android .gms .tasks .OnFailureListener ;
35- import com .google .android .gms .tasks .OnSuccessListener ;
3631import com .google .android .gms .tasks .Task ;
3732import com .google .firebase .auth .AuthResult ;
3833import com .google .firebase .auth .EmailAuthProvider ;
4136import com .google .firebase .auth .GoogleAuthProvider ;
4237import com .google .firebase .auth .PhoneAuthProvider ;
4338
39+ // Minimal changes: import new API classes
40+ import com .google .android .gms .auth .api .identity .BeginSignInRequest ;
41+ import com .google .android .gms .auth .api .identity .SignInClient ;
42+ import com .google .android .gms .auth .api .identity .SignInCredential ;
43+ import com .google .android .gms .auth .api .identity .Identity ;
44+
4445import java .util .ArrayList ;
4546import java .util .List ;
4647
5051import static com .firebase .ui .auth .AuthUI .EMAIL_LINK_PROVIDER ;
5152
5253public class SignInKickstarter extends SignInViewModelBase {
54+ private static final String TAG = "SignInKickstarter" ;
55+
5356 public SignInKickstarter (Application application ) {
5457 super (application );
5558 }
@@ -62,58 +65,59 @@ public void start() {
6265 return ;
6366 }
6467
65- // Signing in with Generic IDP puts the app in the background - it can be reclaimed by the
66- // OS during the sign in flow.
68+ // Signing in with Generic IDP puts the app in the background -
69+ // it can be reclaimed by the OS during the sign in flow.
6770 Task <AuthResult > pendingResultTask = getAuth ().getPendingAuthResult ();
6871 if (pendingResultTask != null ) {
6972 pendingResultTask
70- .addOnSuccessListener (
71- authResult -> {
72- final IdpResponse response = new IdpResponse .Builder (
73- new User .Builder (
74- authResult .getCredential ().getProvider (),
75- authResult .getUser ().getEmail ()).build ())
76- .build ();
77- handleSuccess (response , authResult );
78-
79- })
80- .addOnFailureListener (
81- e -> setResult (Resource .forFailure (e )));
73+ .addOnSuccessListener (authResult -> {
74+ final IdpResponse response = new IdpResponse .Builder (
75+ new User .Builder (
76+ authResult .getCredential ().getProvider (),
77+ authResult .getUser ().getEmail ()).build ())
78+ .build ();
79+ handleSuccess (response , authResult );
80+ })
81+ .addOnFailureListener (e -> setResult (Resource .forFailure (e )));
8282 return ;
8383 }
8484
85-
86- // Only support password credentials if email auth is enabled
8785 boolean supportPasswords = ProviderUtils .getConfigFromIdps (
8886 getArguments ().providers , EmailAuthProvider .PROVIDER_ID ) != null ;
8987 List <String > accountTypes = getCredentialAccountTypes ();
90-
91- // If the request will be empty, avoid the step entirely
92- boolean willRequestCredentials = supportPasswords || accountTypes .size () > 0 ;
88+ boolean willRequestCredentials = supportPasswords || !accountTypes .isEmpty ();
9389
9490 if (getArguments ().enableCredentials && willRequestCredentials ) {
9591 setResult (Resource .forLoading ());
9692
97- GoogleApiUtils .getCredentialsClient (getApplication ())
98- .request (new CredentialRequest .Builder ()
99- .setPasswordLoginSupported (supportPasswords )
100- .setAccountTypes (accountTypes .toArray (new String [accountTypes .size ()]))
101- .build ())
102- .addOnCompleteListener (task -> {
103- try {
104- handleCredential (
105- task .getResult (ApiException .class ).getCredential ());
106- } catch (ResolvableApiException e ) {
107- if (e .getStatusCode () == CommonStatusCodes .RESOLUTION_REQUIRED ) {
108- setResult (Resource .forFailure (
109- new PendingIntentRequiredException (
110- e .getResolution (), RequestCodes .CRED_HINT )));
111- } else {
112- startAuthMethodChoice ();
113- }
114- } catch (ApiException e ) {
115- startAuthMethodChoice ();
116- }
93+ // Minimal change: use new SignInClient with BeginSignInRequest.
94+ SignInClient signInClient = Identity .getSignInClient (getApplication ());
95+ BeginSignInRequest .Builder requestBuilder = BeginSignInRequest .builder ();
96+ if (supportPasswords ) {
97+ requestBuilder .setPasswordRequestOptions (
98+ BeginSignInRequest .PasswordRequestOptions .builder ()
99+ .setSupported (true )
100+ .build ());
101+ }
102+ if (!accountTypes .isEmpty ()) {
103+ // For Google Sign-In, set the ID token request options.
104+ requestBuilder .setGoogleIdTokenRequestOptions (
105+ BeginSignInRequest .GoogleIdTokenRequestOptions .builder ()
106+ .setSupported (true )
107+ .build ());
108+ }
109+ BeginSignInRequest signInRequest = requestBuilder .build ();
110+
111+ signInClient .beginSignIn (signInRequest )
112+ .addOnSuccessListener (result -> {
113+ // The new API returns a PendingIntent to launch the sign-in UI.
114+ setResult (Resource .forFailure (
115+ new PendingIntentRequiredException (result .getPendingIntent (), RequestCodes .CRED_HINT )));
116+ })
117+ .addOnFailureListener (e -> {
118+ Log .e (TAG , "beginSignIn failed: " + e );
119+ // Regardless of the error (including error code 16), fallback to the auth method choice.
120+ startAuthMethodChoice ();
117121 });
118122 } else {
119123 startAuthMethodChoice ();
@@ -133,8 +137,7 @@ private void startAuthMethodChoice() {
133137 break ;
134138 case PhoneAuthProvider .PROVIDER_ID :
135139 setResult (Resource .forFailure (new IntentRequiredException (
136- PhoneActivity .createIntent (
137- getApplication (), getArguments (), firstIdpConfig .getParams ()),
140+ PhoneActivity .createIntent (getApplication (), getArguments (), firstIdpConfig .getParams ()),
138141 RequestCodes .PHONE_FLOW )));
139142 break ;
140143 default :
@@ -159,17 +162,12 @@ private void redirectSignIn(String provider, String id) {
159162 Bundle args = new Bundle ();
160163 args .putString (ExtraConstants .PHONE , id );
161164 setResult (Resource .forFailure (new IntentRequiredException (
162- PhoneActivity .createIntent (
163- getApplication (),
164- getArguments (),
165- args ),
165+ PhoneActivity .createIntent (getApplication (), getArguments (), args ),
166166 RequestCodes .PHONE_FLOW )));
167167 break ;
168168 default :
169169 setResult (Resource .forFailure (new IntentRequiredException (
170- SingleSignInActivity .createIntent (
171- getApplication (),
172- getArguments (),
170+ SingleSignInActivity .createIntent (getApplication (), getArguments (),
173171 new User .Builder (provider , id ).build ()),
174172 RequestCodes .PROVIDER_FLOW )));
175173 }
@@ -189,8 +187,15 @@ private List<String> getCredentialAccountTypes() {
189187 public void onActivityResult (int requestCode , int resultCode , @ Nullable Intent data ) {
190188 switch (requestCode ) {
191189 case RequestCodes .CRED_HINT :
192- if (resultCode == Activity .RESULT_OK ) {
193- handleCredential ((Credential ) data .getParcelableExtra (Credential .EXTRA_KEY ));
190+ if (resultCode == Activity .RESULT_OK && data != null ) {
191+ try {
192+ SignInClient signInClient = Identity .getSignInClient (getApplication ());
193+ SignInCredential credential = signInClient .getSignInCredentialFromIntent (data );
194+ handleCredential (credential );
195+ } catch (ApiException e ) {
196+ // Optionally log the error
197+ startAuthMethodChoice ();
198+ }
194199 } else {
195200 startAuthMethodChoice ();
196201 }
@@ -199,7 +204,8 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d
199204 case RequestCodes .AUTH_PICKER_FLOW :
200205 case RequestCodes .PHONE_FLOW :
201206 case RequestCodes .PROVIDER_FLOW :
202- if (resultCode == RequestCodes .EMAIL_LINK_WRONG_DEVICE_FLOW || resultCode == RequestCodes .EMAIL_LINK_INVALID_LINK_FLOW ) {
207+ if (resultCode == RequestCodes .EMAIL_LINK_WRONG_DEVICE_FLOW ||
208+ resultCode == RequestCodes .EMAIL_LINK_INVALID_LINK_FLOW ) {
203209 startAuthMethodChoice ();
204210 return ;
205211 }
@@ -217,35 +223,39 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d
217223 }
218224 }
219225
220- private void handleCredential (final Credential credential ) {
226+ /**
227+ * Minimal change: Adapted to work with the new SignInCredential.
228+ */
229+ private void handleCredential (final SignInCredential credential ) {
221230 String id = credential .getId ();
222231 String password = credential .getPassword ();
223232 if (TextUtils .isEmpty (password )) {
224- String identity = credential .getAccountType ();
225- if (identity == null ) {
226- startAuthMethodChoice ();
233+ // Instead of checking accountType, check for a Google ID token.
234+ String googleIdToken = credential .getGoogleIdToken ();
235+ if (!TextUtils .isEmpty (googleIdToken )) {
236+ final IdpResponse response = new IdpResponse .Builder (
237+ new User .Builder (GoogleAuthProvider .PROVIDER_ID , id ).build ()).build ();
238+ setResult (Resource .forLoading ());
239+ getAuth ().signInWithCredential (GoogleAuthProvider .getCredential (googleIdToken , null ))
240+ .addOnSuccessListener (authResult -> handleSuccess (response , authResult ))
241+ .addOnFailureListener (e -> startAuthMethodChoice ());
227242 } else {
228- redirectSignIn (
229- ProviderUtils .accountTypeToProviderId (credential .getAccountType ()), id );
243+ startAuthMethodChoice ();
230244 }
231245 } else {
232246 final IdpResponse response = new IdpResponse .Builder (
233247 new User .Builder (EmailAuthProvider .PROVIDER_ID , id ).build ()).build ();
234-
235248 setResult (Resource .forLoading ());
236249 getAuth ().signInWithEmailAndPassword (id , password )
237- .addOnSuccessListener (result -> handleSuccess (response , result ))
250+ .addOnSuccessListener (authResult -> handleSuccess (response , authResult ))
238251 .addOnFailureListener (e -> {
239- if (e instanceof FirebaseAuthInvalidUserException
240- || e instanceof FirebaseAuthInvalidCredentialsException ) {
241- // In this case the credential saved in SmartLock was not
242- // a valid credential, we should delete it from SmartLock
243- // before continuing.
244- GoogleApiUtils .getCredentialsClient (getApplication ())
245- .delete (credential );
252+ if (e instanceof FirebaseAuthInvalidUserException ||
253+ e instanceof FirebaseAuthInvalidCredentialsException ) {
254+ // Minimal change: sign out using the new API (delete isn’t available).
255+ Identity .getSignInClient (getApplication ()).signOut ();
246256 }
247257 startAuthMethodChoice ();
248258 });
249259 }
250260 }
251- }
261+ }
0 commit comments