From ff9848210d76cc805f44470b56aa159b31044a5c Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 12 Feb 2021 19:05:11 +0000 Subject: [PATCH 01/13] Begin development on v7.2.0 --- buildSrc/src/main/kotlin/Config.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index 60dd90f2b..2156953a6 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -1,5 +1,5 @@ object Config { - const val version = "7.1.1" + const val version = "7.2.0-SNAPSHOT" val submodules = listOf("auth", "common", "firestore", "database", "storage") private const val kotlinVersion = "1.3.72" From d87a3a952e05dd2810ebd57fded011ded9f88632 Mon Sep 17 00:00:00 2001 From: Laur <70561735+laurentiu-git@users.noreply.github.com> Date: Mon, 15 Feb 2021 12:45:20 +0200 Subject: [PATCH 02/13] Added Kosovo prefix (#1913) --- .../java/com/firebase/ui/auth/util/data/PhoneNumberUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/util/data/PhoneNumberUtils.java b/auth/src/main/java/com/firebase/ui/auth/util/data/PhoneNumberUtils.java index eb710253c..ce2945b77 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/data/PhoneNumberUtils.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/data/PhoneNumberUtils.java @@ -358,6 +358,7 @@ private static SparseArray> createCountryCodeToRegionCodeMap() { map.put(380, singletonList("UA")); map.put(381, singletonList("RS")); map.put(382, singletonList("ME")); + map.put(383, singletonList("XK")); map.put(385, singletonList("HR")); map.put(386, singletonList("SI")); map.put(387, singletonList("BA")); @@ -471,7 +472,6 @@ private static void initCountryCodeByIsoMap() { map.remove("TA"); map.put("HM", 672); map.put("GS", 500); - map.put("XK", 381); COUNTRY_TO_ISO_CODES = Collections.unmodifiableMap(map); } From c7f188d7ed75a4bb64ec3856d0b9bcfca606dd7c Mon Sep 17 00:00:00 2001 From: Jossi Wolf <10628007+jossiwolf@users.noreply.github.com> Date: Thu, 4 Mar 2021 17:34:53 +0100 Subject: [PATCH 03/13] AuthUI First-party support for Activity Result APIs (#1918) --- .../uidemo/auth/AnonymousUpgradeActivity.java | 69 ++++++++++--------- .../firebase/uidemo/auth/AuthUiActivity.java | 39 ++++++----- auth/build.gradle.kts | 4 ++ .../FirebaseAuthUIActivityResultContract.java | 34 +++++++++ .../FirebaseAuthUIAuthenticationResult.java | 57 +++++++++++++++ buildSrc/src/main/kotlin/Config.kt | 2 + 6 files changed, 152 insertions(+), 53 deletions(-) create mode 100644 auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUIActivityResultContract.java create mode 100644 auth/src/main/java/com/firebase/ui/auth/data/model/FirebaseAuthUIAuthenticationResult.java diff --git a/app/src/main/java/com/firebase/uidemo/auth/AnonymousUpgradeActivity.java b/app/src/main/java/com/firebase/uidemo/auth/AnonymousUpgradeActivity.java index d31b69845..ace5b7178 100644 --- a/app/src/main/java/com/firebase/uidemo/auth/AnonymousUpgradeActivity.java +++ b/app/src/main/java/com/firebase/uidemo/auth/AnonymousUpgradeActivity.java @@ -10,7 +10,9 @@ import com.firebase.ui.auth.AuthUI; import com.firebase.ui.auth.ErrorCodes; +import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract; import com.firebase.ui.auth.IdpResponse; +import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult; import com.firebase.uidemo.R; import com.firebase.uidemo.util.ConfigurationUtils; import com.google.android.gms.tasks.OnCompleteListener; @@ -22,6 +24,8 @@ import java.util.List; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; @@ -29,12 +33,11 @@ import butterknife.ButterKnife; import butterknife.OnClick; -public class AnonymousUpgradeActivity extends AppCompatActivity { +public class AnonymousUpgradeActivity extends AppCompatActivity + implements ActivityResultCallback { private static final String TAG = "AccountLink"; - private static final int RC_SIGN_IN = 123; - @BindView(R.id.status_text) TextView mStatus; @@ -52,6 +55,9 @@ public class AnonymousUpgradeActivity extends AppCompatActivity { private AuthCredential mPendingCredential; + private final ActivityResultLauncher signIn = + registerForActivityResult(new FirebaseAuthUIActivityResultContract(), this); + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -64,8 +70,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { // Occurs after catching an email link IdpResponse response = IdpResponse.fromResultIntent(getIntent()); if (response != null) { - handleSignInResult(RC_SIGN_IN, ErrorCodes.ANONYMOUS_UPGRADE_MERGE_CONFLICT, - getIntent()); + handleSignInResult(ErrorCodes.ANONYMOUS_UPGRADE_MERGE_CONFLICT, response); } } @@ -90,12 +95,12 @@ public void onComplete(@NonNull Task task) { @OnClick(R.id.begin_flow) public void startAuthUI() { List providers = ConfigurationUtils.getConfiguredProviders(this); - Intent intent = AuthUI.getInstance().createSignInIntentBuilder() + Intent signInIntent = AuthUI.getInstance().createSignInIntentBuilder() .setLogo(R.drawable.firebase_auth_120dp) .setAvailableProviders(providers) .enableAnonymousUsersAutoUpgrade() .build(); - startActivityForResult(intent, RC_SIGN_IN); + signIn.launch(signInIntent); } @OnClick(R.id.resolve_merge) @@ -137,34 +142,25 @@ public void onComplete(@NonNull Task task) { }); } - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - handleSignInResult(requestCode, resultCode, data); - } - - private void handleSignInResult(int requestCode, int resultCode, Intent data) { - if (requestCode == RC_SIGN_IN) { - IdpResponse response = IdpResponse.fromResultIntent(data); - if (response == null) { - // User pressed back button - return; - } - if (resultCode == RESULT_OK) { - setStatus("Signed in as " + getUserIdentifier(FirebaseAuth.getInstance() - .getCurrentUser())); - } else if (response.getError().getErrorCode() == ErrorCodes - .ANONYMOUS_UPGRADE_MERGE_CONFLICT) { - setStatus("Merge conflict: user already exists."); - mResolveMergeButton.setEnabled(true); - mPendingCredential = response.getCredentialForLinking(); - } else { - Toast.makeText(this, "Auth error, see logs", Toast.LENGTH_SHORT).show(); - Log.w(TAG, "Error: " + response.getError().getMessage(), response.getError()); - } - - updateUI(); + private void handleSignInResult(int resultCode, @Nullable IdpResponse response) { + if (response == null) { + // User pressed back button + return; + } + if (resultCode == RESULT_OK) { + setStatus("Signed in as " + getUserIdentifier(FirebaseAuth.getInstance() + .getCurrentUser())); + } else if (response.getError().getErrorCode() == ErrorCodes + .ANONYMOUS_UPGRADE_MERGE_CONFLICT) { + setStatus("Merge conflict: user already exists."); + mResolveMergeButton.setEnabled(true); + mPendingCredential = response.getCredentialForLinking(); + } else { + Toast.makeText(this, "Auth error, see logs", Toast.LENGTH_SHORT).show(); + Log.w(TAG, "Error: " + response.getError().getMessage(), response.getError()); } + + updateUI(); } private void updateUI() { @@ -212,4 +208,9 @@ private String getUserIdentifier(FirebaseUser user) { return "unknown"; } } + + @Override + public void onActivityResult(@NonNull FirebaseAuthUIAuthenticationResult result) { + handleSignInResult(result.getResultCode(), result.getIdpResponse()); + } } diff --git a/app/src/main/java/com/firebase/uidemo/auth/AuthUiActivity.java b/app/src/main/java/com/firebase/uidemo/auth/AuthUiActivity.java index adab4512f..539fa0e63 100644 --- a/app/src/main/java/com/firebase/uidemo/auth/AuthUiActivity.java +++ b/app/src/main/java/com/firebase/uidemo/auth/AuthUiActivity.java @@ -31,6 +31,8 @@ import com.firebase.ui.auth.AuthUI.IdpConfig; import com.firebase.ui.auth.ErrorCodes; import com.firebase.ui.auth.IdpResponse; +import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract; +import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult; import com.firebase.ui.auth.util.ExtraConstants; import com.firebase.uidemo.R; import com.firebase.uidemo.util.ConfigurationUtils; @@ -45,6 +47,8 @@ import java.util.ArrayList; import java.util.List; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -56,7 +60,8 @@ import butterknife.ButterKnife; import butterknife.OnClick; -public class AuthUiActivity extends AppCompatActivity { +public class AuthUiActivity extends AppCompatActivity + implements ActivityResultCallback { private static final String TAG = "AuthUiActivity"; private static final String GOOGLE_TOS_URL = "https://www.google.com/policies/terms/"; @@ -66,8 +71,6 @@ public class AuthUiActivity extends AppCompatActivity { private static final String FIREBASE_PRIVACY_POLICY_URL = "https://firebase.google" + ".com/terms/analytics/#7_privacy"; - private static final int RC_SIGN_IN = 100; - @BindView(R.id.root) View mRootView; @BindView(R.id.google_provider) CheckBox mUseGoogleProvider; @@ -111,6 +114,9 @@ public class AuthUiActivity extends AppCompatActivity { @BindView(R.id.require_name) CheckBox mRequireName; @BindView(R.id.use_auth_emulator) CheckBox mUseEmulator; + private final ActivityResultLauncher signIn = + registerForActivityResult(new FirebaseAuthUIActivityResultContract(), this); + @NonNull public static Intent createIntent(@NonNull Context context) { return new Intent(context, AuthUiActivity.class); @@ -237,11 +243,11 @@ public void flipEmailLinkProviderCheckbox(boolean passwordProviderIsChecked) { @OnClick(R.id.sign_in) public void signIn() { - startActivityForResult(buildSignInIntent(/*link=*/null), RC_SIGN_IN); + signIn.launch(getSignInIntent(/*link=*/null)); } public void signInWithEmailLink(@Nullable String link) { - startActivityForResult(buildSignInIntent(link), RC_SIGN_IN); + signIn.launch(getSignInIntent(link)); } @NonNull @@ -254,8 +260,7 @@ public AuthUI getAuthUI() { return authUI; } - @NonNull - public Intent buildSignInIntent(@Nullable String link) { + private Intent getSignInIntent(@Nullable String link) { AuthUI.SignInIntentBuilder builder = getAuthUI().createSignInIntentBuilder() .setTheme(getSelectedTheme()) .setLogo(getSelectedLogo()) @@ -290,7 +295,6 @@ public Intent buildSignInIntent(@Nullable String link) { if (auth.getCurrentUser() != null && auth.getCurrentUser().isAnonymous()) { builder.enableAnonymousUsersAutoUpgrade(); } - return builder.build(); } @@ -309,14 +313,6 @@ public void onComplete(@NonNull Task task) { }); } - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == RC_SIGN_IN) { - handleSignInResponse(resultCode, data); - } - } - @Override protected void onResume() { super.onResume(); @@ -327,9 +323,7 @@ protected void onResume() { } } - private void handleSignInResponse(int resultCode, @Nullable Intent data) { - IdpResponse response = IdpResponse.fromResultIntent(data); - + private void handleSignInResponse(int resultCode, @Nullable IdpResponse response) { // Successfully signed in if (resultCode == RESULT_OK) { startSignedInActivity(response); @@ -529,4 +523,11 @@ private List getFacebookPermissions() { private void showSnackbar(@StringRes int errorMessageRes) { Snackbar.make(mRootView, errorMessageRes, Snackbar.LENGTH_LONG).show(); } + + @Override + public void onActivityResult(@NonNull FirebaseAuthUIAuthenticationResult result) { + // Successfully signed in + IdpResponse response = result.getIdpResponse(); + handleSignInResponse(result.getResultCode(), response); + } } diff --git a/auth/build.gradle.kts b/auth/build.gradle.kts index 53931f7e3..7675ee9da 100644 --- a/auth/build.gradle.kts +++ b/auth/build.gradle.kts @@ -26,6 +26,10 @@ android { } dependencies { + implementation(Config.Libs.Androidx.activity) + // The new activity result APIs force us to include Fragment 1.3.0 + // See https://issuetracker.google.com/issues/152554847 + implementation(Config.Libs.Androidx.fragment) implementation(Config.Libs.Androidx.design) implementation(Config.Libs.Androidx.customTabs) implementation(Config.Libs.Androidx.constraint) diff --git a/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUIActivityResultContract.java b/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUIActivityResultContract.java new file mode 100644 index 000000000..1edbd3a8e --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUIActivityResultContract.java @@ -0,0 +1,34 @@ +package com.firebase.ui.auth; + +import android.content.Context; +import android.content.Intent; + +import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult; + +import androidx.activity.result.contract.ActivityResultContract; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * A {@link ActivityResultContract} describing that the caller can launch authentication flow with a + * {@link Intent} and is guaranteed to receive a {@link FirebaseAuthUIAuthenticationResult} as + * result. The given input intent must be created using a + * {@link com.firebase.ui.auth.AuthUI.SignInIntentBuilder} in order to guarantee a successful + * launch of the authentication flow. + */ +public class FirebaseAuthUIActivityResultContract extends + ActivityResultContract { + + @NonNull + @Override + public Intent createIntent(@NonNull Context context, Intent input) { + return input; + } + + @Override + @NonNull + public FirebaseAuthUIAuthenticationResult parseResult(int resultCode, @Nullable Intent intent) { + return new FirebaseAuthUIAuthenticationResult(resultCode, IdpResponse.fromResultIntent(intent)); + } + +} diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/FirebaseAuthUIAuthenticationResult.java b/auth/src/main/java/com/firebase/ui/auth/data/model/FirebaseAuthUIAuthenticationResult.java new file mode 100644 index 000000000..eea7deabc --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/FirebaseAuthUIAuthenticationResult.java @@ -0,0 +1,57 @@ +package com.firebase.ui.auth.data.model; + +import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract; +import com.firebase.ui.auth.IdpResponse; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * Result of launching a {@link FirebaseAuthUIActivityResultContract} + */ +public class FirebaseAuthUIAuthenticationResult { + + @Nullable + private final IdpResponse idpResponse; + @NonNull + private final Integer resultCode; + + public FirebaseAuthUIAuthenticationResult(@NonNull Integer resultCode, @Nullable IdpResponse idpResponse) { + this.idpResponse = idpResponse; + this.resultCode = resultCode; + } + + /** + * The contained {@link IdpResponse} returned from the Firebase library + */ + @Nullable + public IdpResponse getIdpResponse() { + return idpResponse; + } + + /** + * The result code of the received activity result + * + * @see android.app.Activity.RESULT_CANCELED + * @see android.app.Activity.RESULT_OK + */ + @NonNull + public Integer getResultCode() { + return resultCode; + } + + @Override + public int hashCode() { + int result = idpResponse == null ? 0 : idpResponse.hashCode(); + result = 31 * result + resultCode.hashCode(); + return result; + } + + @Override + public String toString() { + return "FirebaseAuthUIAuthenticationResult{" + + "idpResponse=" + idpResponse + + ", resultCode='" + resultCode + + '}'; + } +} diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index 2156953a6..108519e21 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -26,9 +26,11 @@ object Config { object Androidx { const val annotations = "androidx.annotation:annotation:1.1.0" + const val activity = "androidx.activity:activity:1.2.0" const val customTabs = "androidx.browser:browser:1.0.0" const val cardView = "androidx.cardview:cardview:1.0.0" const val constraint = "androidx.constraintlayout:constraintlayout:2.0.4" + const val fragment = "androidx.fragment:fragment:1.3.0" const val lifecycleCompiler = "androidx.lifecycle:lifecycle-compiler:2.2.0" const val lifecycleExtensions = "androidx.lifecycle:lifecycle-extensions:2.2.0" const val lifecycleRuntime = "androidx.lifecycle:lifecycle-runtime:2.2.0" From 73bb73cbb68c6174ba815c167c378f3cb4aa1369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ros=C3=A1rio=20Pereira=20Fernandes?= Date: Fri, 11 Jun 2021 18:05:39 +0200 Subject: [PATCH 04/13] refactor: update Firebase BoM (26.5.0) and replace singleValueEventListener with Query.get() (#1912) --- .../GenericIdpSignInHandlerTest.java | 6 ++-- .../PhoneProviderResponseHandlerTest.java | 3 +- buildSrc/src/main/kotlin/Config.kt | 2 +- .../database/paging/FirebaseDataSource.java | 28 +++++++++---------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/auth/src/test/java/com/firebase/ui/auth/viewmodel/GenericIdpSignInHandlerTest.java b/auth/src/test/java/com/firebase/ui/auth/viewmodel/GenericIdpSignInHandlerTest.java index cd48c8921..94dcdd44b 100644 --- a/auth/src/test/java/com/firebase/ui/auth/viewmodel/GenericIdpSignInHandlerTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/viewmodel/GenericIdpSignInHandlerTest.java @@ -152,7 +152,7 @@ public void testStartSignIn_normalSignInFlowWithRecoverableError_expectFailure() .build(); FirebaseAuthUserCollisionException collisionException = new FirebaseAuthUserCollisionException("foo", "bar"); - collisionException.zza(EMAIL).zza(credential); + collisionException.zza(EMAIL).zzb(credential); when(mMockAuth.startActivityForSignInWithProvider(any(Activity.class), any(OAuthProvider.class))) .thenReturn(AutoCompleteTask.forFailure(collisionException)); @@ -256,7 +256,7 @@ public void testStartSignIn_anonymousUpgradeFlowWithConflict_expectRecoverableEr .build(); FirebaseAuthUserCollisionException collisionException = new FirebaseAuthUserCollisionException("foo", "bar"); - collisionException.zza(EMAIL).zza(credential); + collisionException.zza(EMAIL).zzb(credential); when(mMockAuth.getCurrentUser().startActivityForLinkWithProvider( any(Activity.class), any(OAuthProvider.class))) .thenReturn(AutoCompleteTask.forFailure(collisionException)); @@ -300,7 +300,7 @@ public void testStartSignIn_anonymousUpgradeFlowWithConflict_expectRecoverableLi .build(); FirebaseAuthUserCollisionException collisionException = new FirebaseAuthUserCollisionException("foo", "bar"); - collisionException.zza(EMAIL).zza(credential); + collisionException.zza(EMAIL).zzb(credential); when(mMockAuth.getCurrentUser().startActivityForLinkWithProvider( any(Activity.class), any(OAuthProvider.class))) diff --git a/auth/src/test/java/com/firebase/ui/auth/viewmodel/PhoneProviderResponseHandlerTest.java b/auth/src/test/java/com/firebase/ui/auth/viewmodel/PhoneProviderResponseHandlerTest.java index 37a267024..693e273c0 100644 --- a/auth/src/test/java/com/firebase/ui/auth/viewmodel/PhoneProviderResponseHandlerTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/viewmodel/PhoneProviderResponseHandlerTest.java @@ -49,7 +49,7 @@ public class PhoneProviderResponseHandlerTest { @Mock FirebaseAuth mMockAuth; @Mock FirebaseUser mMockUser; - @Mock PhoneAuthCredential mCredential; + PhoneAuthCredential mCredential; @Mock Observer> mResponseObserver; private PhoneProviderResponseHandler mHandler; @@ -58,6 +58,7 @@ public class PhoneProviderResponseHandlerTest { public void setUp() { TestHelper.initialize(); MockitoAnnotations.initMocks(this); + mCredential = PhoneAuthCredential.zzb("sessionInfo", "SmsCode"); mHandler = new PhoneProviderResponseHandler((Application) ApplicationProvider.getApplicationContext()); FlowParameters testParams = TestHelper.getFlowParameters(Collections.singletonList( diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index 108519e21..ba73a9e53 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -44,7 +44,7 @@ object Config { } object Firebase { - const val bom = "com.google.firebase:firebase-bom:26.0.0" + const val bom = "com.google.firebase:firebase-bom:26.5.0" const val auth = "com.google.firebase:firebase-auth" const val database = "com.google.firebase:firebase-database" const val firestore = "com.google.firebase:firebase-firestore" diff --git a/database/src/main/java/com/firebase/ui/database/paging/FirebaseDataSource.java b/database/src/main/java/com/firebase/ui/database/paging/FirebaseDataSource.java index 45f686ce8..268f1acbe 100644 --- a/database/src/main/java/com/firebase/ui/database/paging/FirebaseDataSource.java +++ b/database/src/main/java/com/firebase/ui/database/paging/FirebaseDataSource.java @@ -3,10 +3,11 @@ import android.annotation.SuppressLint; import android.util.Log; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.Query; -import com.google.firebase.database.ValueEventListener; import java.util.ArrayList; import java.util.Iterator; @@ -69,9 +70,9 @@ public void loadInitial(@NonNull final LoadInitialParams params, mLoadingState.postValue(LoadingState.LOADING_INITIAL); Query mInitQuery = mQuery.limitToFirst(params.requestedLoadSize); - mInitQuery.addListenerForSingleValueEvent(new ValueEventListener() { + mInitQuery.get().addOnSuccessListener(new OnSuccessListener() { @Override - public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + public void onSuccess(DataSnapshot dataSnapshot) { if (dataSnapshot.exists()) { //Make List of DataSnapshot @@ -95,11 +96,11 @@ public void onDataChange(@NonNull DataSnapshot dataSnapshot) { setDatabaseNotFoundError(); } } - + }).addOnFailureListener(new OnFailureListener() { @Override - public void onCancelled(@NonNull DatabaseError databaseError) { + public void onFailure(@NonNull Exception e) { mRetryRunnable = getRetryLoadInitial(params, callback); - setError(databaseError); + setError(e); } }); } @@ -118,9 +119,9 @@ public void loadAfter(@NonNull final LoadParams params, //Load params.requestedLoadSize+1 because, first data item is getting ignored. Query mNewQuery = mQuery.startAt(null, params.key).limitToFirst(params.requestedLoadSize + 1); - mNewQuery.addListenerForSingleValueEvent(new ValueEventListener() { + mNewQuery.get().addOnSuccessListener(new OnSuccessListener() { @Override - public void onDataChange(@NonNull DataSnapshot dataSnapshot) { + public void onSuccess(DataSnapshot dataSnapshot) { if (dataSnapshot.exists()) { //Make List of DataSnapshot @@ -157,13 +158,12 @@ public void onDataChange(@NonNull DataSnapshot dataSnapshot) { mRetryRunnable = getRetryLoadAfter(params, callback); setDatabaseNotFoundError(); } - } - + }).addOnFailureListener(new OnFailureListener() { @Override - public void onCancelled(@NonNull DatabaseError databaseError) { + public void onFailure(@NonNull Exception e) { mRetryRunnable = getRetryLoadAfter(params, callback); - setError(databaseError); + setError(e); } }); } @@ -229,8 +229,8 @@ private void setDatabaseNotFoundError(){ mLoadingState.postValue(LoadingState.ERROR); } - private void setError(DatabaseError databaseError){ - mError.postValue(databaseError); + private void setError(Exception e){ + mError.postValue(DatabaseError.fromException(e)); mLoadingState.postValue(LoadingState.ERROR); } From 30b067b186411f8f69094c19b7ed80ac6b7e8b5e Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Mon, 14 Jun 2021 05:25:42 -0400 Subject: [PATCH 05/13] Increase SMS resend timeout to 60s (#1954) --- .../ui/auth/ui/phone/SubmitConfirmationCodeFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/phone/SubmitConfirmationCodeFragment.java b/auth/src/main/java/com/firebase/ui/auth/ui/phone/SubmitConfirmationCodeFragment.java index 1f6b5198c..572e9c30d 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/phone/SubmitConfirmationCodeFragment.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/phone/SubmitConfirmationCodeFragment.java @@ -54,7 +54,7 @@ public class SubmitConfirmationCodeFragment extends FragmentBase { public static final String TAG = "SubmitConfirmationCodeFragment"; private static final int VERIFICATION_CODE_LENGTH = 6; - private static final long RESEND_WAIT_MILLIS = 15000; + private static final long RESEND_WAIT_MILLIS = 60000; private static final long TICK_INTERVAL_MILLIS = 500; private static final String EXTRA_MILLIS_UNTIL_FINISHED = "millis_until_finished"; From e04979e91bd6e650f1a54d8005c72e29a749cf54 Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Mon, 14 Jun 2021 05:36:02 -0400 Subject: [PATCH 06/13] Allow setting default_web_client_id at runtime (#1953) --- .../src/main/java/com/firebase/ui/auth/AuthUI.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/AuthUI.java b/auth/src/main/java/com/firebase/ui/auth/AuthUI.java index e42d20dc3..6a909843e 100644 --- a/auth/src/main/java/com/firebase/ui/auth/AuthUI.java +++ b/auth/src/main/java/com/firebase/ui/auth/AuthUI.java @@ -1066,6 +1066,9 @@ private String getDefaultIso() { public static final class GoogleBuilder extends Builder { public GoogleBuilder() { super(GoogleAuthProvider.PROVIDER_ID); + } + + private void validateWebClientId() { Preconditions.checkConfigured(getApplicationContext(), "Check your google-services plugin configuration, the" + " default_web_client_id string wasn't populated.", @@ -1103,8 +1106,14 @@ public GoogleBuilder setSignInOptions(@NonNull GoogleSignInOptions options) { ExtraConstants.GOOGLE_SIGN_IN_OPTIONS); GoogleSignInOptions.Builder builder = new GoogleSignInOptions.Builder(options); - builder.requestEmail().requestIdToken(getApplicationContext() - .getString(R.string.default_web_client_id)); + + String clientId = options.getServerClientId(); + if (clientId == null) { + validateWebClientId(); + clientId = getApplicationContext().getString(R.string.default_web_client_id); + } + + builder.requestEmail().requestIdToken(clientId); getParams().putParcelable( ExtraConstants.GOOGLE_SIGN_IN_OPTIONS, builder.build()); @@ -1115,6 +1124,7 @@ public GoogleBuilder setSignInOptions(@NonNull GoogleSignInOptions options) { @Override public IdpConfig build() { if (!getParams().containsKey(ExtraConstants.GOOGLE_SIGN_IN_OPTIONS)) { + validateWebClientId(); setScopes(Collections.emptyList()); } From 9f607748d6feaaf2402f7144b8017f3460cf71cb Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Mon, 14 Jun 2021 09:08:20 -0400 Subject: [PATCH 07/13] Fix email-link with custom layouts (#1955) --- .../com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java index 28a554ee4..1de2a3338 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java @@ -242,7 +242,8 @@ private void populateIdpListCustomLayout(List providerConfigs) { } boolean hasProvider = false; for (IdpConfig idpConfig : providerConfigs) { - if (providerBtnId.equals(idpConfig.getProviderId())) { + String providerId = providerOrEmailLinkProvider(idpConfig.getProviderId()); + if (providerBtnId.equals(providerId)) { hasProvider = true; break; } From d6a2d81c85c6ac296c37d672f000a3f06757480b Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Mon, 14 Jun 2021 09:21:44 -0400 Subject: [PATCH 08/13] Fix error message on phone auth (#1956) --- .../main/java/com/firebase/ui/auth/ui/phone/PhoneActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/phone/PhoneActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/phone/PhoneActivity.java index d4caa46fa..dacac70de 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/phone/PhoneActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/phone/PhoneActivity.java @@ -169,7 +169,7 @@ private void handleError(@Nullable Exception e) { } errorView.setError(getErrorMessage(error)); } else if (e != null) { - errorView.setError(e.getLocalizedMessage()); + errorView.setError(getErrorMessage(FirebaseAuthError.ERROR_UNKNOWN)); } else { errorView.setError(null); } From bf38de7703eb70a600d3ae274a87bdddd55e753e Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Mon, 14 Jun 2021 09:31:38 -0400 Subject: [PATCH 09/13] Country code always to left of phone (#1957) --- auth/src/main/res/layout/fui_phone_layout.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/auth/src/main/res/layout/fui_phone_layout.xml b/auth/src/main/res/layout/fui_phone_layout.xml index aa86cf726..68fc06fd6 100644 --- a/auth/src/main/res/layout/fui_phone_layout.xml +++ b/auth/src/main/res/layout/fui_phone_layout.xml @@ -24,7 +24,7 @@ Date: Mon, 14 Jun 2021 09:47:12 -0400 Subject: [PATCH 10/13] Allow setSignInOptions without email scope (#1958) --- .../main/java/com/firebase/ui/auth/AuthUI.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/AuthUI.java b/auth/src/main/java/com/firebase/ui/auth/AuthUI.java index 6a909843e..c9c6673c8 100644 --- a/auth/src/main/java/com/firebase/ui/auth/AuthUI.java +++ b/auth/src/main/java/com/firebase/ui/auth/AuthUI.java @@ -1113,7 +1113,22 @@ public GoogleBuilder setSignInOptions(@NonNull GoogleSignInOptions options) { clientId = getApplicationContext().getString(R.string.default_web_client_id); } - builder.requestEmail().requestIdToken(clientId); + // Warn the user that they are _probably_ doing the wrong thing if they + // have not called requestEmail (see issue #1899 and #1621) + boolean hasEmailScope = false; + for (Scope s : options.getScopes()) { + if ("email".equals(s.getScopeUri())) { + hasEmailScope = true; + break; + } + } + if (!hasEmailScope) { + Log.w(TAG, "The GoogleSignInOptions passed to setSignInOptions does not " + + "request the 'email' scope. In most cases this is a mistake! " + + "Call requestEmail() on the GoogleSignInOptions object."); + } + + builder.requestIdToken(clientId); getParams().putParcelable( ExtraConstants.GOOGLE_SIGN_IN_OPTIONS, builder.build()); From 9b3b3a3b6b2da8d85bf7cba7133ce95defede4ae Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Mon, 14 Jun 2021 10:18:50 -0400 Subject: [PATCH 11/13] Fix bad merge (#1960) --- .../uidemo/auth/AnonymousUpgradeActivity.java | 45 +++++++------------ 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/firebase/uidemo/auth/AnonymousUpgradeActivity.java b/app/src/main/java/com/firebase/uidemo/auth/AnonymousUpgradeActivity.java index 66aedde9f..41a0b308b 100644 --- a/app/src/main/java/com/firebase/uidemo/auth/AnonymousUpgradeActivity.java +++ b/app/src/main/java/com/firebase/uidemo/auth/AnonymousUpgradeActivity.java @@ -35,8 +35,6 @@ public class AnonymousUpgradeActivity extends AppCompatActivity private static final String TAG = "AccountLink"; - private static final int RC_SIGN_IN = 123; - private ActivityAnonymousUpgradeBinding mBinding; private AuthCredential mPendingCredential; @@ -152,33 +150,22 @@ public void onComplete(@NonNull Task task) { }); } - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - handleSignInResult(requestCode, resultCode, data); - } - - private void handleSignInResult(int requestCode, int resultCode, Intent data) { - if (requestCode == RC_SIGN_IN) { - IdpResponse response = IdpResponse.fromResultIntent(data); - if (response == null) { - // User pressed back button - return; - } - if (resultCode == RESULT_OK) { - setStatus("Signed in as " + getUserIdentifier(FirebaseAuth.getInstance() - .getCurrentUser())); - } else if (response.getError().getErrorCode() == ErrorCodes - .ANONYMOUS_UPGRADE_MERGE_CONFLICT) { - setStatus("Merge conflict: user already exists."); - mBinding.resolveMerge.setEnabled(true); - mPendingCredential = response.getCredentialForLinking(); - } else { - Toast.makeText(this, "Auth error, see logs", Toast.LENGTH_SHORT).show(); - Log.w(TAG, "Error: " + response.getError().getMessage(), response.getError()); - } - - updateUI(); + private void handleSignInResult(int resultCode, @Nullable IdpResponse response) { + if (response == null) { + // User pressed back button + return; + } + if (resultCode == RESULT_OK) { + setStatus("Signed in as " + getUserIdentifier(FirebaseAuth.getInstance() + .getCurrentUser())); + } else if (response.getError().getErrorCode() == ErrorCodes + .ANONYMOUS_UPGRADE_MERGE_CONFLICT) { + setStatus("Merge conflict: user already exists."); + mBinding.resolveMerge.setEnabled(true); + mPendingCredential = response.getCredentialForLinking(); + } else { + Toast.makeText(this, "Auth error, see logs", Toast.LENGTH_SHORT).show(); + Log.w(TAG, "Error: " + response.getError().getMessage(), response.getError()); } updateUI(); From f7b147d14b7e7eeaf791a3ebd98731288c0c9b41 Mon Sep 17 00:00:00 2001 From: Sam Stern Date: Mon, 14 Jun 2021 10:27:19 -0400 Subject: [PATCH 12/13] Update dependencies (#1959) --- buildSrc/src/main/kotlin/Config.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index 76097624d..580b27d2f 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -13,7 +13,7 @@ object Config { object Plugins { const val android = "com.android.tools.build:gradle:4.0.0" const val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" - const val google = "com.google.gms:google-services:4.3.3" + const val google = "com.google.gms:google-services:4.3.8" const val mavenPublish = "com.vanniktech:gradle-maven-publish-plugin:0.14.2" const val buildInfo = "org.jfrog.buildinfo:build-info-extractor-gradle:4.15.2" @@ -44,7 +44,7 @@ object Config { } object Firebase { - const val bom = "com.google.firebase:firebase-bom:26.5.0" + const val bom = "com.google.firebase:firebase-bom:26.8.0" const val auth = "com.google.firebase:firebase-auth" const val database = "com.google.firebase:firebase-database" const val firestore = "com.google.firebase:firebase-firestore" From 490394735a27aeffd6f67b1b7f52088c1d028f48 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 14 Jun 2021 15:31:39 +0100 Subject: [PATCH 13/13] Version 7.2.0 --- README.md | 8 ++++---- auth/README.md | 2 +- buildSrc/src/main/kotlin/Config.kt | 2 +- gradle.properties | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 247c66f8c..1b50358d1 100644 --- a/README.md +++ b/README.md @@ -48,16 +48,16 @@ libraries. ```groovy dependencies { // FirebaseUI for Firebase Realtime Database - implementation 'com.firebaseui:firebase-ui-database:7.1.1' + implementation 'com.firebaseui:firebase-ui-database:7.2.0' // FirebaseUI for Cloud Firestore - implementation 'com.firebaseui:firebase-ui-firestore:7.1.1' + implementation 'com.firebaseui:firebase-ui-firestore:7.2.0' // FirebaseUI for Firebase Auth - implementation 'com.firebaseui:firebase-ui-auth:7.1.1' + implementation 'com.firebaseui:firebase-ui-auth:7.2.0' // FirebaseUI for Cloud Storage - implementation 'com.firebaseui:firebase-ui-storage:7.1.1' + implementation 'com.firebaseui:firebase-ui-storage:7.2.0' } ``` diff --git a/auth/README.md b/auth/README.md index 61763b2d5..923923212 100644 --- a/auth/README.md +++ b/auth/README.md @@ -66,7 +66,7 @@ Gradle, add the dependency: ```groovy dependencies { // ... - implementation 'com.firebaseui:firebase-ui-auth:7.1.1' + implementation 'com.firebaseui:firebase-ui-auth:7.2.0' // Required only if Facebook login support is required // Find the latest Facebook SDK releases here: https://github.com/facebook/facebook-android-sdk/blob/master/CHANGELOG.md diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index 580b27d2f..96d64a200 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -1,5 +1,5 @@ object Config { - const val version = "7.2.0-SNAPSHOT" + const val version = "7.2.0" val submodules = listOf("auth", "common", "firestore", "database", "storage") private const val kotlinVersion = "1.3.72" diff --git a/gradle.properties b/gradle.properties index 8b876bf09..cd7813079 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ android.useAndroidX=true android.enableJetifier=true GROUP=com.firebaseui -VERSION_NAME=7.1.1 +VERSION_NAME=7.2.0 POM_PACKAGING=aar POM_DESCRIPTION=FirebaseUI for Android