From 7dc4b2b4b78e3fa97356d89fdf14eca66db7a34f Mon Sep 17 00:00:00 2001 From: Jedi Burrell Date: Sat, 20 May 2017 00:53:33 -0400 Subject: [PATCH] Add Google Smart Lock. You now no longer have to type in your email and password, with Google Smart Lock. Simply tap "Basic Authentication", and if you've previously logged in, let Google do it's magic and you don't even touch that log-in form. --- app/build.gradle | 3 +- app/src/main/java/com/fastaccess/App.java | 12 +++ .../com/fastaccess/ui/base/BaseActivity.java | 10 +- .../ui/modules/login/LoginActivity.java | 96 ++++++++++++++++++- .../fastaccess/ui/modules/login/LoginMvp.java | 4 +- .../ui/modules/login/LoginPresenter.java | 13 ++- 6 files changed, 125 insertions(+), 13 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8d9c8c18..af4a99a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,7 +25,7 @@ android { } } compileSdkVersion 'android-O' - buildToolsVersion "26.0.0-rc1" + buildToolsVersion "26.0.0-rc2" defaultConfig { applicationId "com.fastaccess.github" minSdkVersion 21 @@ -162,6 +162,7 @@ dependencies { compile "com.google.firebase:firebase-messaging:${firebase}" releaseCompile "com.google.firebase:firebase-crash:${firebase}" } + compile "com.google.android.gms:play-services-auth:10.2.6" testCompile "junit:junit:${junitVersion}" testCompile "org.mockito:mockito-core:${mockitoVersion}" testCompile "org.assertj:assertj-core:${assertjVersion}" diff --git a/app/src/main/java/com/fastaccess/App.java b/app/src/main/java/com/fastaccess/App.java index a8eec359..65b20c2f 100644 --- a/app/src/main/java/com/fastaccess/App.java +++ b/app/src/main/java/com/fastaccess/App.java @@ -8,6 +8,9 @@ import com.fastaccess.data.dao.model.Models; import com.fastaccess.helper.TypeFaceHelper; import com.fastaccess.provider.tasks.notification.NotificationSchedulerJobTask; import com.fastaccess.provider.uil.UILProvider; +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.common.Scopes; +import com.google.android.gms.common.api.GoogleApiClient; import io.requery.Persistable; import io.requery.android.sqlite.DatabaseSource; @@ -27,6 +30,7 @@ import shortbread.Shortbread; public class App extends Application { private static App instance; private SingleEntityStore dataStore; + private static GoogleApiClient googleApiClient; @Override public void onCreate() { super.onCreate(); @@ -46,6 +50,10 @@ public class App extends Application { TypeFaceHelper.generateTypeface(this); NotificationSchedulerJobTask.scheduleJob(this); Shortbread.create(this); + googleApiClient = new GoogleApiClient.Builder(this) + .addApi(Auth.CREDENTIALS_API) + .build(); + googleApiClient.connect(); } public SingleEntityStore getDataStore() { @@ -60,4 +68,8 @@ public class App extends Application { } return dataStore; } + + public GoogleApiClient getGoogleApiClient() { + return googleApiClient; + } } \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java index bc7bd07c..cf6f8893 100644 --- a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java +++ b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java @@ -32,6 +32,7 @@ import com.fastaccess.helper.BundleConstant; import com.fastaccess.helper.Bundler; import com.fastaccess.helper.InputHelper; import com.fastaccess.helper.PrefGetter; +import com.fastaccess.helper.PrefHelper; import com.fastaccess.helper.ViewHelper; import com.fastaccess.ui.base.mvp.BaseMvp; import com.fastaccess.ui.base.mvp.presenter.BasePresenter; @@ -50,6 +51,7 @@ import com.fastaccess.ui.modules.user.UserPagerActivity; import com.fastaccess.ui.widgets.AvatarLayout; import com.fastaccess.ui.widgets.dialog.MessageDialogView; import com.fastaccess.ui.widgets.dialog.ProgressDialogFragment; +import com.google.android.gms.auth.api.Auth; import com.nostra13.universalimageloader.core.ImageLoader; import java.util.ArrayList; @@ -139,7 +141,11 @@ public abstract class BaseActivity i @Nullable @BindView(R.id.login) FloatingActionButton login; @Nullable @BindView(R.id.progress) ProgressBar progress; + private String pass; + private static int RESOLUTION_CODE = 100; + private static int RESOLUTION_CHOOSER_CODE = 101; + @State boolean isBasicAuth; public static void start(@NonNull Activity activity, boolean isBasicAuth) { @@ -65,6 +75,7 @@ public class LoginActivity extends BaseActivity i .put(BundleConstant.YES_NO_EXTRA, isBasicAuth) .end()); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("smartLock", true); activity.startActivity(intent); activity.finish(); } @@ -138,11 +149,43 @@ public class LoginActivity extends BaseActivity i hideProgress(); Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(SlackBottomSheetDialog.TAG, true); startActivity(intent); finishAffinity(); } + @Override public void onSuccessfullyLoggedIn(Login userModel) { + Credential credential = new Credential.Builder(userModel.getLogin()) + .setPassword(pass) + .setProfilePictureUri(Uri.parse(userModel.getAvatarUrl())) + .build(); + Auth.CredentialsApi.save(App.getInstance().getGoogleApiClient(), credential).setResultCallback(status -> { + if(status.isSuccess()) { + onSuccessfullyLoggedIn(); + } else if(status.hasResolution()){ + try { + status.startResolutionForResult(this, RESOLUTION_CODE); + } catch (IntentSender.SendIntentException e) { + e.printStackTrace(); + } + } else { + Log.e(getLoggingTag(), status+""); + onSuccessfullyLoggedIn(); + } + }); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode==RESOLUTION_CODE) { + onSuccessfullyLoggedIn(); + } else if (requestCode==RESOLUTION_CHOOSER_CODE) { + if (resultCode==RESULT_OK) { + Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY); + doLogin(credential.getId(), credential.getPassword()); + } + } + } + @Override protected void onCreate(Bundle savedInstanceState) { setTheme(R.style.LoginTheme); super.onCreate(savedInstanceState); @@ -166,6 +209,43 @@ public class LoginActivity extends BaseActivity i if(!Locale.getDefault().getLanguage().equals(language)) recreate(); } + + if(isBasicAuth&&getIntent()!=null) + if(getIntent().hasExtra("smartLock")) + if(App.getInstance().getGoogleApiClient().isConnecting()&& + !App.getInstance().getGoogleApiClient().isConnected()) { + App.getInstance().getGoogleApiClient().registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { + @Override + public void onConnected(@Nullable Bundle bundle) { + doCredentialRequest(); + } + @Override + public void onConnectionSuspended(int i) { + } + }); + } else { + doCredentialRequest(); + } + } + + private void doCredentialRequest() { + CredentialRequest credentialRequest = new CredentialRequest.Builder() + .setPasswordLoginSupported(true) + .build(); + Auth.CredentialsApi.request(App.getInstance().getGoogleApiClient(), credentialRequest).setResultCallback(credentialRequestResult -> { + if(credentialRequestResult.getStatus().isSuccess()) { + doLogin(credentialRequestResult.getCredential().getId(), + credentialRequestResult.getCredential().getPassword()); + } else if(credentialRequestResult.getStatus().hasResolution()) + try { + credentialRequestResult.getStatus().startResolutionForResult(this, RESOLUTION_CHOOSER_CODE); + } catch (IntentSender.SendIntentException e) { + e.printStackTrace(); + } + else { + Log.e(getLoggingTag(), credentialRequestResult.getStatus()+""); + } + }); } private void showLanguage() { @@ -225,7 +305,15 @@ public class LoginActivity extends BaseActivity i getPresenter().login(InputHelper.toString(username), InputHelper.toString(password), InputHelper.toString(twoFactor), - isBasicAuth); + isBasicAuth, false); + } + } + + private void doLogin(String username, String password) { + if (progress == null || twoFactor == null || username == null || password == null) return; + if (progress.getVisibility() == View.GONE) { + pass = password; + getPresenter().login(username, password, "", isBasicAuth, true); } } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java index b35cdc8a..d02d7b01 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java +++ b/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java @@ -23,6 +23,8 @@ public interface LoginMvp { void onEmptyPassword(boolean isEmpty); + void onSuccessfullyLoggedIn(Login userModel); + void onSuccessfullyLoggedIn(); } @@ -36,6 +38,6 @@ public interface LoginMvp { void onUserResponse(@Nullable Login response); - void login(@NonNull String username, @NonNull String password, @Nullable String twoFactorCode, boolean isBasicAuth); + void login(@NonNull String username, @NonNull String password, @Nullable String twoFactorCode, boolean isBasicAuth, @Nullable boolean ignore); } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java index 130069b5..e4cc9ceb 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java +++ b/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java @@ -101,20 +101,23 @@ public class LoginPresenter extends BasePresenter implements Logi if (userModel != null) { userModel.setToken(PrefGetter.getToken()); userModel.save(userModel); - sendToView(LoginMvp.View::onSuccessfullyLoggedIn); + if(getView()!=null) + getView().onSuccessfullyLoggedIn(userModel); + else + sendToView(LoginMvp.View::onSuccessfullyLoggedIn); return; } sendToView(view -> view.showMessage(R.string.error, R.string.failed_login)); } @Override public void login(@NonNull String username, @NonNull String password, - @Nullable String twoFactorCode, boolean isBasicAuth) { + @Nullable String twoFactorCode, boolean isBasicAuth, boolean ignore) { boolean usernameIsEmpty = InputHelper.isEmpty(username); boolean passwordIsEmpty = InputHelper.isEmpty(password); if (getView() == null) return; - getView().onEmptyUserName(usernameIsEmpty); - getView().onEmptyPassword(passwordIsEmpty); - if (!usernameIsEmpty && !passwordIsEmpty) { + getView().onEmptyUserName(!ignore&&usernameIsEmpty); + getView().onEmptyPassword(!ignore&&passwordIsEmpty); + if ((!usernameIsEmpty && !passwordIsEmpty) || ignore) { String authToken = Credentials.basic(username, password); if (isBasicAuth) { AuthModel authModel = new AuthModel();