Skip to content

Commit 7f2d6a5

Browse files
authored
Version 7.1.0
Version 7.1.0
2 parents aef1d2f + 94e1005 commit 7f2d6a5

File tree

14 files changed

+227
-26
lines changed

14 files changed

+227
-26
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ libraries.
4848
```groovy
4949
dependencies {
5050
// FirebaseUI for Firebase Realtime Database
51-
implementation 'com.firebaseui:firebase-ui-database:7.0.0'
51+
implementation 'com.firebaseui:firebase-ui-database:7.1.0'
5252
5353
// FirebaseUI for Cloud Firestore
54-
implementation 'com.firebaseui:firebase-ui-firestore:7.0.0'
54+
implementation 'com.firebaseui:firebase-ui-firestore:7.1.0'
5555
5656
// FirebaseUI for Firebase Auth
57-
implementation 'com.firebaseui:firebase-ui-auth:7.0.0'
57+
implementation 'com.firebaseui:firebase-ui-auth:7.1.0'
5858
5959
// FirebaseUI for Cloud Storage
60-
implementation 'com.firebaseui:firebase-ui-storage:7.0.0'
60+
implementation 'com.firebaseui:firebase-ui-storage:7.1.0'
6161
}
6262
```
6363

@@ -244,4 +244,4 @@ accept your pull requests.
244244
1. Submit a pull request targeting the latest dev branch.
245245

246246
[gh-actions]: https://github.com/firebase/FirebaseUI-Android/actions
247-
[gh-actions-badge]: https://github.com/firebase/FirebaseUI-Android/workflows/Android%20CI/badge.svg
247+
[gh-actions-badge]: https://github.com/firebase/FirebaseUI-Android/workflows/Android%20CI/badge.svg

