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();