idpConfigs) {
for (IdpConfig idpConfig : idpConfigs) {
if (configuredProviders.contains(idpConfig.getProviderId())) {
throw new IllegalArgumentException("Each provider can only be set once. "
- + idpConfig.getProviderId() + " was set twice.");
+ + idpConfig.getProviderId()
+ + " was set twice.");
}
configuredProviders.add(idpConfig.getProviderId());
mProviders.add(idpConfig);
@@ -602,7 +613,7 @@ public SignInIntentBuilder setProviders(@NonNull String... providers) {
/**
* Enables or disables the use of Smart Lock for Passwords in the sign in flow.
- *
+ *
* SmartLock is enabled by default
*/
public SignInIntentBuilder setIsSmartLockEnabled(boolean enabled) {
@@ -610,24 +621,6 @@ public SignInIntentBuilder setIsSmartLockEnabled(boolean enabled) {
return this;
}
- public Intent build() {
- Context context = mApp.getApplicationContext();
- return build(context);
- }
-
- @VisibleForTesting
- public Intent build(Context context) {
- return ChooseAccountActivity.createIntent(
- context,
- new FlowParameters(
- mApp.getName(),
- new ArrayList<>(mProviders),
- mTheme,
- mLogo,
- mTosUrl,
- mIsSmartLockEnabled));
- }
-
private boolean isIdpAlreadyConfigured(@NonNull String providerId) {
for (IdpConfig config : mProviders) {
if (config.getProviderId().equals(providerId)) {
@@ -636,5 +629,18 @@ private boolean isIdpAlreadyConfigured(@NonNull String providerId) {
}
return false;
}
+
+ public void build(@NonNull FragmentActivity activity) {
+ SignInDelegate.delegateSignIn(activity, getFlowParams());
+ }
+
+ public FlowParameters getFlowParams() {
+ return new FlowParameters(mApp.getName(),
+ new ArrayList<>(mProviders),
+ mTheme,
+ mLogo,
+ mTosUrl,
+ mIsSmartLockEnabled);
+ }
}
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/IdpResponse.java b/auth/src/main/java/com/firebase/ui/auth/IdpResponse.java
index 89d98e7e0..b9383de17 100644
--- a/auth/src/main/java/com/firebase/ui/auth/IdpResponse.java
+++ b/auth/src/main/java/com/firebase/ui/auth/IdpResponse.java
@@ -18,7 +18,15 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
+
+import com.firebase.ui.auth.provider.FacebookProvider;
+import com.firebase.ui.auth.provider.GoogleProvider;
+import com.firebase.ui.auth.provider.TwitterProvider;
import com.firebase.ui.auth.ui.ExtraConstants;
+import com.google.firebase.auth.AuthCredential;
+import com.google.firebase.auth.FacebookAuthProvider;
+import com.google.firebase.auth.GoogleAuthProvider;
+import com.google.firebase.auth.TwitterAuthProvider;
/**
* A container that encapsulates the result of authenticating with an Identity Provider.
@@ -120,4 +128,18 @@ public void writeToParcel(Parcel dest, int flags) {
public static IdpResponse fromResultIntent(Intent resultIntent) {
return resultIntent.getParcelableExtra(ExtraConstants.EXTRA_IDP_RESPONSE);
}
+
+ public static AuthCredential createCredential(IdpResponse idpSignInResponse) {
+ if (idpSignInResponse.getProviderType().equalsIgnoreCase(FacebookAuthProvider.PROVIDER_ID)) {
+ return FacebookProvider.createAuthCredential(idpSignInResponse);
+ } else if (idpSignInResponse.getProviderType().equalsIgnoreCase(GoogleAuthProvider
+ .PROVIDER_ID)) {
+ return GoogleProvider.createAuthCredential(idpSignInResponse);
+ } else if (idpSignInResponse
+ .getProviderType()
+ .equalsIgnoreCase(TwitterAuthProvider.PROVIDER_ID)) {
+ return TwitterProvider.createAuthCredential(idpSignInResponse);
+ }
+ return null;
+ }
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/provider/FacebookProvider.java b/auth/src/main/java/com/firebase/ui/auth/provider/FacebookProvider.java
index 7fc91c0f0..b18ee0c4d 100644
--- a/auth/src/main/java/com/firebase/ui/auth/provider/FacebookProvider.java
+++ b/auth/src/main/java/com/firebase/ui/auth/provider/FacebookProvider.java
@@ -19,6 +19,7 @@
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
+
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
@@ -34,11 +35,13 @@
import com.firebase.ui.auth.R;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.FacebookAuthProvider;
-import java.util.ArrayList;
-import java.util.List;
+
import org.json.JSONException;
import org.json.JSONObject;
+import java.util.ArrayList;
+import java.util.List;
+
public class FacebookProvider implements IdpProvider, FacebookCallback {
protected static final String ERROR = "err";
protected static final String ERROR_MSG = "err_msg";
diff --git a/auth/src/main/java/com/firebase/ui/auth/provider/GoogleProvider.java b/auth/src/main/java/com/firebase/ui/auth/provider/GoogleProvider.java
index cb23873ab..6ec7a173b 100644
--- a/auth/src/main/java/com/firebase/ui/auth/provider/GoogleProvider.java
+++ b/auth/src/main/java/com/firebase/ui/auth/provider/GoogleProvider.java
@@ -20,11 +20,10 @@
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
import com.firebase.ui.auth.AuthUI.IdpConfig;
import com.firebase.ui.auth.IdpResponse;
@@ -39,24 +38,22 @@
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.GoogleAuthProvider;
-public class GoogleProvider implements
- IdpProvider, OnClickListener, GoogleApiClient.OnConnectionFailedListener {
+public class GoogleProvider implements IdpProvider, GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "GoogleProvider";
private static final int AUTO_MANAGE_ID = 1;
private static final int RC_SIGN_IN = 20;
private static final String ERROR_KEY = "error";
+
private GoogleApiClient mGoogleApiClient;
- private Activity mActivity;
private IdpCallback mIDPCallback;
public GoogleProvider(FragmentActivity activity, IdpConfig idpConfig) {
this(activity, idpConfig, null);
}
- public GoogleProvider(FragmentActivity activity, IdpConfig idpConfig, @Nullable String email) {
- mActivity = activity;
- String mClientId = activity.getString(R.string.default_web_client_id);
+ public GoogleProvider(Context context, IdpConfig idpConfig, @Nullable String email) {
+ String mClientId = context.getString(R.string.default_web_client_id);
GoogleSignInOptions googleSignInOptions;
GoogleSignInOptions.Builder builder =
@@ -64,8 +61,8 @@ public GoogleProvider(FragmentActivity activity, IdpConfig idpConfig, @Nullable
.requestEmail()
.requestIdToken(mClientId);
- if (activity.getResources().getIdentifier(
- "google_permissions", "array", activity.getPackageName()) != 0){
+ if (context.getResources().getIdentifier(
+ "google_permissions", "array", context.getPackageName()) != 0) {
Log.w(TAG, "DEVELOPER WARNING: You have defined R.array.google_permissions but that is"
+ " no longer respected as of FirebaseUI 1.0.0. Please see README for IDP scope"
+ " configuration instructions.");
@@ -81,10 +78,15 @@ public GoogleProvider(FragmentActivity activity, IdpConfig idpConfig, @Nullable
}
googleSignInOptions = builder.build();
- mGoogleApiClient = new GoogleApiClient.Builder(activity)
- .enableAutoManage(activity, AUTO_MANAGE_ID, this)
- .addApi(Auth.GOOGLE_SIGN_IN_API, googleSignInOptions)
- .build();
+ GoogleApiClient.Builder googleBuilder = new GoogleApiClient.Builder(context);
+
+ try {
+ googleBuilder =
+ googleBuilder.enableAutoManage((FragmentActivity) context, AUTO_MANAGE_ID, this);
+ } finally {
+ mGoogleApiClient =
+ googleBuilder.addApi(Auth.GOOGLE_SIGN_IN_API, googleSignInOptions).build();
+ }
}
public String getName(Context context) {
@@ -136,8 +138,15 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
@Override
public void startLogin(Activity activity) {
- Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
- activity.startActivityForResult(signInIntent, RC_SIGN_IN);
+ activity.startActivityForResult(getSignInIntent(), RC_SIGN_IN);
+ }
+
+ public void startLogin(Fragment fragment) {
+ fragment.startActivityForResult(getSignInIntent(), RC_SIGN_IN);
+ }
+
+ private Intent getSignInIntent() {
+ return Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
}
private void onError(String errorMessage) {
@@ -146,12 +155,6 @@ private void onError(String errorMessage) {
mIDPCallback.onFailure(extra);
}
- @Override
- public void onClick(View view) {
- Auth.GoogleSignInApi.signOut(mGoogleApiClient);
- startLogin(mActivity);
- }
-
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.w(TAG, "onConnectionFailed:" + connectionResult);
diff --git a/auth/src/main/java/com/firebase/ui/auth/provider/IdpProvider.java b/auth/src/main/java/com/firebase/ui/auth/provider/IdpProvider.java
index 2a117c30e..0c589f2ed 100644
--- a/auth/src/main/java/com/firebase/ui/auth/provider/IdpProvider.java
+++ b/auth/src/main/java/com/firebase/ui/auth/provider/IdpProvider.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+
import com.firebase.ui.auth.IdpResponse;
public interface IdpProvider {
@@ -35,8 +36,8 @@ public interface IdpProvider {
void startLogin(Activity activity);
- public interface IdpCallback {
- public void onSuccess(IdpResponse idpResponse);
- public void onFailure(Bundle extra);
+ interface IdpCallback {
+ void onSuccess(IdpResponse idpResponse);
+ void onFailure(Bundle extra);
}
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/AcquireEmailHelper.java b/auth/src/main/java/com/firebase/ui/auth/ui/AcquireEmailHelper.java
index 4c11d904d..87ddcd3c3 100644
--- a/auth/src/main/java/com/firebase/ui/auth/ui/AcquireEmailHelper.java
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/AcquireEmailHelper.java
@@ -16,11 +16,13 @@
import android.content.Intent;
import android.support.annotation.NonNull;
+import android.text.TextUtils;
import com.firebase.ui.auth.R;
import com.firebase.ui.auth.ui.account_link.WelcomeBackIdpPrompt;
import com.firebase.ui.auth.ui.email.RegisterEmailActivity;
import com.firebase.ui.auth.ui.email.SignInActivity;
+import com.firebase.ui.auth.util.BaseHelper;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.EmailAuthProvider;
@@ -41,16 +43,16 @@ public class AcquireEmailHelper {
RC_SIGN_IN
);
- private ActivityHelper mActivityHelper;
+ private BaseHelper mHelper;
- public AcquireEmailHelper(ActivityHelper activityHelper) {
- mActivityHelper = activityHelper;
+ public AcquireEmailHelper(BaseHelper helper) {
+ mHelper = helper;
}
public void checkAccountExists(final String email) {
- FirebaseAuth firebaseAuth = mActivityHelper.getFirebaseAuth();
- mActivityHelper.showLoadingDialog(R.string.progress_dialog_loading);
- if (email != null && !email.isEmpty()) {
+ FirebaseAuth firebaseAuth = mHelper.getFirebaseAuth();
+ mHelper.showLoadingDialog(R.string.progress_dialog_loading);
+ if (!TextUtils.isEmpty(email)) {
firebaseAuth
.fetchProvidersForEmail(email)
.addOnFailureListener(
@@ -62,7 +64,7 @@ public void onComplete(@NonNull Task task) {
if (task.isSuccessful()) {
startEmailHandler(email, task.getResult().getProviders());
} else {
- mActivityHelper.dismissDialog();
+ mHelper.dismissDialog();
}
}
});
@@ -70,46 +72,46 @@ public void onComplete(@NonNull Task task) {
}
private void startEmailHandler(String email, List providers) {
- mActivityHelper.dismissDialog();
+ mHelper.dismissDialog();
if (providers == null || providers.isEmpty()) {
// account doesn't exist yet
Intent registerIntent = RegisterEmailActivity.createIntent(
- mActivityHelper.getApplicationContext(),
- mActivityHelper.getFlowParams(),
+ mHelper.getApplicationContext(),
+ mHelper.getFlowParams(),
email);
- mActivityHelper.startActivityForResult(registerIntent, RC_REGISTER_ACCOUNT);
+ mHelper.startActivityForResult(registerIntent, RC_REGISTER_ACCOUNT);
} else {
// account does exist
for (String provider : providers) {
if (provider.equalsIgnoreCase(EmailAuthProvider.PROVIDER_ID)) {
Intent signInIntent = SignInActivity.createIntent(
- mActivityHelper.getApplicationContext(),
- mActivityHelper.getFlowParams(),
+ mHelper.getApplicationContext(),
+ mHelper.getFlowParams(),
email);
- mActivityHelper.startActivityForResult(signInIntent, RC_SIGN_IN);
+ mHelper.startActivityForResult(signInIntent, RC_SIGN_IN);
return;
}
Intent intent = WelcomeBackIdpPrompt.createIntent(
- mActivityHelper.getApplicationContext(),
- mActivityHelper.getFlowParams(),
+ mHelper.getApplicationContext(),
+ mHelper.getFlowParams(),
provider,
null,
email);
- mActivityHelper.startActivityForResult(intent, RC_WELCOME_BACK_IDP);
+ mHelper.startActivityForResult(intent, RC_WELCOME_BACK_IDP);
return;
}
Intent signInIntent = new Intent(
- mActivityHelper.getApplicationContext(), SignInActivity.class);
+ mHelper.getApplicationContext(), SignInActivity.class);
signInIntent.putExtra(ExtraConstants.EXTRA_EMAIL, email);
- mActivityHelper.startActivityForResult(signInIntent, RC_SIGN_IN);
+ mHelper.startActivityForResult(signInIntent, RC_SIGN_IN);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (REQUEST_CODES.contains(requestCode)) {
- mActivityHelper.finish(resultCode, data);
+ mHelper.finish(resultCode, data);
}
}
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/ActivityBase.java b/auth/src/main/java/com/firebase/ui/auth/ui/ActivityBase.java
deleted file mode 100644
index b85c06bb5..000000000
--- a/auth/src/main/java/com/firebase/ui/auth/ui/ActivityBase.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.firebase.ui.auth.ui;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-
-public class ActivityBase extends Activity {
- protected ActivityHelper mActivityHelper;
-
- @Override
- protected void onCreate(Bundle savedInstance) {
- super.onCreate(savedInstance);
- mActivityHelper = new ActivityHelper(this, getIntent());
- mActivityHelper.configureTheme();
- }
-
- public void finish(int resultCode, Intent intent) {
- mActivityHelper.finish(resultCode, intent);
- }
-
-}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/ActivityHelper.java b/auth/src/main/java/com/firebase/ui/auth/ui/ActivityHelper.java
index 667c16613..ca4f3ba93 100644
--- a/auth/src/main/java/com/firebase/ui/auth/ui/ActivityHelper.java
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/ActivityHelper.java
@@ -15,54 +15,19 @@
package com.firebase.ui.auth.ui;
import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.Context;
import android.content.Intent;
-import android.support.annotation.NonNull;
-import android.support.annotation.StringRes;
-import com.google.android.gms.auth.api.Auth;
-import com.google.android.gms.auth.api.credentials.CredentialsApi;
-import com.google.firebase.FirebaseApp;
-import com.google.firebase.auth.FirebaseAuth;
-import com.google.firebase.auth.FirebaseUser;
+import com.firebase.ui.auth.util.BaseHelper;
-import static com.firebase.ui.auth.util.Preconditions.checkNotNull;
-
-public class ActivityHelper {
- private ProgressDialog mProgressDialog;
+public class ActivityHelper extends BaseHelper {
private Activity mActivity;
- private final FlowParameters mFlowParams;
public ActivityHelper(Activity activity, Intent intent) {
+ super(activity, (FlowParameters) intent.getParcelableExtra(ExtraConstants.EXTRA_FLOW_PARAMS));
mActivity = activity;
- mFlowParams = intent.getParcelableExtra(ExtraConstants.EXTRA_FLOW_PARAMS);
- }
-
- public void configureTheme() {
- mActivity.setTheme(mFlowParams.themeId);
- }
-
- public void dismissDialog() {
- if (mProgressDialog != null && mProgressDialog.isShowing()) {
- mProgressDialog.dismiss();
- mProgressDialog = null;
- }
- }
-
- public FlowParameters getFlowParams() {
- return mFlowParams;
- }
-
- public void showLoadingDialog(String message) {
- dismissDialog();
- mProgressDialog = ProgressDialog.show(mActivity, "", message, true);
- }
-
- public void showLoadingDialog(@StringRes int stringResource) {
- showLoadingDialog(mActivity.getString(stringResource));
}
+ @Override
public void startActivityForResult(Intent intent, int requestCode) {
mActivity.startActivityForResult(intent, requestCode);
}
@@ -71,39 +36,4 @@ public void finish(int resultCode, Intent intent) {
mActivity.setResult(resultCode, intent);
mActivity.finish();
}
-
- public Context getApplicationContext() {
- return mActivity.getApplicationContext();
- }
-
- public String getAppName() {
- return mFlowParams.appName;
- }
-
- public FirebaseApp getFirebaseApp() {
- return FirebaseApp.getInstance(mFlowParams.appName);
- }
-
- public FirebaseAuth getFirebaseAuth() {
- return FirebaseAuth.getInstance(getFirebaseApp());
- }
-
- public CredentialsApi getCredentialsApi() {
- return Auth.CredentialsApi;
- }
-
- public FirebaseUser getCurrentUser() {
- return getFirebaseAuth().getCurrentUser();
- }
-
- public static Intent createBaseIntent(
- @NonNull Context context,
- @NonNull Class extends Activity> target,
- @NonNull FlowParameters flowParams) {
- return new Intent(
- checkNotNull(context, "context cannot be null"),
- checkNotNull(target, "target activity cannot be null"))
- .putExtra(ExtraConstants.EXTRA_FLOW_PARAMS,
- checkNotNull(flowParams, "flowParams cannot be null"));
- }
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/BaseFragment.java b/auth/src/main/java/com/firebase/ui/auth/ui/BaseFragment.java
new file mode 100644
index 000000000..52a2d98ef
--- /dev/null
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/BaseFragment.java
@@ -0,0 +1,23 @@
+package com.firebase.ui.auth.ui;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+
+import com.firebase.ui.auth.util.BaseHelper;
+
+/**
+ * A simple Fragment with {@code setRetainInstance} set to true.
+ */
+public class BaseFragment extends Fragment {
+ protected BaseHelper mHelper;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setRetainInstance(true);
+ mHelper = new FragmentHelper(this,
+ (FlowParameters) getArguments()
+ .getParcelable(ExtraConstants.EXTRA_FLOW_PARAMS));
+ }
+}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/ChooseAccountActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/ChooseAccountActivity.java
deleted file mode 100644
index 98d46f8a3..000000000
--- a/auth/src/main/java/com/firebase/ui/auth/ui/ChooseAccountActivity.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.firebase.ui.auth.ui;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.firebase.ui.auth.AuthUI.IdpConfig;
-import com.firebase.ui.auth.BuildConfig;
-import com.firebase.ui.auth.ui.idp.AuthMethodPickerActivity;
-import com.firebase.ui.auth.ui.idp.IdpSignInContainerActivity;
-import com.firebase.ui.auth.util.CredentialsAPI;
-import com.firebase.ui.auth.util.CredentialsApiHelper;
-import com.firebase.ui.auth.util.EmailFlowUtil;
-import com.firebase.ui.auth.util.PlayServicesHelper;
-import com.google.android.gms.auth.api.credentials.Credential;
-import com.google.android.gms.auth.api.credentials.CredentialsApi;
-import com.google.android.gms.auth.api.credentials.IdentityProviders;
-import com.google.android.gms.common.api.Status;
-import com.google.android.gms.tasks.OnCompleteListener;
-import com.google.android.gms.tasks.OnFailureListener;
-import com.google.android.gms.tasks.OnSuccessListener;
-import com.google.android.gms.tasks.Task;
-import com.google.firebase.auth.AuthResult;
-import com.google.firebase.auth.EmailAuthProvider;
-import com.google.firebase.auth.FacebookAuthProvider;
-import com.google.firebase.auth.FirebaseAuthInvalidUserException;
-import com.google.firebase.auth.GoogleAuthProvider;
-import com.google.firebase.auth.TwitterAuthProvider;
-import java.util.List;
-
-import static com.firebase.ui.auth.ui.ResultCodes.RESULT_NO_NETWORK;
-
-/**
- * Attempts to acquire a credential from Smart Lock for Passwords to sign in
- * an existing account. If this succeeds, an attempt is made to sign the user in
- * with this credential. If it does not, the
- * {@link AuthMethodPickerActivity authentication method picker activity}
- * is started, unless only email is supported, in which case the
- * {@link com.firebase.ui.auth.ui.email.SignInNoPasswordActivity email sign-in flow}
- * is started.
- */
-public class ChooseAccountActivity extends ActivityBase {
- private static final String TAG = "ChooseAccountActivity";
-
- private static final int RC_CREDENTIALS_READ = 2;
- private static final int RC_IDP_SIGNIN = 3;
- private static final int RC_AUTH_METHOD_PICKER = 4;
- private static final int RC_EMAIL_FLOW = 5;
- private static final int RC_PLAY_SERVICES = 6;
-
- private CredentialsAPI mCredentialsApi;
- private PlayServicesHelper mPlayServicesHelper;
-
- @Override
- protected void onCreate(Bundle savedInstance) {
- super.onCreate(savedInstance);
-
- if (!hasNetworkConnection()) {
- Log.d(TAG, "No network connection");
-
- finish(RESULT_NO_NETWORK, new Intent());
- return;
- }
-
- // Make Google Play Services available at the correct version, if possible
- mPlayServicesHelper = PlayServicesHelper.getInstance(this);
- boolean madeAvailable = mPlayServicesHelper
- .makePlayServicesAvailable(this, RC_PLAY_SERVICES,
- new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialogInterface) {
- Log.w(TAG, "playServices:dialog.onCancel()");
- finish(RESULT_CANCELED, new Intent());
- }
- });
-
- if (!madeAvailable) {
- Log.w(TAG, "playServices: could not make available.");
- finish(RESULT_CANCELED, new Intent());
- return;
- }
-
- mCredentialsApi = new CredentialsAPI(this, new CredentialsAPI.CallbackInterface() {
- @Override
- public void onAsyncTaskFinished() {
- onCredentialsApiConnected(mCredentialsApi, mActivityHelper);
- }
- });
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- if (mCredentialsApi != null) {
- mCredentialsApi.onStart();
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (mCredentialsApi != null) {
- mCredentialsApi.onStop();
- }
- }
-
- /**
- * Check if there is an active or soon-to-be-active network connection.
- */
- private boolean hasNetworkConnection() {
- ConnectivityManager manager =
- (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
-
- return manager != null
- && manager.getActiveNetworkInfo() != null
- && manager.getActiveNetworkInfo().isConnectedOrConnecting();
- }
-
- /**
- * Called when the Credentials API connects.
- */
- public void onCredentialsApiConnected(
- CredentialsAPI credentialsApi,
- ActivityHelper activityHelper) {
- String email = credentialsApi.getEmailFromCredential();
- String password = credentialsApi.getPasswordFromCredential();
- String accountType = credentialsApi.getAccountTypeFromCredential();
-
- FlowParameters flowParams = activityHelper.getFlowParams();
-
- if (flowParams.smartLockEnabled
- && mPlayServicesHelper.isPlayServicesAvailable()
- && credentialsApi.isCredentialsAvailable()) {
-
- // Attempt auto-sign in using SmartLock
- if (credentialsApi.isAutoSignInAvailable()) {
- credentialsApi.googleSilentSignIn();
- if (!TextUtils.isEmpty(password)) {
- // Sign in with the email/password retrieved from SmartLock
- signInWithEmailAndPassword(activityHelper, email, password);
- } else {
- // log in with id/provider
- redirectToIdpSignIn(email, accountType);
- }
- } else if (credentialsApi.isSignInResolutionNeeded()) {
- // resolve credential
- credentialsApi.resolveSavedEmails(this);
- } else {
- startAuthMethodChoice(activityHelper);
- }
- } else {
- startAuthMethodChoice(activityHelper);
- }
- }
-
- private void startAuthMethodChoice(ActivityHelper activityHelper) {
- List idpConfigs = activityHelper.getFlowParams().providerInfo;
-
- // If the only provider is Email, immediately launch the email flow. Otherwise, launch
- // the auth method picker screen.
- if (idpConfigs.size() == 1
- && idpConfigs.get(0).getProviderId().equals(EmailAuthProvider.PROVIDER_ID)) {
- startActivityForResult(
- EmailFlowUtil.createIntent(
- this,
- activityHelper.getFlowParams()),
- RC_EMAIL_FLOW);
- } else {
- startActivityForResult(
- AuthMethodPickerActivity.createIntent(
- this,
- activityHelper.getFlowParams()),
- RC_AUTH_METHOD_PICKER);
- }
- }
-
- private void logInWithCredential(
- final String email,
- final String password,
- final String accountType) {
-
- if (email != null
- && mCredentialsApi.isCredentialsAvailable()
- && !mCredentialsApi.isSignInResolutionNeeded()) {
- if (password != null && !password.isEmpty()) {
- // email/password combination
- signInWithEmailAndPassword(mActivityHelper, email, password);
- } else {
- // identifier/provider combination
- redirectToIdpSignIn(email, accountType);
- }
- }
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data);
- }
-
- switch (requestCode) {
- case RC_CREDENTIALS_READ:
- if (resultCode == RESULT_OK) {
- // credential selected from SmartLock, log in with that credential
- Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
- mCredentialsApi.handleCredential(credential);
- mCredentialsApi.resolveSignIn();
- logInWithCredential(
- mCredentialsApi.getEmailFromCredential(),
- mCredentialsApi.getPasswordFromCredential(),
- mCredentialsApi.getAccountTypeFromCredential()
- );
- } else if (resultCode == RESULT_CANCELED
- || resultCode == CredentialsApi.ACTIVITY_RESULT_OTHER_ACCOUNT) {
- // Smart lock selector cancelled, go to the AuthMethodPicker screen
- startAuthMethodChoice(mActivityHelper);
- } else if (resultCode == RESULT_FIRST_USER) {
- // TODO: (serikb) figure out flow
- }
- break;
- case RC_IDP_SIGNIN:
- case RC_AUTH_METHOD_PICKER:
- case RC_EMAIL_FLOW:
- finish(resultCode, data);
- break;
- case RC_PLAY_SERVICES:
- if (resultCode != RESULT_OK) {
- finish(resultCode, new Intent());
- }
- break;
- }
- }
-
- /**
- * Begin sign in process with email and password from a SmartLock credential.
- * On success, finish with {@link #RESULT_OK}.
- * On failure, delete the credential from SmartLock (if applicable) and then launch the
- * auth method picker flow.
- */
- private void signInWithEmailAndPassword(ActivityHelper helper, String email, String password) {
- helper.getFirebaseAuth()
- .signInWithEmailAndPassword(email, password)
- .addOnFailureListener(new TaskFailureLogger(
- TAG, "Error signing in with email and password"))
- .addOnSuccessListener(new OnSuccessListener() {
- @Override
- public void onSuccess(AuthResult authResult) {
- finish(RESULT_OK, new Intent());
- }
- })
- .addOnFailureListener(new OnFailureListener() {
- @Override
- public void onFailure(@NonNull Exception e) {
- if (e instanceof FirebaseAuthInvalidUserException) {
- // In this case the credential saved in SmartLock was not
- // a valid credential, we should delete it from SmartLock
- // before continuing.
- deleteCredentialAndRedirect();
- } else {
- startAuthMethodChoice(mActivityHelper);
- }
- }
- });
- }
-
- /**
- * Delete the last credential retrieved from SmartLock and then redirect to the
- * auth method choice flow.
- */
- private void deleteCredentialAndRedirect() {
- if (mCredentialsApi.getCredential() == null) {
- Log.w(TAG, "deleteCredentialAndRedirect: null credential");
- startAuthMethodChoice(mActivityHelper);
- return;
- }
-
- CredentialsApiHelper credentialsApiHelper = CredentialsApiHelper.getInstance(this);
- credentialsApiHelper.delete(mCredentialsApi.getCredential())
- .addOnCompleteListener(this, new OnCompleteListener() {
- @Override
- public void onComplete(@NonNull Task task) {
- if (!task.isSuccessful()) {
- Log.w(TAG, "deleteCredential:failure", task.getException());
- }
- startAuthMethodChoice(mActivityHelper);
- }
- });
- }
-
- protected void redirectToIdpSignIn(String email, String accountType) {
- Intent nextIntent;
- switch (accountType) {
- case IdentityProviders.GOOGLE:
- nextIntent = IdpSignInContainerActivity.createIntent(
- this,
- mActivityHelper.getFlowParams(),
- GoogleAuthProvider.PROVIDER_ID,
- email);
- break;
- case IdentityProviders.FACEBOOK:
- nextIntent = IdpSignInContainerActivity.createIntent(
- this,
- mActivityHelper.getFlowParams(),
- FacebookAuthProvider.PROVIDER_ID,
- email);
- break;
- case IdentityProviders.TWITTER:
- nextIntent = IdpSignInContainerActivity.createIntent(
- this,
- mActivityHelper.getFlowParams(),
- TwitterAuthProvider.PROVIDER_ID,
- email);
- break;
- default:
- Log.w(TAG, "unknown provider: " + accountType);
- nextIntent = AuthMethodPickerActivity.createIntent(
- this,
- mActivityHelper.getFlowParams());
- }
- this.startActivityForResult(nextIntent, RC_IDP_SIGNIN);
- }
-
- public static Intent createIntent(
- Context context,
- FlowParameters flowParams) {
- return ActivityHelper.createBaseIntent(context, ChooseAccountActivity.class, flowParams);
- }
-}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/FragmentHelper.java b/auth/src/main/java/com/firebase/ui/auth/ui/FragmentHelper.java
new file mode 100644
index 000000000..1d71e2b55
--- /dev/null
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/FragmentHelper.java
@@ -0,0 +1,28 @@
+package com.firebase.ui.auth.ui;
+
+import android.content.Intent;
+import android.support.v4.app.Fragment;
+
+import com.firebase.ui.auth.util.BaseHelper;
+import com.firebase.ui.auth.util.smartlock.SignInDelegate;
+
+public class FragmentHelper extends BaseHelper {
+ private Fragment mFragment;
+
+ public FragmentHelper(Fragment fragment, FlowParameters parameters) {
+ super(fragment.getContext(), parameters);
+ mFragment = fragment;
+ }
+
+ @Override
+ public void startActivityForResult(Intent intent, int requestCode) {
+ mFragment.startActivityForResult(intent, requestCode);
+ }
+
+ @Override
+ public void finish(int resultCode, Intent intent) {
+ if (mFragment instanceof SignInDelegate) {
+ ((SignInDelegate) mFragment).finish(resultCode, intent);
+ }
+ }
+}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/account_link/WelcomeBackPasswordPrompt.java b/auth/src/main/java/com/firebase/ui/auth/ui/account_link/WelcomeBackPasswordPrompt.java
index b3179d066..4e91bf220 100644
--- a/auth/src/main/java/com/firebase/ui/auth/ui/account_link/WelcomeBackPasswordPrompt.java
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/account_link/WelcomeBackPasswordPrompt.java
@@ -38,7 +38,7 @@
import com.firebase.ui.auth.ui.TaskFailureLogger;
import com.firebase.ui.auth.ui.email.PasswordToggler;
import com.firebase.ui.auth.ui.email.RecoverPasswordActivity;
-import com.firebase.ui.auth.util.SmartLock;
+import com.firebase.ui.auth.util.smartlock.SaveSmartLock;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.AuthCredential;
@@ -80,7 +80,8 @@ protected void onCreate(Bundle savedInstanceState) {
TextView bodyTextView = ((TextView) findViewById(R.id.welcome_back_password_body));
bodyTextView.setText(spannableStringBuilder);
- ((TextInputLayout) findViewById(R.id.password_layout)).setPasswordVisibilityToggleEnabled(false);
+ ((TextInputLayout) findViewById(R.id.password_layout)).setPasswordVisibilityToggleEnabled(
+ false);
// Click listeners
findViewById(R.id.button_done).setOnClickListener(this);
@@ -133,20 +134,21 @@ public void onSuccess(AuthResult authResult) {
// Sign in with the credential
firebaseAuth.signInWithCredential(authCredential)
.addOnFailureListener(
- new TaskFailureLogger(TAG, "Error signing in with credential"))
+ new TaskFailureLogger(TAG,
+ "Error signing in with credential"))
.addOnSuccessListener(
new OnSuccessListener() {
@Override
public void onSuccess(AuthResult authResult) {
- SmartLock
+ SaveSmartLock
.getInstance(WelcomeBackPasswordPrompt.this,
+ mActivityHelper.getFlowParams(),
TAG)
- .saveCredentialsOrFinish(
- WelcomeBackPasswordPrompt.this,
- mActivityHelper,
- authResult.getUser(),
- password,
- null /* provider */);
+ .saveCredentialsOrFinish(WelcomeBackPasswordPrompt.this,
+ mActivityHelper.getFlowParams(),
+ authResult.getUser(),
+ password,
+ null /* provider */);
}
});
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailHintContainerActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailHintContainerActivity.java
deleted file mode 100644
index 94b95344c..000000000
--- a/auth/src/main/java/com/firebase/ui/auth/ui/email/EmailHintContainerActivity.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.firebase.ui.auth.ui.email;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentSender;
-import android.os.Bundle;
-
-import com.firebase.ui.auth.ui.AcquireEmailHelper;
-import com.firebase.ui.auth.ui.ActivityHelper;
-import com.firebase.ui.auth.ui.AppCompatBase;
-import com.firebase.ui.auth.ui.FlowParameters;
-import com.firebase.ui.auth.util.FirebaseAuthWrapper;
-import com.firebase.ui.auth.util.FirebaseAuthWrapperFactory;
-import com.google.android.gms.auth.api.credentials.Credential;
-
-public class EmailHintContainerActivity extends AppCompatBase {
- private static final int RC_HINT = 13;
- private AcquireEmailHelper mAcquireEmailHelper;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mAcquireEmailHelper = new AcquireEmailHelper(mActivityHelper);
- FirebaseAuthWrapper apiWrapper =
- FirebaseAuthWrapperFactory.getFirebaseAuthWrapper(mActivityHelper.getAppName());
-
- PendingIntent hintIntent = apiWrapper.getEmailHintIntent(this);
- if (hintIntent != null) {
- try {
- startIntentSenderForResult(hintIntent.getIntentSender(), RC_HINT, null, 0, 0, 0);
- return;
- } catch (IntentSender.SendIntentException e) {
- e.printStackTrace();
- }
- }
- finish(RESULT_CANCELED, new Intent());
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == RC_HINT && data != null) {
- Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
- if (credential == null) {
- // If the hint picker is cancelled show the SignInNoPasswordActivity
- startActivityForResult(
- SignInNoPasswordActivity.createIntent(
- this,
- mActivityHelper.getFlowParams(),
- null),
- AcquireEmailHelper.RC_SIGN_IN);
- return;
- }
- mAcquireEmailHelper.checkAccountExists(credential.getId());
- } else {
- mAcquireEmailHelper.onActivityResult(requestCode, resultCode, data);
- }
- }
-
- public static Intent createIntent(
- Context context,
- FlowParameters flowParams) {
- return ActivityHelper.createBaseIntent(
- context,
- EmailHintContainerActivity.class,
- flowParams);
- }
-}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailActivity.java
index 0974c1c91..5c056eee3 100644
--- a/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailActivity.java
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailActivity.java
@@ -39,7 +39,7 @@
import com.firebase.ui.auth.ui.email.field_validators.EmailFieldValidator;
import com.firebase.ui.auth.ui.email.field_validators.PasswordFieldValidator;
import com.firebase.ui.auth.ui.email.field_validators.RequiredFieldValidator;
-import com.firebase.ui.auth.util.SmartLock;
+import com.firebase.ui.auth.util.smartlock.SaveSmartLock;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
@@ -154,9 +154,11 @@ public void onComplete(@NonNull Task task) {
// This executes even if the name change fails, since
// the account creation succeeded and we want to save
// the credential to SmartLock (if enabled).
- SmartLock.getInstance(RegisterEmailActivity.this, TAG)
+ SaveSmartLock.getInstance(RegisterEmailActivity.this,
+ mActivityHelper.getFlowParams(),
+ TAG)
.saveCredentialsOrFinish(RegisterEmailActivity.this,
- mActivityHelper,
+ mActivityHelper.getFlowParams(),
firebaseUser,
password,
null /* provider */);
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/SignInActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/SignInActivity.java
index 7d091eac7..140aebc8f 100644
--- a/auth/src/main/java/com/firebase/ui/auth/ui/email/SignInActivity.java
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/SignInActivity.java
@@ -34,7 +34,7 @@
import com.firebase.ui.auth.ui.TaskFailureLogger;
import com.firebase.ui.auth.ui.email.field_validators.EmailFieldValidator;
import com.firebase.ui.auth.ui.email.field_validators.RequiredFieldValidator;
-import com.firebase.ui.auth.util.SmartLock;
+import com.firebase.ui.auth.util.smartlock.SaveSmartLock;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.AuthResult;
@@ -98,9 +98,11 @@ private void signIn(String email, final String password) {
@Override
public void onSuccess(AuthResult authResult) {
// Save credential in SmartLock (if enabled)
- SmartLock.getInstance(SignInActivity.this, TAG)
+ SaveSmartLock.getInstance(SignInActivity.this,
+ mActivityHelper.getFlowParams(),
+ TAG)
.saveCredentialsOrFinish(SignInActivity.this,
- mActivityHelper,
+ mActivityHelper.getFlowParams(),
authResult.getUser(),
password,
null /* provider */);
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 ca746e5e5..7df9d9ae8 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
@@ -25,19 +25,20 @@
import com.firebase.ui.auth.AuthUI;
import com.firebase.ui.auth.AuthUI.IdpConfig;
import com.firebase.ui.auth.BuildConfig;
+import com.firebase.ui.auth.IdpResponse;
import com.firebase.ui.auth.R;
import com.firebase.ui.auth.provider.FacebookProvider;
import com.firebase.ui.auth.provider.GoogleProvider;
import com.firebase.ui.auth.provider.IdpProvider;
import com.firebase.ui.auth.provider.IdpProvider.IdpCallback;
-import com.firebase.ui.auth.IdpResponse;
import com.firebase.ui.auth.provider.TwitterProvider;
import com.firebase.ui.auth.ui.ActivityHelper;
+import com.firebase.ui.auth.ui.AppCompatBase;
import com.firebase.ui.auth.ui.FlowParameters;
import com.firebase.ui.auth.ui.TaskFailureLogger;
-import com.firebase.ui.auth.ui.email.EmailHintContainerActivity;
import com.firebase.ui.auth.util.EmailFlowUtil;
-import com.firebase.ui.auth.util.SmartLock;
+import com.firebase.ui.auth.util.EmailHintContainer;
+import com.firebase.ui.auth.util.smartlock.SaveSmartLock;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.FirebaseAuth;
@@ -51,18 +52,20 @@
* Presents the list of authentication options for this app to the user. If an
* identity provider option is selected, a {@link IdpSignInContainerActivity container activity}
* is launched to manage the IDP-specific sign-in flow. If email authentication is chosen,
- * the {@link EmailHintContainerActivity root email flow activity} is started.
- *
+ * the {@link EmailHintContainer root email flow activity} is started.
+ *
*
*
+ * src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWgAAAKACAMAAACGxBKVAAAAOVBMVEXu7u7Nzs7h4eLFwsMvPp7QAho7WZg+ULQAAAD///8yUpQ2SbNpfLxteG+eqL6Rk5Hrj4zfQ1BERESoYitxAAALMElEQVR42uzdDXuiOBSG4XwoXqEhwP//s3tOAkhrrO7u6G7wuWtLichcfTkeIjN1zAlvYYiAoAkaBP1WMcV0Ieh/4RKLy9f3Ufm4Bnu52BDCs0kT9P2Ys7V45fZt4HTSmFUi6H/YEL67LOGv+e+DdiKsIykEUzaOEn/cFgT9S9LJGYnR70t6TXoXtIZn1ixjiBfj8rfBS1fRxZcuCPpu60hm6QrBxl36Jeld0D6XdVwLOn9Gd4nhcrpI7HKPfkvQd6Wwuewbd/lyDVqCNFvr+Ao+Sr+ORoI+adAn46JzVPRv3E3OpXNr0rugU9SDEncnx0tpIiVoevQTc4SSc/w5FdGT4u5kaLX4d62jtOQlaFrHM2065+xv5yKnyz7oy65orSkRn3K6Ue/7yoVN0L/OPCRBV5tcn3ZBu7gre2nQ0Rg9GZ7kDmckZBuZdTxzQqzPrndB22/9JZpgL3oyPF2cfieZS+IE/Yj98dr6soi8MnyH/jZ5rnX8v+YxREDQBI1/EPQFb0HQBE3QIGiCJmgiIGiCBkETNEGDoAkaBE3QBA2CJmgQNEETNAiaoEHQBE3QIGiCBkETNEGDoAkaBE3QBA2CJmgQNEETNAiaoEHQBE3QIOhjBP2FtzDWeryeNZIztxff5EOCtrrg9rpb+aJB4w2Mw2vZsiDoNzHOGMfHCz+MWRcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACtcsY1dGs359CYRqN2oTkUNCV9rIomaIImaIImaIImaIImaIImaIIm6NcGbZw1BP3yoO2cTQT92qCnef7/J32AoHPOk379vXu4J8e2Ue+fitD6zwjaraV8t0uPwzD4YId0m1FlrIw6G8IwbENJdpHu7v4zgp4etYxxSHYcbPCVA+GrB0dGNb1hvOY8yi7Shwc95ZZhiztBmNGb0cpi9PqdH8ecmoxdV9Io6xJxklGp4FEqOo0l61zb+r1s6/OmeSEPlAfp/u2yj2MHnQs6FrX61MYhP6l81eiGZPLClrHrih/kJuteRr3Wr4RdytistZ10xK+LURc5aDeMaUifHrQmrV1XE0wSmgSd19ag1xU7OMnNDc7lEEsd54glR6llrfExj+4XOehxMI86yCFah646cSdouVNqVuKzkuD9oMOQBi+fYQt6XILWinZ+iVZCLYtvQaujBz2sT2wbY+3pq3dLLT+saI1L20W4qejSo3+U8s+KDubgQUuTHUb9Ib0UtKueDMdUKnrr0fWgfU7NL0Gna0VLV9EHDqU5p3Vx7dFW/4jx6C9Y/LDoYv18pO1VZxz6Ka1BZhUS5phPhnnWsazIwsn0weUtndapdoi09h6ZjWzTjXUhext1tiIPKwf72C/Bt6THhy/inITj/9SraqOvgsbPeQmu0+Ecs334047PHI2n5QNsPinoHPZzRfhHr6Ya9/yFcS78c/WOoAmaoAmaoAmaoAmaoAmaoAmaoAn6Ltte0LbNiraN/QKcsa3+Rqf1TWk1Z+OcbYpr+LfBAQAAAAAADsPGvinRNhp015xGC7pvLug2S9o3F3TvCZqgCfo/lwiaiiZogiZoejQVTdAETdAE/a96dLzqCfplFd3v/wVvIujXBb3+m3SfUjXoPt+6WLkrViMpozGt95YLytUt07ODBwo6Spy1oKMJwXW9Cbc/emVsGY2xux61tOz/dlNbGa0OHqFHr0H3nTO1oIORSjd91EdIXeb6XupTx7aVfq1/GY2yIwl6uScFm1LKlV0KvFsXPnQ3YzrYVZ4Ah6loqedaj46aV7Kdd7IwLrkuOVnG/KO7fl3po4u9T50svOtcPjrJmViCzotodUt5hNE/xeuKD/JovcsZvy28bO7sUYPWhhqrPVrf0qrXrXopbDlxdlYXps+P7LeVLvg+6LqMyiYuRX1/mVCCTjKh0adG0J04K8fO6Js9Sqb50VHH3LqQoE2tpRwjaJ3Y9fWToYRrooYqCUqQsp4jXoPeVlyU3Rinq6V1xKWWy1s+6ixStpZ7e+tj8Ppc8WWP7ttC0q829GP0aAmoM9UeLe1SK1ECMprRvaC1bp3TxrwFnbagpaL1gMlptZOdyC7j+ma8ubHo2HXh75w5D96jtWNqLT+qaCnQIH05xFrQcWn2vlR0SlrR5by3jm0LCVp61OcFLaNe+2ju0c6Hu0HLhhp2X4I2Kd4E7fQ45B7t5dlhc6ayx9yjfenRPvdoecTtJYLDB63/csXmGYbOOqSqZeKha+usY1mRhZWQfZ+39MbL/EM2zRGXOUqes0RZ5BmG1/a1zFl0zHbrQndpXTzetY60C7rWG8v0N097tWzLVHqb/fbXSe/y7bp5/3M6XMa+zZn7detlf/11P/3hrt7160vkO6+Td1Pq+qHgWscfv0waIxeVuB7N3xlS0QRN0ARN0PRoKpqgCZqg6dEE/bdYgn4P1zWn0Xdy9F1Tv8/Zdb7RoG1zTJt437v3RS1ht/JpeHtBAAAAAADwKzufmzK3evXu3JxGC7q9oBt937v2gm7z7wyn9oKeqGgqmoqmoqloKpqKpqKpaCqaiqaiqWgquvWKnsW0fFLRr6voef/fQv9W6vOTY9vo9PCJIxtO86dU9GTm9T8Jn6bq9VOfj8BcOQpz9cjoqD45wqPL3lOY5zB9SkXLTyufwp3n6oXqKUyz041q99UDPJ9d0Gv1jwp6Oj8d9AEqOkfsSty1oE3QSCTsWS+/T246u8mXY6Vj24o8HXTd6paTkZ0GM61HbjJyz+Rmp3fZ/FdTdtbNP6ii56U35wZSr+i8vUYiG5p1Me/H5rydFv9Z6l96UNnM2pKj0W3kXjctY7LLEP5W6zhEResbspV33bX1Vrr06JxKznJ5ys/fV+R54eYSnrYO7dF5j3PZZgrl6SFjMsHxYf60Hv141qGdZQl6vhu0fJc/zmvQ5hp0OdVeg87vgveRFb2oVbQWZkn594qWcMM5N/xaRZfesgStA9OnVfT8KGhtraZEImXp7gc9BX+2y2ppxEvQ2qNzrteg3ef16McvWCanc4Y863BGz3cy8chry6xjWcmL66c5WwnZTWtMUsMuT010TGYhMgeZ841rHZVePeeJBdc6Xn31zubXNVzreMPVu//suhPXo6lorkdT0VQ0FU1FU9FUNBVNRVPRVDQVTUVT0Xe59oJu9X3vmito3veO9707VNINv+9dUwwAAAAA4K/27ljZQRAIo/ACjbdYmNn3f9iLUSNVMil+B8fzTYqUeiQEKBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+OIPl7AFlyA0oQkNQhOa0CQgNKFBaEITGoQm9GeeXHnJ4R6E7h2K5aS74Lb9FH8TPsjxx/7TtKFbjyAMnS15hPeHGbpHWUo9XhZzhvZsJZaUdJ33Wckty0IPTWLO0JEsrRcmG9HN/ExQHxu62N5BNqKtnO+rxTND98n5GGOqEe3mYwN/ZOicy/uakiz0eNuqlcfcocPyed+qEd0I/foizH7liH7q1HEs7ZQjehlXGu2pX4b7ZkW66hj2D2G6NeT0odcS6/whG9FxbgiTakDfI/S2Z9HtDKN/ZvqtR8smO7hqub5NuwXfpmrhWUfsf1eadAd4NzlUeu3Z6qITrdZ2v3NSDv4JTWgQmtCEJgGhCQ1CE5rQIDSh8bN/7xna+k/jxQQAAAAASUVORK5CYII=">
*/
-public class AuthMethodPickerActivity extends IDPBaseActivity
+public class AuthMethodPickerActivity extends AppCompatBase
implements IdpCallback, View.OnClickListener {
private static final String TAG = "AuthMethodPicker";
private static final int RC_EMAIL_FLOW = 2;
private static final int RC_ACCOUNT_LINK = 3;
+
private ArrayList mIdpProviders;
+ private EmailHintContainer mEmailHintContainer;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -149,7 +152,11 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
} else if (requestCode == RC_ACCOUNT_LINK) {
finish(resultCode, data);
} else {
- for(IdpProvider provider : mIdpProviders) {
+ if (mEmailHintContainer != null) {
+ mEmailHintContainer.onActivityResult(this, requestCode, resultCode, data);
+ }
+
+ for (IdpProvider provider : mIdpProviders) {
provider.onActivityResult(requestCode, resultCode, data);
}
}
@@ -157,7 +164,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
@Override
public void onSuccess(final IdpResponse response) {
- AuthCredential credential = createCredential(response);
+ AuthCredential credential = IdpResponse.createCredential(response);
final FirebaseAuth firebaseAuth = mActivityHelper.getFirebaseAuth();
firebaseAuth
@@ -167,7 +174,9 @@ public void onSuccess(final IdpResponse response) {
.addOnCompleteListener(new CredentialSignInHandler(
AuthMethodPickerActivity.this,
mActivityHelper,
- SmartLock.getInstance(AuthMethodPickerActivity.this, TAG),
+ SaveSmartLock.getInstance(AuthMethodPickerActivity.this,
+ mActivityHelper.getFlowParams(),
+ TAG),
RC_ACCOUNT_LINK,
response));
}
@@ -181,10 +190,10 @@ public void onFailure(Bundle extra) {
@Override
public void onClick(View view) {
if (view.getId() == R.id.email_provider) {
- Intent intent = EmailFlowUtil.createIntent(
- this,
- mActivityHelper.getFlowParams());
- startActivityForResult(intent, RC_EMAIL_FLOW);
+ mEmailHintContainer = EmailFlowUtil.startEmailFlow(this,
+ null,
+ mActivityHelper,
+ RC_EMAIL_FLOW);
}
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/idp/CredentialSignInHandler.java b/auth/src/main/java/com/firebase/ui/auth/ui/idp/CredentialSignInHandler.java
index e5a8da173..5fac8c4f8 100644
--- a/auth/src/main/java/com/firebase/ui/auth/ui/idp/CredentialSignInHandler.java
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/idp/CredentialSignInHandler.java
@@ -23,7 +23,8 @@
import com.firebase.ui.auth.ui.TaskFailureLogger;
import com.firebase.ui.auth.ui.account_link.WelcomeBackIdpPrompt;
import com.firebase.ui.auth.ui.account_link.WelcomeBackPasswordPrompt;
-import com.firebase.ui.auth.util.SmartLock;
+import com.firebase.ui.auth.util.BaseHelper;
+import com.firebase.ui.auth.util.smartlock.SaveSmartLock;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
@@ -39,19 +40,19 @@ public class CredentialSignInHandler implements OnCompleteListener {
private final static String TAG = "CredentialSignInHandler";
private AppCompatBase mActivity;
- private ActivityHelper mActivityHelper;
- private SmartLock mSmartLock;
+ private BaseHelper mHelper;
+ private SaveSmartLock mSmartLock;
private IdpResponse mResponse;
private int mAccountLinkResultCode;
public CredentialSignInHandler(
AppCompatBase activity,
- ActivityHelper activityHelper,
- SmartLock smartLock,
+ ActivityHelper helper,
+ SaveSmartLock smartLock,
int accountLinkResultCode,
IdpResponse response) {
mActivity = activity;
- mActivityHelper = activityHelper;
+ mHelper = helper;
mSmartLock = smartLock;
mResponse = response;
mAccountLinkResultCode = accountLinkResultCode;
@@ -62,14 +63,14 @@ public void onComplete(@NonNull Task task) {
if (task.isSuccessful()) {
FirebaseUser firebaseUser = task.getResult().getUser();
mSmartLock.saveCredentialsOrFinish(mActivity,
- mActivityHelper,
+ mHelper.getFlowParams(),
firebaseUser,
null /* password */,
mResponse.getProviderType());
} else {
if (task.getException() instanceof FirebaseAuthUserCollisionException) {
final String email = mResponse.getEmail();
- FirebaseAuth firebaseAuth = mActivityHelper.getFirebaseAuth();
+ FirebaseAuth firebaseAuth = mHelper.getFirebaseAuth();
firebaseAuth.fetchProvidersForEmail(email)
.addOnFailureListener(new TaskFailureLogger(
TAG, "Error fetching providers for email"))
@@ -83,7 +84,7 @@ public void onFailure(@NonNull Exception e) {
}
});
} else {
- mActivityHelper.dismissDialog();
+ mHelper.dismissDialog();
Log.e(TAG, "Unexpected exception when signing in with credential",
task.getException());
}
@@ -99,23 +100,23 @@ public StartWelcomeBackFlow(String email) {
@Override
public void onSuccess(@NonNull ProviderQueryResult result) {
- mActivityHelper.dismissDialog();
+ mHelper.dismissDialog();
String provider = result.getProviders().get(0);
if (provider.equals(EmailAuthProvider.PROVIDER_ID)) {
// Start email welcome back flow
mActivity.startActivityForResult(
WelcomeBackPasswordPrompt.createIntent(
- mActivityHelper.getApplicationContext(),
- mActivityHelper.getFlowParams(),
+ mHelper.getApplicationContext(),
+ mHelper.getFlowParams(),
mResponse
), mAccountLinkResultCode);
} else {
// Start IDP welcome back flow
mActivity.startActivityForResult(
WelcomeBackIdpPrompt.createIntent(
- mActivityHelper.getApplicationContext(),
- mActivityHelper.getFlowParams(),
+ mHelper.getApplicationContext(),
+ mHelper.getFlowParams(),
result.getProviders().get(0),
mResponse,
mEmail
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/idp/IDPBaseActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/idp/IDPBaseActivity.java
deleted file mode 100644
index fee155e1d..000000000
--- a/auth/src/main/java/com/firebase/ui/auth/ui/idp/IDPBaseActivity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.firebase.ui.auth.ui.idp;
-
-import com.firebase.ui.auth.provider.FacebookProvider;
-import com.firebase.ui.auth.provider.GoogleProvider;
-import com.firebase.ui.auth.IdpResponse;
-import com.firebase.ui.auth.provider.TwitterProvider;
-import com.firebase.ui.auth.ui.AppCompatBase;
-import com.google.firebase.auth.AuthCredential;
-import com.google.firebase.auth.FacebookAuthProvider;
-import com.google.firebase.auth.GoogleAuthProvider;
-import com.google.firebase.auth.TwitterAuthProvider;
-
-public class IDPBaseActivity extends AppCompatBase {
- protected AuthCredential createCredential(IdpResponse idpSignInResponse) {
- if (idpSignInResponse.getProviderType().equalsIgnoreCase(FacebookAuthProvider.PROVIDER_ID)) {
- return FacebookProvider.createAuthCredential(idpSignInResponse);
- } else if (idpSignInResponse.getProviderType().equalsIgnoreCase(GoogleAuthProvider
- .PROVIDER_ID)) {
- return GoogleProvider.createAuthCredential(idpSignInResponse);
- } else if (idpSignInResponse
- .getProviderType()
- .equalsIgnoreCase(TwitterAuthProvider.PROVIDER_ID)) {
- return TwitterProvider.createAuthCredential(idpSignInResponse);
- }
- return null;
- }
-}
diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/idp/IdpSignInContainerActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/idp/IdpSignInContainerActivity.java
index a6c5bffa6..0e5697a30 100644
--- a/auth/src/main/java/com/firebase/ui/auth/ui/idp/IdpSignInContainerActivity.java
+++ b/auth/src/main/java/com/firebase/ui/auth/ui/idp/IdpSignInContainerActivity.java
@@ -17,6 +17,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+
import com.firebase.ui.auth.AuthUI.IdpConfig;
import com.firebase.ui.auth.IdpResponse;
import com.firebase.ui.auth.provider.FacebookProvider;
@@ -25,19 +26,20 @@
import com.firebase.ui.auth.provider.IdpProvider.IdpCallback;
import com.firebase.ui.auth.provider.TwitterProvider;
import com.firebase.ui.auth.ui.ActivityHelper;
+import com.firebase.ui.auth.ui.AppCompatBase;
import com.firebase.ui.auth.ui.ExtraConstants;
import com.firebase.ui.auth.ui.FlowParameters;
import com.firebase.ui.auth.ui.TaskFailureLogger;
-import com.firebase.ui.auth.util.SmartLock;
+import com.firebase.ui.auth.util.smartlock.SaveSmartLock;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.FirebaseAuth;
-import com.google.firebase.auth.TwitterAuthProvider;
import com.google.firebase.auth.GoogleAuthProvider;
+import com.google.firebase.auth.TwitterAuthProvider;
-public class IdpSignInContainerActivity extends IDPBaseActivity implements IdpCallback {
+public class IdpSignInContainerActivity extends AppCompatBase implements IdpCallback {
private static final String TAG = "IDPSignInContainer";
private static final int RC_WELCOME_BACK_IDP = 4;
@@ -78,7 +80,7 @@ protected void onCreate(Bundle savedInstanceState) {
public void onSuccess(final IdpResponse response) {
Intent data = new Intent();
data.putExtra(ExtraConstants.EXTRA_IDP_RESPONSE, response);
- AuthCredential credential = createCredential(response);
+ AuthCredential credential = IdpResponse.createCredential(response);
final FirebaseAuth firebaseAuth = mActivityHelper.getFirebaseAuth();
Task authResultTask = firebaseAuth.signInWithCredential(credential);
authResultTask
@@ -87,7 +89,9 @@ public void onSuccess(final IdpResponse response) {
.addOnCompleteListener(new CredentialSignInHandler(
IdpSignInContainerActivity.this,
mActivityHelper,
- SmartLock.getInstance(IdpSignInContainerActivity.this, TAG),
+ SaveSmartLock.getInstance(IdpSignInContainerActivity.this,
+ mActivityHelper.getFlowParams(),
+ TAG),
RC_WELCOME_BACK_IDP,
response));
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/util/BaseHelper.java b/auth/src/main/java/com/firebase/ui/auth/util/BaseHelper.java
new file mode 100644
index 000000000..3683ed7d1
--- /dev/null
+++ b/auth/src/main/java/com/firebase/ui/auth/util/BaseHelper.java
@@ -0,0 +1,92 @@
+package com.firebase.ui.auth.util;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
+
+import com.firebase.ui.auth.ui.ExtraConstants;
+import com.firebase.ui.auth.ui.FlowParameters;
+import com.google.android.gms.auth.api.Auth;
+import com.google.android.gms.auth.api.credentials.CredentialsApi;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+
+import static com.firebase.ui.auth.util.Preconditions.checkNotNull;
+
+public abstract class BaseHelper {
+ private ProgressDialog mProgressDialog;
+ private Context mContext;
+ private final FlowParameters mFlowParams;
+
+ public BaseHelper(Context context, FlowParameters parameters) {
+ mContext = context;
+ mFlowParams = parameters;
+ }
+
+ public void configureTheme() {
+ mContext.setTheme(mFlowParams.themeId);
+ }
+
+ public FlowParameters getFlowParams() {
+ return mFlowParams;
+ }
+
+ public void showLoadingDialog(String message) {
+ dismissDialog();
+ mProgressDialog = ProgressDialog.show(mContext, "", message, true);
+ }
+
+ public void showLoadingDialog(@StringRes int stringResource) {
+ showLoadingDialog(mContext.getString(stringResource));
+ }
+
+ public void dismissDialog() {
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
+ }
+ }
+
+ public abstract void startActivityForResult(Intent intent, int requestCode);
+
+ public abstract void finish(int resultCode, Intent intent);
+
+ public Context getApplicationContext() {
+ return mContext.getApplicationContext();
+ }
+
+ public String getAppName() {
+ return mFlowParams.appName;
+ }
+
+ public FirebaseApp getFirebaseApp() {
+ return FirebaseApp.getInstance(mFlowParams.appName);
+ }
+
+ public FirebaseAuth getFirebaseAuth() {
+ return FirebaseAuth.getInstance(getFirebaseApp());
+ }
+
+ public CredentialsApi getCredentialsApi() {
+ return Auth.CredentialsApi;
+ }
+
+ public FirebaseUser getCurrentUser() {
+ return getFirebaseAuth().getCurrentUser();
+ }
+
+ public static Intent createBaseIntent(
+ @NonNull Context context,
+ @NonNull Class extends Activity> target,
+ @NonNull FlowParameters flowParams) {
+ return new Intent(
+ checkNotNull(context, "context cannot be null"),
+ checkNotNull(target, "target activity cannot be null"))
+ .putExtra(ExtraConstants.EXTRA_FLOW_PARAMS,
+ checkNotNull(flowParams, "flowParams cannot be null"));
+ }
+}
diff --git a/auth/src/main/java/com/firebase/ui/auth/util/CredentialsAPI.java b/auth/src/main/java/com/firebase/ui/auth/util/CredentialsAPI.java
deleted file mode 100644
index 7f514c958..000000000
--- a/auth/src/main/java/com/firebase/ui/auth/util/CredentialsAPI.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.firebase.ui.auth.util;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.IntentSender;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.google.android.gms.auth.api.Auth;
-import com.google.android.gms.auth.api.credentials.Credential;
-import com.google.android.gms.auth.api.credentials.CredentialRequest;
-import com.google.android.gms.auth.api.credentials.CredentialRequestResult;
-import com.google.android.gms.auth.api.credentials.IdentityProviders;
-import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
-import com.google.android.gms.common.ConnectionResult;
-import com.google.android.gms.common.api.CommonStatusCodes;
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.ResultCallback;
-import com.google.android.gms.common.api.Status;
-
-public class CredentialsAPI implements
- GoogleApiClient.ConnectionCallbacks,
- GoogleApiClient.OnConnectionFailedListener {
- private static final int RC_CREDENTIALS_READ = 2;
- private static final String TAG = "CredentialsAPI";
-
- private GoogleApiClient mGoogleApiClient;
- private boolean mAutoSignInAvailable;
- private boolean mSignInResolutionNeeded;
- private Activity mActivity;
- private CredentialRequestResult mCredentialRequestResult;
- private ProgressDialog mProgressDialog;
- private Credential mCredential;
- private final CallbackInterface mCallback;
- private PlayServicesHelper mPlayServicesHelper;
-
- public interface CallbackInterface {
- void onAsyncTaskFinished();
- }
-
- public CredentialsAPI(Activity activity, CallbackInterface callback) {
- mAutoSignInAvailable = false;
- mSignInResolutionNeeded = false;
- mActivity = activity;
- mCallback = callback;
- mPlayServicesHelper = PlayServicesHelper.getInstance(mActivity);
-
- initGoogleApiClient(null);
- requestCredentials(true /* shouldResolve */, false /* onlyPasswords */);
- }
-
- public boolean isPlayServicesAvailable() {
- return mPlayServicesHelper.isPlayServicesAvailable();
- }
-
- public boolean isCredentialsAvailable() {
- // TODO: (serikb) find the way to check if Credentials is available on top of play services
- return true;
- }
-
- public boolean isAutoSignInAvailable() {
- return mAutoSignInAvailable;
- }
-
- public boolean isSignInResolutionNeeded() {
- return mSignInResolutionNeeded;
- }
-
- public void resolveSignIn() {
- mSignInResolutionNeeded = false;
- }
-
- public void resolveSavedEmails(Activity activity) {
- if (mCredentialRequestResult == null || mCredentialRequestResult.getStatus() == null) {
- return;
- }
- Status status = mCredentialRequestResult.getStatus();
- if (status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED) {
- try {
- status.startResolutionForResult(activity, RC_CREDENTIALS_READ);
- } catch (IntentSender.SendIntentException e) {
- Log.e(TAG, "Failed to send Credentials intent.", e);
- }
- }
- }
-
- public Credential getCredential() {
- return mCredential;
- }
-
- public String getEmailFromCredential() {
- if (mCredential == null) {
- return null;
- }
- return mCredential.getId();
- }
-
- public String getAccountTypeFromCredential() {
- if (mCredential == null) {
- return null;
- }
- return mCredential.getAccountType();
- }
-
- public String getPasswordFromCredential() {
- if (mCredential == null) {
- return null;
- }
- return mCredential.getPassword();
- }
-
- @Override
- public void onConnected(@Nullable Bundle bundle) {}
-
- @Override
- public void onConnectionSuspended(int cause) {}
-
- private void initGoogleApiClient(String accountName) {
- GoogleSignInOptions.Builder gsoBuilder = new GoogleSignInOptions
- .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
- .requestEmail();
-
- if (accountName != null) {
- gsoBuilder.setAccountName(accountName);
- }
-
- GoogleApiClient.Builder builder = new GoogleApiClient.Builder(mActivity)
- .addConnectionCallbacks(this)
- .addApi(Auth.CREDENTIALS_API)
- .addApi(Auth.GOOGLE_SIGN_IN_API, gsoBuilder.build());
-
- mGoogleApiClient = builder.build();
- }
-
- public void googleSilentSignIn() {
- // Try silent sign-in with Google Sign In API
- Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
- }
-
- public void handleCredential(Credential credential) {
- mCredential = credential;
-
- if (IdentityProviders.GOOGLE.equals(credential.getAccountType())) {
- // Google account, rebuild GoogleApiClient to set account name and then try
- initGoogleApiClient(credential.getId());
- googleSilentSignIn();
- } else {
- // Email/password account
- String status = String.format("Signed in as %s", credential.getId());
- Log.d(TAG, status);
- }
- }
-
- public void requestCredentials(final boolean shouldResolve, boolean onlyPasswords) {
- if (!mPlayServicesHelper.isPlayServicesAvailable()) {
- // TODO(samstern): it would probably be better to not actually call the method
- // in this case.
- return;
- }
-
- CredentialRequest.Builder crBuilder = new CredentialRequest.Builder()
- .setPasswordLoginSupported(true);
-
- if (!onlyPasswords) {
- crBuilder.setAccountTypes(IdentityProviders.GOOGLE);
- }
-
- showProgress();
- Auth.CredentialsApi.request(mGoogleApiClient, crBuilder.build())
- .setResultCallback(
- new ResultCallback() {
- @Override
- public void onResult(CredentialRequestResult credentialRequestResult) {
- mCredentialRequestResult = credentialRequestResult;
- Status status = credentialRequestResult.getStatus();
-
- if (status.isSuccess()) {
- // Auto sign-in success
- mAutoSignInAvailable = true;
- handleCredential(credentialRequestResult.getCredential());
- } else if (status.getStatusCode() ==
- CommonStatusCodes.RESOLUTION_REQUIRED && shouldResolve) {
- mSignInResolutionNeeded = true;
- // Getting credential needs to show some UI, start resolution
- }
- hideProgress();
- mCallback.onAsyncTaskFinished();
- }
- });
- }
-
- private void showProgress() {
- if (mProgressDialog == null || !mProgressDialog.isShowing()) {
- mProgressDialog = new ProgressDialog(mActivity);
- mProgressDialog.setIndeterminate(true);
- mProgressDialog.setMessage(
- mActivity.getString(com.firebase.ui.auth.R.string.progress_dialog_loading));
- }
- mProgressDialog.show();
- }
-
- private void hideProgress() {
- if (mProgressDialog != null && mProgressDialog.isShowing()) {
- mProgressDialog.dismiss();
- }
- }
-
- public void onStart() {
- if (mGoogleApiClient != null) {
- mGoogleApiClient.connect();
- }
- }
-
- public void onStop() {
- if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
- mGoogleApiClient.disconnect();;
- }
-
- hideProgress();
- }
-
- @Override
- public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
- Log.w(TAG, "onConnectionFailed:" + connectionResult);
- Toast.makeText(mActivity, "An error has occurred.", Toast.LENGTH_SHORT).show();
- }
-
- public boolean isGoogleApiClient() {
- return mGoogleApiClient != null;
- }
-
- public GoogleApiClient getGoogleApiClient() {
- return mGoogleApiClient;
- }
-
- public void signOut() {
- disableAutoSignIn();
- Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
- new ResultCallback() {
- @Override
- public void onResult(Status status) {
- mCallback.onAsyncTaskFinished();
- }
- });
- }
-
- public void disableAutoSignIn() {
- Auth.CredentialsApi.disableAutoSignIn(mGoogleApiClient);
- }
-}
diff --git a/auth/src/main/java/com/firebase/ui/auth/util/EmailFlowUtil.java b/auth/src/main/java/com/firebase/ui/auth/util/EmailFlowUtil.java
index d0db5c591..71e248d49 100644
--- a/auth/src/main/java/com/firebase/ui/auth/util/EmailFlowUtil.java
+++ b/auth/src/main/java/com/firebase/ui/auth/util/EmailFlowUtil.java
@@ -1,27 +1,40 @@
package com.firebase.ui.auth.util;
-import android.content.Context;
-import android.content.Intent;
+import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
-import com.firebase.ui.auth.ui.FlowParameters;
-import com.firebase.ui.auth.ui.email.EmailHintContainerActivity;
import com.firebase.ui.auth.ui.email.SignInNoPasswordActivity;
+import com.firebase.ui.auth.util.smartlock.SignInDelegate;
/**
* Helper class to kick off the Email/Password sign-in flow.
*/
public class EmailFlowUtil {
-
/**
- * Return an intent for either {@link EmailHintContainerActivity} or
+ * Return an intent for either {@link EmailHintContainer} or
* {@link SignInNoPasswordActivity} depending on if SmartLock is enabled.
*/
- public static Intent createIntent(Context context, FlowParameters parameters) {
- if (parameters.smartLockEnabled) {
- return EmailHintContainerActivity.createIntent(context, parameters);
+ public static EmailHintContainer startEmailFlow(FragmentActivity activity,
+ @Nullable SignInDelegate signInDelegate,
+ BaseHelper helper,
+ int requestCode) {
+ if (helper.getFlowParams().smartLockEnabled) {
+ if (signInDelegate != null) {
+ return new EmailHintContainer(helper).trySignInWithEmailAndPassword(signInDelegate);
+ } else {
+ return new EmailHintContainer(helper).trySignInWithEmailAndPassword(activity);
+ }
} else {
- return SignInNoPasswordActivity.createIntent(context, parameters, null);
+ if (signInDelegate != null) {
+ signInDelegate.startActivityForResult(
+ SignInNoPasswordActivity.createIntent(signInDelegate.getContext(), helper.getFlowParams(), null),
+ requestCode);
+ } else {
+ activity.startActivityForResult(
+ SignInNoPasswordActivity.createIntent(activity, helper.getFlowParams(), null),
+ requestCode);
+ }
}
+ return null;
}
-
}
diff --git a/auth/src/main/java/com/firebase/ui/auth/util/EmailHintContainer.java b/auth/src/main/java/com/firebase/ui/auth/util/EmailHintContainer.java
new file mode 100644
index 000000000..121703f02
--- /dev/null
+++ b/auth/src/main/java/com/firebase/ui/auth/util/EmailHintContainer.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.firebase.ui.auth.util;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.util.Log;
+
+import com.firebase.ui.auth.ui.AcquireEmailHelper;
+import com.firebase.ui.auth.ui.email.SignInNoPasswordActivity;
+import com.google.android.gms.auth.api.credentials.Credential;
+
+public class EmailHintContainer {
+ private static final int RC_HINT = 13;
+ private AcquireEmailHelper mAcquireEmailHelper;
+ private BaseHelper mHelper;
+
+ public EmailHintContainer(BaseHelper helper) {
+ mHelper = helper;
+ }
+
+ public void onActivityResult(Fragment fragment, int requestCode, int resultCode, Intent data) {
+ if (requestCode == RC_HINT && data != null) {
+ Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
+ if (credential == null) {
+ // If the hint picker is cancelled show the SignInNoPasswordActivity
+ fragment.startActivityForResult(
+ SignInNoPasswordActivity.createIntent(
+ fragment.getContext(),
+ mHelper.getFlowParams(),
+ null),
+ AcquireEmailHelper.RC_SIGN_IN);
+ return;
+ }
+ mAcquireEmailHelper.checkAccountExists(credential.getId());
+ } else {
+ mAcquireEmailHelper.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
+ if (requestCode == RC_HINT && data != null) {
+ Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
+ if (credential == null) {
+ // If the hint picker is cancelled show the SignInNoPasswordActivity
+ activity.startActivityForResult(
+ SignInNoPasswordActivity.createIntent(
+ activity,
+ mHelper.getFlowParams(),
+ null),
+ AcquireEmailHelper.RC_SIGN_IN);
+ return;
+ }
+ mAcquireEmailHelper.checkAccountExists(credential.getId());
+ } else {
+ mAcquireEmailHelper.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ public EmailHintContainer trySignInWithEmailAndPassword(Fragment fragment) {
+ mAcquireEmailHelper = new AcquireEmailHelper(mHelper);
+ FirebaseAuthWrapper apiWrapper =
+ FirebaseAuthWrapperFactory.getFirebaseAuthWrapper(mHelper.getAppName());
+
+ PendingIntent hintIntent = apiWrapper.getEmailHintIntent(fragment.getActivity());
+ if (hintIntent != null) {
+ try {
+ fragment.startIntentSenderForResult(hintIntent.getIntentSender(),
+ RC_HINT,
+ null,
+ 0,
+ 0,
+ 0,
+ null);
+ return this;
+ } catch (IntentSender.SendIntentException e) {
+ Log.e("EmailHintContainer", "Failed to send Credentials intent.", e);
+ }
+ }
+ mHelper.finish(Activity.RESULT_CANCELED, new Intent());
+ return null;
+ }
+
+ public EmailHintContainer trySignInWithEmailAndPassword(FragmentActivity activity) {
+ mAcquireEmailHelper = new AcquireEmailHelper(mHelper);
+ FirebaseAuthWrapper apiWrapper =
+ FirebaseAuthWrapperFactory.getFirebaseAuthWrapper(mHelper.getAppName());
+
+ PendingIntent hintIntent = apiWrapper.getEmailHintIntent(activity);
+ if (hintIntent != null) {
+ try {
+ activity.startIntentSenderForResult(hintIntent.getIntentSender(),
+ RC_HINT,
+ null,
+ 0,
+ 0,
+ 0,
+ null);
+ return this;
+ } catch (IntentSender.SendIntentException e) {
+ Log.e("EmailHintContainer", "Failed to send Credentials intent.", e);
+ }
+ }
+ mHelper.finish(Activity.RESULT_CANCELED, new Intent());
+ return null;
+ }
+}
diff --git a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperImpl.java b/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperImpl.java
index df8e06953..b7cb26178 100644
--- a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperImpl.java
+++ b/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperImpl.java
@@ -14,7 +14,6 @@
package com.firebase.ui.auth.util;
-import android.app.Fragment;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Bundle;
diff --git a/auth/src/main/java/com/firebase/ui/auth/util/SmartLock.java b/auth/src/main/java/com/firebase/ui/auth/util/smartlock/SaveSmartLock.java
similarity index 68%
rename from auth/src/main/java/com/firebase/ui/auth/util/SmartLock.java
rename to auth/src/main/java/com/firebase/ui/auth/util/smartlock/SaveSmartLock.java
index 864e2928f..2ef8e8a5a 100644
--- a/auth/src/main/java/com/firebase/ui/auth/util/SmartLock.java
+++ b/auth/src/main/java/com/firebase/ui/auth/util/smartlock/SaveSmartLock.java
@@ -12,9 +12,10 @@
* limitations under the License.
*/
-package com.firebase.ui.auth.util;
+package com.firebase.ui.auth.util.smartlock;
import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.net.Uri;
@@ -22,50 +23,46 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
+import android.text.TextUtils;
import android.util.Log;
+import android.widget.Toast;
import com.firebase.ui.auth.BuildConfig;
-import com.firebase.ui.auth.ui.ActivityHelper;
import com.firebase.ui.auth.ui.AppCompatBase;
+import com.firebase.ui.auth.ui.ExtraConstants;
+import com.firebase.ui.auth.ui.FlowParameters;
+import com.firebase.ui.auth.util.FirebaseAuthWrapperFactory;
+import com.firebase.ui.auth.util.PlayServicesHelper;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.credentials.Credential;
-import com.google.android.gms.auth.api.credentials.IdentityProviders;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
-import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.FirebaseUser;
-import com.google.firebase.auth.GoogleAuthProvider;
-import com.google.firebase.auth.TwitterAuthProvider;
import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_FIRST_USER;
import static android.app.Activity.RESULT_OK;
-public class SmartLock extends Fragment
- implements GoogleApiClient.ConnectionCallbacks,
- GoogleApiClient.OnConnectionFailedListener,
- ResultCallback {
- private static final String TAG = "CredentialsSaveBase";
+public class SaveSmartLock extends SmartLock {
+ private static final String TAG = "SaveSmartLock";
private static final int RC_SAVE = 100;
private static final int RC_UPDATE_SERVICE = 28;
- private AppCompatBase mActivity;
- private ActivityHelper mActivityHelper;
+ private GoogleApiClient mGoogleApiClient;
private String mName;
private String mEmail;
private String mPassword;
private String mProvider;
private String mProfilePictureUri;
- private GoogleApiClient mCredentialsApiClient;
@Override
- public void onConnected(@Nullable Bundle bundle) {
- if (mEmail == null) {
+ public void onConnected(Bundle bundle) {
+ if (TextUtils.isEmpty(mEmail)) {
Log.e(TAG, "Unable to save null credential!");
finish(RESULT_CANCELED);
return;
@@ -76,25 +73,15 @@ public void onConnected(@Nullable Bundle bundle) {
if (mPassword == null) {
// only password OR provider can be set, not both
if (mProvider != null) {
- String translatedProvider = null;
- // translate the google.com/facebook.com provider strings into full URIs
- switch (mProvider) {
- case GoogleAuthProvider.PROVIDER_ID:
- translatedProvider = IdentityProviders.GOOGLE;
- break;
- case FacebookAuthProvider.PROVIDER_ID:
- translatedProvider = IdentityProviders.FACEBOOK;
- break;
- case TwitterAuthProvider.PROVIDER_ID:
- translatedProvider = IdentityProviders.TWITTER;
- break;
- default:
- Log.e(TAG, "Unable to save null credential!");
- finish(RESULT_CANCELED);
- return;
- }
+ String translatedProvider = SmartLock.providerIdToAccountType(mProvider);
- builder.setAccountType(translatedProvider);
+ if (translatedProvider != null) {
+ builder.setAccountType(translatedProvider);
+ } else {
+ Log.e(TAG, "Unable to save null credential!");
+ finish(RESULT_CANCELED);
+ return;
+ }
}
}
@@ -106,8 +93,8 @@ public void onConnected(@Nullable Bundle bundle) {
builder.setProfilePictureUri(Uri.parse(mProfilePictureUri));
}
- mActivityHelper.getCredentialsApi()
- .save(mCredentialsApiClient, builder.build())
+ mHelper.getCredentialsApi()
+ .save(mGoogleApiClient, builder.build())
.setResultCallback(this);
}
@@ -124,10 +111,12 @@ public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.d(TAG, "connection failed with " + connectionResult.getErrorMessage()
+ " and code: " + connectionResult.getErrorCode());
}
+ Toast.makeText(getActivity(), "An error has occurred.", Toast.LENGTH_SHORT).show();
+
PendingIntent resolution =
GoogleApiAvailability
.getInstance()
- .getErrorResolutionPendingIntent(mActivity,
+ .getErrorResolutionPendingIntent(getActivity(),
connectionResult.getErrorCode(),
RC_UPDATE_SERVICE);
try {
@@ -139,12 +128,11 @@ public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
0,
null);
} catch (IntentSender.SendIntentException e) {
- e.printStackTrace();
+ Log.e(TAG, "STATUS: Failed to send resolution.", e);
finish(RESULT_CANCELED);
}
}
-
@Override
public void onResult(@NonNull Status status) {
if (status.isSuccess()) {
@@ -190,8 +178,8 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Credential credential = new Credential.Builder(mEmail).setPassword(mPassword)
.build();
- mActivityHelper.getCredentialsApi()
- .save(mCredentialsApiClient, credential)
+ mHelper.getCredentialsApi()
+ .save(mGoogleApiClient, credential)
.setResultCallback(this);
} else {
Log.e(TAG, "SAVE: Canceled by user");
@@ -201,25 +189,33 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
private void finish(int resultCode) {
- mActivity.finish(RESULT_OK, mActivity.getIntent());
+ if (mGoogleApiClient != null) {
+ mGoogleApiClient.disconnect();
+ }
+ ((AppCompatBase) getActivity()).finish(RESULT_OK, getActivity().getIntent());
}
/**
* If SmartLock is enabled and Google Play Services is available, save the credentials.
* Otherwise, finish the calling Activity with RESULT_OK.
*
- * @param activity the calling Activity.
* @param firebaseUser Firebase user to save in Credential.
* @param password (optional) password for email credential.
* @param provider (optional) provider string for provider credential.
*/
- public void saveCredentialsOrFinish(AppCompatBase activity,
- ActivityHelper helper,
+ public void saveCredentialsOrFinish(Context context,
+ FlowParameters parameters,
FirebaseUser firebaseUser,
@Nullable String password,
@Nullable String provider) {
- mActivity = activity;
- mActivityHelper = helper;
+ if (!parameters.smartLockEnabled
+ || !PlayServicesHelper.getInstance(getActivity()).isPlayServicesAvailable()
+ || !FirebaseAuthWrapperFactory.getFirebaseAuthWrapper(parameters.appName)
+ .isPlayServicesAvailable(getActivity())) {
+ finish(RESULT_CANCELED);
+ return;
+ }
+
mName = firebaseUser.getDisplayName();
mEmail = firebaseUser.getEmail();
mPassword = password;
@@ -227,45 +223,33 @@ public void saveCredentialsOrFinish(AppCompatBase activity,
mProfilePictureUri = firebaseUser.getPhotoUrl() != null ? firebaseUser.getPhotoUrl()
.toString() : null;
- // If SmartLock is disabled, finish the Activity
- if (!helper.getFlowParams().smartLockEnabled) {
- finish(RESULT_CANCELED);
- return;
- }
-
- // If Play Services is not available, finish the Activity
- if (!PlayServicesHelper.getInstance(activity).isPlayServicesAvailable()) {
- finish(RESULT_CANCELED);
- return;
- }
-
- if (!FirebaseAuthWrapperFactory
- .getFirebaseAuthWrapper(helper.getFlowParams().appName)
- .isPlayServicesAvailable(activity)) {
- finish(RESULT_CANCELED);
- return;
- }
-
- mCredentialsApiClient = new GoogleApiClient.Builder(activity)
+ mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Auth.CREDENTIALS_API)
- .enableAutoManage(activity, this)
.build();
+ mGoogleApiClient.connect();
}
- public static SmartLock getInstance(AppCompatBase activity, String tag) {
- SmartLock result;
+ public static SaveSmartLock getInstance(FragmentActivity activity,
+ FlowParameters parameters,
+ String tag) {
+ SaveSmartLock result;
FragmentManager fm = activity.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = fm.findFragmentByTag(tag);
- if (fragment == null || !(fragment instanceof SmartLock)) {
- result = new SmartLock();
+ if (fragment == null || !(fragment instanceof SaveSmartLock)) {
+ result = new SaveSmartLock();
+
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(ExtraConstants.EXTRA_FLOW_PARAMS, parameters);
+ result.setArguments(bundle);
+
ft.add(result, tag).disallowAddToBackStack().commit();
} else {
- result = (SmartLock) fragment;
+ result = (SaveSmartLock) fragment;
}
return result;
diff --git a/auth/src/main/java/com/firebase/ui/auth/util/smartlock/SignInDelegate.java b/auth/src/main/java/com/firebase/ui/auth/util/smartlock/SignInDelegate.java
new file mode 100644
index 000000000..e1d4ef0f6
--- /dev/null
+++ b/auth/src/main/java/com/firebase/ui/auth/util/smartlock/SignInDelegate.java
@@ -0,0 +1,434 @@
+package com.firebase.ui.auth.util.smartlock;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.net.ConnectivityManager;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.firebase.ui.auth.AuthUI;
+import com.firebase.ui.auth.BuildConfig;
+import com.firebase.ui.auth.R;
+import com.firebase.ui.auth.ui.ExtraConstants;
+import com.firebase.ui.auth.ui.FlowParameters;
+import com.firebase.ui.auth.ui.TaskFailureLogger;
+import com.firebase.ui.auth.ui.email.SignInNoPasswordActivity;
+import com.firebase.ui.auth.ui.idp.AuthMethodPickerActivity;
+import com.firebase.ui.auth.ui.idp.IdpSignInContainerActivity;
+import com.firebase.ui.auth.util.CredentialsApiHelper;
+import com.firebase.ui.auth.util.EmailFlowUtil;
+import com.firebase.ui.auth.util.EmailHintContainer;
+import com.firebase.ui.auth.util.FirebaseAuthWrapperFactory;
+import com.firebase.ui.auth.util.PlayServicesHelper;
+import com.google.android.gms.auth.api.Auth;
+import com.google.android.gms.auth.api.credentials.Credential;
+import com.google.android.gms.auth.api.credentials.CredentialRequest;
+import com.google.android.gms.auth.api.credentials.CredentialRequestResult;
+import com.google.android.gms.auth.api.credentials.IdentityProviders;
+import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
+import com.google.android.gms.common.api.CommonStatusCodes;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.api.Status;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.android.gms.tasks.Task;
+import com.google.firebase.auth.AuthResult;
+import com.google.firebase.auth.EmailAuthProvider;
+import com.google.firebase.auth.FacebookAuthProvider;
+import com.google.firebase.auth.FirebaseAuthInvalidUserException;
+import com.google.firebase.auth.GoogleAuthProvider;
+import com.google.firebase.auth.TwitterAuthProvider;
+
+import java.util.List;
+
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
+import static com.firebase.ui.auth.ui.ResultCodes.RESULT_NO_NETWORK;
+
+/**
+ * Attempts to acquire a credential from Smart Lock for Passwords to sign in
+ * an existing account. If this succeeds, an attempt is made to sign the user in
+ * with this credential. If it does not, the
+ * {@link AuthMethodPickerActivity authentication method picker activity}
+ * is started, unless only email is supported, in which case the
+ * {@link SignInNoPasswordActivity email sign-in flow}
+ * is started.
+ */
+public class SignInDelegate extends SmartLock {
+ private static final String TAG = "SignInDelegate";
+ private static final int RC_CREDENTIALS_READ = 2;
+ private static final int RC_IDP_SIGNIN = 3;
+ private static final int RC_AUTH_METHOD_PICKER = 4;
+ private static final int RC_EMAIL_FLOW = 5;
+ private static final int RC_PLAY_SERVICES = 6;
+
+ private GoogleApiClient mGoogleApiClient;
+ private Credential mCredential;
+ private EmailHintContainer mEmailHintContainer;
+
+ @Override
+ public void onCreate(Bundle savedInstance) {
+ super.onCreate(savedInstance);
+
+ if (!hasNetworkConnection()) {
+ Log.d(TAG, "No network connection");
+
+ finish(RESULT_NO_NETWORK, new Intent());
+ return;
+ }
+
+ // Make Google Play Services available at the correct version, if possible
+ boolean madeAvailable =
+ PlayServicesHelper
+ .getInstance(getActivity())
+ .makePlayServicesAvailable(getActivity(), RC_PLAY_SERVICES,
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialogInterface) {
+ Log.w(TAG,
+ "playServices:dialog.onCancel()");
+ finish(RESULT_CANCELED, new Intent());
+ }
+ });
+
+ if (!madeAvailable
+ || !PlayServicesHelper.getInstance(getActivity()).isPlayServicesAvailable()
+ || !FirebaseAuthWrapperFactory.getFirebaseAuthWrapper(mHelper.getAppName())
+ .isPlayServicesAvailable(getActivity())) {
+ Log.w(TAG, "playServices: could not make available.");
+ finish(RESULT_CANCELED, new Intent());
+ return;
+ }
+
+ if (mHelper.getFlowParams().smartLockEnabled) {
+ mHelper.showLoadingDialog(R.string.progress_dialog_loading);
+ initGoogleApiClient(null);
+ mHelper.getCredentialsApi()
+ .request(mGoogleApiClient,
+ new CredentialRequest.Builder()
+ .setPasswordLoginSupported(true)
+ .setAccountTypes(IdentityProviders.GOOGLE,
+ IdentityProviders.FACEBOOK,
+ IdentityProviders.TWITTER)
+ .build())
+ .setResultCallback(this);
+ } else {
+ startAuthMethodChoice();
+ }
+ }
+
+ @Override
+ public void onResult(@NonNull CredentialRequestResult result) {
+ Status status = result.getStatus();
+
+ if (status.isSuccess()) {
+ // Auto sign-in success
+ handleCredential(result.getCredential());
+ String email = getEmailFromCredential();
+ String password = getPasswordFromCredential();
+
+ if (TextUtils.isEmpty(password)) {
+ // log in with id/provider
+ redirectToIdpSignIn(email, getAccountTypeFromCredential());
+ } else {
+ // Sign in with the email/password retrieved from SmartLock
+ signInWithEmailAndPassword(email, password);
+ }
+ } else if (status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED) {
+ mHelper.dismissDialog(); // TODO: 10/22/2016
+ // resolve saved emails
+ try {
+ startIntentSenderForResult(status.getResolution().getIntentSender(),
+ RC_CREDENTIALS_READ,
+ null,
+ 0,
+ 0,
+ 0,
+ null);
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(TAG, "Failed to send Credentials intent.", e);
+ }
+ }
+ }
+
+ @Override
+ public void onConnected(@Nullable Bundle bundle) {
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (BuildConfig.DEBUG) {
+ Log.d(TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data);
+ }
+
+ switch (requestCode) {
+ case RC_CREDENTIALS_READ:
+ if (resultCode == RESULT_OK) {
+ // credential selected from SmartLock, log in with that credential
+ Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
+ handleCredential(credential);
+
+ String email = getEmailFromCredential();
+ String password = getPasswordFromCredential();
+ if (email != null) {
+ if (password == null || password.isEmpty()) {
+ // identifier/provider combination
+ redirectToIdpSignIn(email, getAccountTypeFromCredential());
+ } else {
+ // email/password combination
+ signInWithEmailAndPassword(email, password);
+ }
+ }
+ } else {
+ // Smart lock selector cancelled, go to the AuthMethodPicker screen
+ startAuthMethodChoice();
+ }
+ break;
+ case RC_IDP_SIGNIN:
+ case RC_AUTH_METHOD_PICKER:
+ case RC_EMAIL_FLOW:
+ finish(resultCode, data);
+ break;
+ case RC_PLAY_SERVICES:
+ if (resultCode != RESULT_OK) {
+ finish(resultCode, data);
+ }
+ break;
+ default:
+ if (mEmailHintContainer != null) {
+ mEmailHintContainer.onActivityResult(this, requestCode, resultCode, data);
+ }
+ break;
+ }
+ }
+
+ private String getEmailFromCredential() {
+ if (mCredential == null) {
+ return null;
+ }
+ return mCredential.getId();
+ }
+
+ private String getAccountTypeFromCredential() {
+ if (mCredential == null) {
+ return null;
+ }
+ return mCredential.getAccountType();
+ }
+
+ private String getPasswordFromCredential() {
+ if (mCredential == null) {
+ return null;
+ }
+ return mCredential.getPassword();
+ }
+
+ private void handleCredential(Credential credential) {
+ mCredential = credential;
+
+ if (IdentityProviders.GOOGLE.equals(credential.getAccountType())) {
+ // Google account, rebuild GoogleApiClient to set account name and then try
+ initGoogleApiClient(credential.getId());
+ // Try silent sign-in with Google Sign In API
+ Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
+ } else {
+ // Email/password account
+ String status = String.format("Signed in as %s", credential.getId());
+ Log.d(TAG, status);
+ }
+ }
+
+ private void initGoogleApiClient(String accountName) {
+ GoogleSignInOptions.Builder gsoBuilder = new GoogleSignInOptions
+ .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
+ .requestEmail();
+
+ if (accountName != null) {
+ gsoBuilder.setAccountName(accountName);
+ }
+
+ if (mGoogleApiClient != null) {
+ mGoogleApiClient.disconnect();
+ }
+
+ mGoogleApiClient = new GoogleApiClient.Builder(getContext())
+ .addConnectionCallbacks(this)
+ .addApi(Auth.CREDENTIALS_API)
+ .addApi(Auth.GOOGLE_SIGN_IN_API, gsoBuilder.build())
+ .build();
+ mGoogleApiClient.connect();
+ }
+
+ private void startAuthMethodChoice() {
+ List providers = mHelper.getFlowParams().providerInfo;
+
+ // If the only provider is Email, immediately launch the email flow. Otherwise, launch
+ // the auth method picker screen.
+ if (providers.size() == 1) {
+ if (providers.get(0).getProviderId().equals(EmailAuthProvider.PROVIDER_ID)) {
+ mEmailHintContainer = EmailFlowUtil.startEmailFlow(getActivity(),
+ this,
+ mHelper,
+ RC_EMAIL_FLOW);
+ } else {
+ redirectToIdpSignIn(null,
+ SmartLock.providerIdToAccountType(
+ providers.get(0).getProviderId()));
+ }
+ } else {
+ startActivityForResult(
+ AuthMethodPickerActivity.createIntent(
+ getContext(),
+ mHelper.getFlowParams()),
+ RC_AUTH_METHOD_PICKER);
+ }
+ }
+
+ /**
+ * Begin sign in process with email and password from a SmartLock credential.
+ * On success, finish with {@code RESULT_OK}.
+ * On failure, delete the credential from SmartLock (if applicable) and then launch the
+ * auth method picker flow.
+ */
+ private void signInWithEmailAndPassword(String email, String password) {
+ mHelper.getFirebaseAuth()
+ .signInWithEmailAndPassword(email, password)
+ .addOnFailureListener(new TaskFailureLogger(
+ TAG, "Error signing in with email and password"))
+ .addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(AuthResult authResult) {
+ finish(RESULT_OK, new Intent());
+ }
+ })
+ .addOnFailureListener(new OnFailureListener() {
+ @Override
+ public void onFailure(@NonNull Exception e) {
+ if (e instanceof FirebaseAuthInvalidUserException) {
+ // In this case the credential saved in SmartLock was not
+ // a valid credential, we should delete it from SmartLock
+ // before continuing.
+ deleteCredentialAndRedirect();
+ } else {
+ startAuthMethodChoice();
+ }
+ }
+ });
+ }
+
+ /**
+ * Delete the last credential retrieved from SmartLock and then redirect to the
+ * auth method choice flow.
+ */
+ private void deleteCredentialAndRedirect() {
+ if (mCredential == null) {
+ Log.w(TAG, "deleteCredentialAndRedirect: null credential");
+ startAuthMethodChoice();
+ return;
+ }
+
+ CredentialsApiHelper credentialsApiHelper = CredentialsApiHelper.getInstance(getActivity());
+ credentialsApiHelper.delete(mCredential)
+ .addOnCompleteListener(new OnCompleteListener() {
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (!task.isSuccessful()) {
+ Log.w(TAG, "deleteCredential:failure", task.getException());
+ }
+ startAuthMethodChoice();
+ }
+ });
+ }
+
+ private void redirectToIdpSignIn(String email, String accountType) {
+ Intent nextIntent;
+ switch (accountType) {
+ case IdentityProviders.GOOGLE:
+ nextIntent = IdpSignInContainerActivity.createIntent(
+ getContext(),
+ mHelper.getFlowParams(),
+ GoogleAuthProvider.PROVIDER_ID,
+ email);
+ break;
+ case IdentityProviders.FACEBOOK:
+ nextIntent = IdpSignInContainerActivity.createIntent(
+ getContext(),
+ mHelper.getFlowParams(),
+ FacebookAuthProvider.PROVIDER_ID,
+ email);
+ break;
+ case IdentityProviders.TWITTER:
+ nextIntent = IdpSignInContainerActivity.createIntent(
+ getContext(),
+ mHelper.getFlowParams(),
+ TwitterAuthProvider.PROVIDER_ID,
+ email);
+ break;
+ default:
+ Log.w(TAG, "unknown provider: " + accountType);
+ nextIntent = AuthMethodPickerActivity.createIntent(
+ getContext(),
+ mHelper.getFlowParams());
+ }
+ startActivityForResult(nextIntent, RC_IDP_SIGNIN);
+ }
+
+ public void finish(int resultCode, Intent data) {
+ if (mGoogleApiClient != null) {
+ mGoogleApiClient.disconnect();
+ }
+ mHelper.dismissDialog();
+
+ try {
+ if (resultCode == RESULT_OK) {
+ ((AuthUI.SignInResult) getActivity()).onSignInSuccessful(data);
+ } else {
+ ((AuthUI.SignInResult) getActivity()).onSignInFailed(resultCode);
+ }
+ } catch (ClassCastException e) {
+ Log.e(TAG, getActivity().toString()
+ + " must implement AuthUI.AuthUIResult to receive sign in results");
+ }
+
+ getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
+ }
+
+ /**
+ * Check if there is an active or soon-to-be-active network connection.
+ */
+ private boolean hasNetworkConnection() {
+ ConnectivityManager manager =
+ (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
+
+ return manager != null
+ && manager.getActiveNetworkInfo() != null
+ && manager.getActiveNetworkInfo().isConnectedOrConnecting();
+ }
+
+ public static void delegateSignIn(FragmentActivity activity, FlowParameters parameters) {
+ FragmentManager fm = activity.getSupportFragmentManager();
+ FragmentTransaction ft = fm.beginTransaction();
+
+ Fragment fragment = fm.findFragmentByTag(TAG);
+ if (fragment == null || !(fragment instanceof SignInDelegate)) {
+ SignInDelegate result = new SignInDelegate();
+
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(ExtraConstants.EXTRA_FLOW_PARAMS, parameters);
+ result.setArguments(bundle);
+
+ ft.add(result, TAG).disallowAddToBackStack().commit();
+ }
+ }
+}
diff --git a/auth/src/main/java/com/firebase/ui/auth/util/SmartLockUtil.java b/auth/src/main/java/com/firebase/ui/auth/util/smartlock/SmartLock.java
similarity index 69%
rename from auth/src/main/java/com/firebase/ui/auth/util/SmartLockUtil.java
rename to auth/src/main/java/com/firebase/ui/auth/util/smartlock/SmartLock.java
index 4fd61de00..5316fce3f 100644
--- a/auth/src/main/java/com/firebase/ui/auth/util/SmartLockUtil.java
+++ b/auth/src/main/java/com/firebase/ui/auth/util/smartlock/SmartLock.java
@@ -1,11 +1,18 @@
-package com.firebase.ui.auth.util;
+package com.firebase.ui.auth.util.smartlock;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
+import android.widget.Toast;
+import com.firebase.ui.auth.BuildConfig;
+import com.firebase.ui.auth.ui.BaseFragment;
import com.google.android.gms.auth.api.credentials.Credential;
import com.google.android.gms.auth.api.credentials.IdentityProviders;
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.api.Result;
+import com.google.android.gms.common.api.ResultCallback;
import com.google.firebase.auth.EmailAuthProvider;
import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.FirebaseUser;
@@ -17,11 +24,27 @@
import java.util.Collections;
import java.util.List;
-/**
- * Helper class to deal with Smartlock Flows.
- */
-public class SmartLockUtil {
- private static final String TAG = "SmartLockUtil";
+public abstract class SmartLock extends BaseFragment implements
+ GoogleApiClient.ConnectionCallbacks,
+ ResultCallback,
+ GoogleApiClient.OnConnectionFailedListener {
+ private static final String TAG = "SmartLockBase";
+
+ @Override
+ public void onConnectionSuspended(int i) {
+ if (BuildConfig.DEBUG) {
+ Log.d(TAG, "Connection suspended with code " + i);
+ }
+ }
+
+ @Override
+ public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
+ if (BuildConfig.DEBUG) {
+ Log.d(TAG, "connection failed with " + connectionResult.getErrorMessage()
+ + " and code: " + connectionResult.getErrorCode());
+ }
+ Toast.makeText(getContext(), "An error has occurred.", Toast.LENGTH_SHORT).show();
+ }
/**
* Translate a Firebase Auth provider ID (such as {@link GoogleAuthProvider#PROVIDER_ID}) to
diff --git a/auth/src/main/res/layout/delete_credential.xml b/auth/src/main/res/layout/delete_credential.xml
deleted file mode 100644
index df77836c0..000000000
--- a/auth/src/main/res/layout/delete_credential.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/auth/src/main/res/layout/email_hint_container_layout.xml b/auth/src/main/res/layout/email_hint_container_layout.xml
deleted file mode 100644
index 3509b8411..000000000
--- a/auth/src/main/res/layout/email_hint_container_layout.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/auth/src/main/res/layout/save_credentials_layout.xml b/auth/src/main/res/layout/save_credentials_layout.xml
deleted file mode 100644
index 3509b8411..000000000
--- a/auth/src/main/res/layout/save_credentials_layout.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/auth/src/main/res/values/strings.xml b/auth/src/main/res/values/strings.xml
index c58abc2ad..aed0917c0 100644
--- a/auth/src/main/res/values/strings.xml
+++ b/auth/src/main/res/values/strings.xml
@@ -11,11 +11,8 @@
@string/check_your_email
Email
- Put an email to use for sign in
Password
- Trouble remembering your password
First & last name
- Forgot password
Get instructions sent to this email that explain how to
reset your password.
Create account
@@ -28,11 +25,9 @@
An account already exists with that email address.
Send
Save
- Please input email address
Follow the instructions sent to %1$s to recover your
password.
That email address doesn\'t match an existing account
- Welcome back
Finding a credential…
Delete
Welcome back!
@@ -52,7 +47,6 @@
You\'ve already used
%1$s to sign in. Enter
your password for that account.
- Password
Google
Facebook
Twitter
@@ -62,7 +56,6 @@
Sign in with Twitter
Login unsuccessful
Email account registration unsuccessful
- Missing password or email
Loading…
Sending…
diff --git a/auth/src/main/res/values/styles.xml b/auth/src/main/res/values/styles.xml
index d6717cdc2..f8be26528 100644
--- a/auth/src/main/res/values/styles.xml
+++ b/auth/src/main/res/values/styles.xml
@@ -29,7 +29,7 @@
- 24dp
-