Skip to content

Commit a72885b

Browse files
authored
Allow most auth flows without Play services (#1865)
1 parent f59e133 commit a72885b

File tree

5 files changed

+67
-7
lines changed

5 files changed

+67
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Allow most auth flows on devices without Google Play services (#1858)

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

Lines changed: 31 additions & 5 deletions
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
/**

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

Lines changed: 8 additions & 2 deletions
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

Lines changed: 19 additions & 0 deletions
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/util/GoogleApiUtils.java

Lines changed: 8 additions & 0 deletions
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()

0 commit comments

Comments
 (0)