auth/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Gradle, add the dependency:
6666
```groovy
6767
dependencies {
6868
// ...
69-
implementation 'com.firebaseui:firebase-ui-auth:7.0.0'
69+
implementation 'com.firebaseui:firebase-ui-auth:7.1.0'
7070
7171
// Required only if Facebook login support is required
7272
// Find the latest Facebook SDK releases here: https://github.com/facebook/facebook-android-sdk/blob/master/CHANGELOG.md

auth/src/main/java/com/firebase/ui/auth/AuthUI.java

+42-5
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@
3939
import com.google.android.gms.auth.api.signin.GoogleSignIn;
4040
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
4141
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
42+
import com.google.android.gms.common.ConnectionResult;
43+
import com.google.android.gms.common.GoogleApiAvailability;
4244
import com.google.android.gms.common.api.ApiException;
4345
import com.google.android.gms.common.api.CommonStatusCodes;
46+
import com.google.android.gms.common.api.GoogleApi;
4447
import com.google.android.gms.common.api.Scope;
4548
import com.google.android.gms.tasks.Continuation;
4649
import com.google.android.gms.tasks.Task;
@@ -340,6 +343,12 @@ public Task<AuthResult> silentSignIn(@NonNull Context context,
340343
.getParcelable(ExtraConstants.GOOGLE_SIGN_IN_OPTIONS);
341344
}
342345

346+
// If Play services are not available we can't attempt to use the credentials client.
347+
if (!GoogleApiUtils.isPlayServicesAvailable(context)) {
348+
return Tasks.forException(
349+
new FirebaseUiException(ErrorCodes.PLAY_SERVICES_UPDATE_CANCELLED));
350+
}
351+
343352
return GoogleApiUtils.getCredentialsClient(context)
344353
.request(new CredentialRequest.Builder()
345354
// We can support both email and Google at the same time here because they
@@ -392,8 +401,16 @@ public Task<AuthResult> then(
392401
*/
393402
@NonNull
394403
public Task<Void> signOut(@NonNull Context context) {
395-
Task<Void> maybeDisableAutoSignIn = GoogleApiUtils.getCredentialsClient(context)
396-
.disableAutoSignIn()
404+
boolean playServicesAvailable = GoogleApiUtils.isPlayServicesAvailable(context);
405+
if (!playServicesAvailable) {
406+
Log.w(TAG, "Google Play services not available during signOut");
407+
}
408+
409+
Task<Void> maybeDisableAutoSignIn = playServicesAvailable
410+
? GoogleApiUtils.getCredentialsClient(context).disableAutoSignIn()
411+
: Tasks.forResult((Void) null);
412+
413+
maybeDisableAutoSignIn
397414
.continueWith(new Continuation<Void, Void>() {
398415
@Override
399416
public Void then(@NonNull Task<Void> task) {
@@ -434,7 +451,7 @@ public Void then(@NonNull Task<Void> task) {
434451
* @param context the calling {@link Context}.
435452
*/
436453
@NonNull
437-
public Task<Void> delete(@NonNull Context context) {
454+
public Task<Void> delete(@NonNull final Context context) {
438455
final FirebaseUser currentUser = mAuth.getCurrentUser();
439456
if (currentUser == null) {
440457
return Tasks.forException(new FirebaseAuthInvalidUserException(
@@ -443,14 +460,19 @@ public Task<Void> delete(@NonNull Context context) {
443460
}
444461

445462
final List<Credential> credentials = getCredentialsFromFirebaseUser(currentUser);
446-
final CredentialsClient client = GoogleApiUtils.getCredentialsClient(context);
447463

448464
// Ensure the order in which tasks are executed properly destructures the user.
449465
return signOutIdps(context).continueWithTask(new Continuation<Void, Task<Void>>() {
450466
@Override
451467
public Task<Void> then(@NonNull Task<Void> task) {
452468
task.getResult(); // Propagate exception if there was one
453469

470+
if (!GoogleApiUtils.isPlayServicesAvailable(context)) {
471+
Log.w(TAG, "Google Play services not available during delete");
472+
return Tasks.forResult((Void) null);
473+
}
474+
475+
final CredentialsClient client = GoogleApiUtils.getCredentialsClient(context);
454476
List<Task<?>> credentialTasks = new ArrayList<>();
455477
for (Credential credential : credentials) {
456478
credentialTasks.add(client.delete(credential));
@@ -516,7 +538,11 @@ private Task<Void> signOutIdps(@NonNull Context context) {
516538
if (ProviderAvailability.IS_FACEBOOK_AVAILABLE) {
517539
LoginManager.getInstance().logOut();
518540
}
519-
return GoogleSignIn.getClient(context, GoogleSignInOptions.DEFAULT_SIGN_IN).signOut();
541+
if (GoogleApiUtils.isPlayServicesAvailable(context)) {
542+
return GoogleSignIn.getClient(context, GoogleSignInOptions.DEFAULT_SIGN_IN).signOut();
543+
} else {
544+
return Tasks.forResult((Void) null);
545+
}
520546
}
521547

522548
/**
@@ -732,6 +758,17 @@ public EmailBuilder setForceSameDevice() {
732758
return this;
733759
}
734760

761+
/**
762+
* Sets a default sign in email, if the given email has been registered before, then
763+
* it will ask the user for password, if the given email it's not registered, then
764+
* it starts signing up the default email.
765+
*/
766+
@NonNull
767+
public EmailBuilder setDefaultEmail(String email) {
768+
getParams().putString(ExtraConstants.DEFAULT_EMAIL, email);
769+
return this;
770+
}
771+
735772
@Override
736773
public IdpConfig build() {
737774
if (super.mProviderId.equals(EMAIL_LINK_PROVIDER)) {

auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
import com.google.android.gms.common.GoogleApiAvailability;
1515
import com.google.android.gms.tasks.OnFailureListener;
1616
import com.google.android.gms.tasks.OnSuccessListener;
17+
import com.google.android.gms.tasks.Task;
18+
import com.google.android.gms.tasks.Tasks;
19+
import com.google.firebase.auth.GoogleAuthProvider;
1720

1821
import androidx.annotation.NonNull;
1922
import androidx.annotation.Nullable;
@@ -53,8 +56,11 @@ protected void onFailure(@NonNull Exception e) {
5356
}
5457
});
5558

56-
GoogleApiAvailability.getInstance()
57-
.makeGooglePlayServicesAvailable(this)
59+
Task<Void> checkPlayServicesTask = getFlowParams().isPlayServicesRequired()
60+
? GoogleApiAvailability.getInstance().makeGooglePlayServicesAvailable(this)
61+
: Tasks.forResult((Void) null);
62+
63+
checkPlayServicesTask
5864
.addOnSuccessListener(this, new OnSuccessListener<Void>() {
5965
@Override
6066
public void onSuccess(Void aVoid) {

auth/src/main/java/com/firebase/ui/auth/data/model/FlowParameters.java

+19
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
import android.text.TextUtils;
2020

2121
import com.firebase.ui.auth.AuthMethodPickerLayout;
22+
import com.firebase.ui.auth.AuthUI;
2223
import com.firebase.ui.auth.AuthUI.IdpConfig;
2324
import com.firebase.ui.auth.util.ExtraConstants;
2425
import com.firebase.ui.auth.util.Preconditions;
2526
import com.google.firebase.auth.ActionCodeSettings;
27+
import com.google.firebase.auth.GoogleAuthProvider;
2628

2729
import java.util.Collections;
2830
import java.util.List;
@@ -200,6 +202,23 @@ public boolean isAnonymousUpgradeEnabled() {
200202
return enableAnonymousUpgrade;
201203
}
202204

205+
public boolean isPlayServicesRequired() {
206+
// Play services only required for Google Sign In and the Credentials API
207+
return isProviderEnabled(GoogleAuthProvider.PROVIDER_ID)
208+
|| enableHints
209+
|| enableCredentials;
210+
}
211+
212+
public boolean isProviderEnabled(@AuthUI.SupportedProvider String provider) {
213+
for (AuthUI.IdpConfig idp : providers) {
214+
if (idp.getProviderId().equals(provider)) {
215+
return true;
216+
}
217+
}
218+
219+
return false;
220+
}
221+
203222
public boolean shouldShowProviderChoice() {
204223
return defaultProvider == null && (!isSingleProviderFlow() || alwaysShowProviderChoice);
205224
}

auth/src/main/java/com/firebase/ui/auth/ui/email/EmailActivity.java

+6
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
9898
responseForLinking, forceSameDevice);
9999
switchFragment(fragment, R.id.fragment_register_email, EmailLinkFragment.TAG);
100100
} else {
101+
AuthUI.IdpConfig emailConfig = ProviderUtils.getConfigFromIdps(
102+
getFlowParams().providers, EmailAuthProvider.PROVIDER_ID);
103+
104+
if (emailConfig != null) {
105+
email = emailConfig.getParams().getString(ExtraConstants.DEFAULT_EMAIL);;
106+
}
101107
// Start with check email
102108
CheckEmailFragment fragment = CheckEmailFragment.newInstance(email);
103109
switchFragment(fragment, R.id.fragment_register_email, CheckEmailFragment.TAG);

auth/src/main/java/com/firebase/ui/auth/util/ExtraConstants.java

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public final class ExtraConstants {
2727
public static final String CREDENTIAL = "extra_credential";
2828

2929
public static final String EMAIL = "extra_email";
30+
public static final String DEFAULT_EMAIL = "extra_default_email";
3031
public static final String ALLOW_NEW_EMAILS = "extra_allow_new_emails";
3132
public static final String REQUIRE_NAME = "extra_require_name";
3233
public static final String GOOGLE_SIGN_IN_OPTIONS = "extra_google_sign_in_options";

auth/src/main/java/com/firebase/ui/auth/util/GoogleApiUtils.java

+8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import com.google.android.gms.auth.api.credentials.Credentials;
77
import com.google.android.gms.auth.api.credentials.CredentialsClient;
88
import com.google.android.gms.auth.api.credentials.CredentialsOptions;
9+
import com.google.android.gms.common.ConnectionResult;
10+
import com.google.android.gms.common.GoogleApiAvailability;
911

1012
import androidx.annotation.NonNull;
1113
import androidx.annotation.RestrictTo;
@@ -16,6 +18,12 @@ private GoogleApiUtils() {
1618
throw new AssertionError("No instance for you!");
1719
}
1820

21+
public static boolean isPlayServicesAvailable(@NonNull Context context) {
22+
return GoogleApiAvailability
23+
.getInstance()
24+
.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
25+
}
26+
1927
@NonNull
2028
public static CredentialsClient getCredentialsClient(@NonNull Context context) {
2129
CredentialsOptions options = new CredentialsOptions.Builder()

auth/src/test/java/com/firebase/ui/auth/AuthUITest.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public void testPhoneBuilder_withValidDefaultNumberCode_expectSuccess() {
203203
}
204204

205205
@Test
206-
public void testPhoneBuilder_withBlacklistedCountryWithSameCountryCode_expectSucess() {
206+
public void testPhoneBuilder_withBlacklistedCountryWithSameCountryCode_expectSuccess() {
207207
new IdpConfig.PhoneBuilder()
208208
.setDefaultNumber("+1123456789")
209209
.setBlacklistedCountries(Arrays.asList("ca"))
@@ -333,6 +333,19 @@ public void testEmailBuilder_withAnonymousUpgradeAndNotForcingSameDevice_expectT
333333
(actionCodeSettings).build();
334334
}
335335

336+
@Test
337+
public void testEmailBuilder_withSetDefaultEmail_expectSuccess() {
338+
ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder().setUrl(URL).build();
339+
340+
IdpConfig config = new IdpConfig.EmailBuilder()
341+
.setDefaultEmail(TestConstants.EMAIL)
342+
.setActionCodeSettings(actionCodeSettings)
343+
.build();
344+
345+
assertThat(config.getParams().getString(ExtraConstants.DEFAULT_EMAIL))
346+
.isEqualTo(TestConstants.EMAIL);
347+
}
348+
336349
@Test(expected = IllegalStateException.class)
337350
public void testSignInIntentBuilder_anonymousUpgradeWithEmailLinkCrossDevice_expectThrows() {
338351
ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder().setUrl(URL).build();

auth/src/test/java/com/firebase/ui/auth/testhelpers/TestHelper.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,13 @@ public static FlowParameters getFlowParameters(Collection<String> providerIds) {
126126

127127
public static FlowParameters getFlowParameters(Collection<String> providerIds,
128128
boolean enableAnonymousUpgrade) {
129-
return getFlowParameters(providerIds, enableAnonymousUpgrade, null);
129+
return getFlowParameters(providerIds, enableAnonymousUpgrade, null, false);
130130
}
131131

132132
public static FlowParameters getFlowParameters(Collection<String> providerIds,
133133
boolean enableAnonymousUpgrade,
134-
AuthMethodPickerLayout customLayout) {
134+
AuthMethodPickerLayout customLayout,
135+
boolean hasDefaultEmail) {
135136
List<IdpConfig> idpConfigs = new ArrayList<>();
136137
for (String providerId : providerIds) {
137138
switch (providerId) {
@@ -153,7 +154,13 @@ public static FlowParameters getFlowParameters(Collection<String> providerIds,
153154
.setHandleCodeInApp(true).build()).build());
154155
break;
155156
case EmailAuthProvider.PROVIDER_ID:
156-
idpConfigs.add(new IdpConfig.EmailBuilder().build());
157+
if (hasDefaultEmail) { idpConfigs.add(new IdpConfig.EmailBuilder()
158+
.setDefaultEmail(TestConstants.EMAIL)
159+
.build());
160+
} else
161+
{
162+
idpConfigs.add(new IdpConfig.EmailBuilder().build());
163+
}
157164
break;
158165
case PhoneAuthProvider.PROVIDER_ID:
159166
idpConfigs.add(new IdpConfig.PhoneBuilder().build());

auth/src/test/java/com/firebase/ui/auth/ui/email/EmailActivityTest.java

+49-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.firebase.ui.auth.testhelpers.TestHelper;
2626
import com.firebase.ui.auth.util.ExtraConstants;
2727
import com.firebase.ui.auth.util.data.EmailLinkPersistenceManager;
28+
import com.google.android.material.textfield.TextInputEditText;
2829
import com.google.android.material.textfield.TextInputLayout;
2930
import com.google.firebase.auth.EmailAuthProvider;
3031
import com.google.firebase.auth.GoogleAuthProvider;
@@ -34,6 +35,8 @@
3435
import org.junit.runner.RunWith;
3536
import org.robolectric.Robolectric;
3637
import org.robolectric.RobolectricTestRunner;
38+
import org.robolectric.Shadows;
39+
import org.robolectric.shadows.ShadowActivity;
3740

3841
import java.util.Collections;
3942

@@ -73,7 +76,7 @@ public void testOnCreate_emailLinkLinkingFlow_expectSendEmailLinkFlowStarted() {
7376
EmailLinkPersistenceManager.getInstance().saveEmail(ApplicationProvider.getApplicationContext(),
7477
EMAIL, TestConstants.SESSION_ID, TestConstants.UID);
7578

76-
EmailActivity emailActivity = createActivity(AuthUI.EMAIL_LINK_PROVIDER, true);
79+
EmailActivity emailActivity = createActivity(AuthUI.EMAIL_LINK_PROVIDER, true, false);
7780

7881
EmailLinkFragment fragment = (EmailLinkFragment) emailActivity
7982
.getSupportFragmentManager().findFragmentByTag(EmailLinkFragment.TAG);
@@ -141,16 +144,59 @@ public void testSignUpButton_validatesFields() {
141144
passwordLayout.getError().toString());
142145
}
143146

147+
@Test
148+
public void testSetDefaultEmail_validField() {
149+
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);
150+
151+
CheckEmailFragment fragment = (CheckEmailFragment) emailActivity
152+
.getSupportFragmentManager().findFragmentByTag(CheckEmailFragment.TAG);
153+
assertThat(fragment).isNotNull();
154+
155+
TextInputEditText email = emailActivity.findViewById(R.id.email);
156+
assertEquals(TestConstants.EMAIL, email.getText().toString());
157+
158+
}
159+
160+
@Test
161+
public void testSetDefaultEmail_expectWelcomeBackPasswordPrompt() {
162+
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);
163+
164+
emailActivity.onExistingEmailUser(new User.Builder(EmailAuthProvider.PROVIDER_ID, TestConstants.EMAIL).build());
165+
166+
ShadowActivity.IntentForResult nextIntent =
167+
Shadows.shadowOf(emailActivity).getNextStartedActivityForResult();
168+
assertEquals(WelcomeBackPasswordPrompt.class.getName(),
169+
nextIntent.intent.getComponent().getClassName());
170+
171+
}
172+
173+
@Test
174+
public void testSetDefaultEmail_expectRegisterEmailFragment() {
175+
EmailActivity emailActivity = createActivity(EmailAuthProvider.PROVIDER_ID, false, true);
176+
177+
emailActivity.onNewUser(new User.Builder(EmailAuthProvider.PROVIDER_ID, TestConstants.EMAIL).build());
178+
179+
RegisterEmailFragment registerEmailFragment = (RegisterEmailFragment) emailActivity
180+
.getSupportFragmentManager().findFragmentByTag(RegisterEmailFragment.TAG);
181+
assertThat(registerEmailFragment).isNotNull();
182+
}
183+
144184

145185
private EmailActivity createActivity(String providerId) {
146-
return createActivity(providerId, false);
186+
return createActivity(providerId, false, false);
147187
}
148188

149-
private EmailActivity createActivity(String providerId, boolean emailLinkLinkingFlow) {
189+
private EmailActivity createActivity(String providerId, boolean emailLinkLinkingFlow, boolean hasDefaultEmail) {
150190
Intent startIntent = EmailActivity.createIntent(
151191
ApplicationProvider.getApplicationContext(),
152192
TestHelper.getFlowParameters(Collections.singletonList(providerId)));
153193

194+
if (hasDefaultEmail) {
195+
startIntent = EmailActivity.createIntent(
196+
ApplicationProvider.getApplicationContext(),
197+
TestHelper.getFlowParameters(Collections.singletonList(providerId), false, null, true));
198+
}
199+
154200
if (emailLinkLinkingFlow) {
155201
startIntent.putExtra(ExtraConstants.EMAIL, EMAIL);
156202
startIntent.putExtra(ExtraConstants.IDP_RESPONSE, buildGoogleIdpResponse());

0 commit comments

Comments
 (0)