Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
AloqaIM-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
AloqaIM-Android
Commits
ae33779b
Unverified
Commit
ae33779b
authored
Jun 01, 2018
by
Rafael Kellermann Streit
Committed by
GitHub
Jun 01, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1334 from RocketChat/ux/smart-lock
[IMPROVEMENT] Google Smart Lock feature refactor
parents
f6ad8e18
0802e41d
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
228 additions
and
225 deletions
+228
-225
LoginPresenter.kt
...droid/authentication/login/presentation/LoginPresenter.kt
+1
-5
LoginView.kt
...et/android/authentication/login/presentation/LoginView.kt
+2
-2
LoginFragment.kt
...t/rocket/android/authentication/login/ui/LoginFragment.kt
+49
-168
SignupPresenter.kt
...oid/authentication/signup/presentation/SignupPresenter.kt
+1
-5
SignupView.kt
.../android/authentication/signup/presentation/SignupView.kt
+2
-2
SignupFragment.kt
...rocket/android/authentication/signup/ui/SignupFragment.kt
+15
-43
SmartLockHelper.kt
...c/main/java/chat/rocket/android/helper/SmartLockHelper.kt
+146
-0
fragment_authentication_log_in.xml
app/src/main/res/layout/fragment_authentication_log_in.xml
+12
-0
No files found.
app/src/main/java/chat/rocket/android/authentication/login/presentation/LoginPresenter.kt
View file @
ae33779b
...
...
@@ -55,7 +55,6 @@ class LoginPresenter @Inject constructor(
private
lateinit
var
credentialSecret
:
String
private
lateinit
var
deepLinkUserId
:
String
private
lateinit
var
deepLinkToken
:
String
private
var
loginCredentials
:
Credential
?
=
null
fun
setupView
()
{
setupConnectionInfo
(
currentServer
)
...
...
@@ -330,10 +329,7 @@ class LoginPresenter @Inject constructor(
saveToken
(
token
)
registerPushToken
()
if
(
loginType
==
TYPE_LOGIN_USER_EMAIL
)
{
loginCredentials
=
Credential
.
Builder
(
usernameOrEmail
)
.
setPassword
(
password
)
.
build
()
view
.
saveSmartLockCredentials
(
loginCredentials
)
view
.
saveSmartLockCredentials
(
usernameOrEmail
,
password
)
}
navigator
.
toChatList
()
}
else
if
(
loginType
==
TYPE_LOGIN_OAUTH
)
{
...
...
app/src/main/java/chat/rocket/android/authentication/login/presentation/LoginView.kt
View file @
ae33779b
...
...
@@ -226,7 +226,7 @@ interface LoginView : LoadingView, MessageView {
fun
alertWrongPassword
()
/**
* Save
credentials via google smart lock
* Save
s Google Smart Lock credentials.
*/
fun
saveSmartLockCredentials
(
loginCredential
:
Credential
?
)
fun
saveSmartLockCredentials
(
id
:
String
,
password
:
String
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/authentication/login/ui/LoginFragment.kt
View file @
ae33779b
...
...
@@ -2,28 +2,27 @@ package chat.rocket.android.authentication.login.ui
import
DrawableHelper
import
android.app.Activity
import
android.app.PendingIntent
import
android.content.Intent
import
android.content.IntentSender
import
android.graphics.PorterDuff
import
android.os.Build
import
android.os.Bundle
import
android.support.v4.app.Fragment
import
android.support.v4.app.FragmentActivity
import
android.text.style.ClickableSpan
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewTreeObserver
import
android.widget.*
import
android.widget.Button
import
android.widget.ImageButton
import
android.widget.LinearLayout
import
android.widget.ScrollView
import
androidx.core.view.isVisible
import
androidx.core.view.postDelayed
import
chat.rocket.android.R
import
chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import
chat.rocket.android.authentication.login.presentation.LoginPresenter
import
chat.rocket.android.authentication.login.presentation.LoginView
import
chat.rocket.android.helper.KeyboardHelper
import
chat.rocket.android.helper.TextHelper
import
chat.rocket.android.helper.*
import
chat.rocket.android.util.extensions.*
import
chat.rocket.android.webview.cas.ui.INTENT_CAS_TOKEN
import
chat.rocket.android.webview.cas.ui.casWebViewIntent
...
...
@@ -31,37 +30,24 @@ import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_SECRET
import
chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN
import
chat.rocket.android.webview.oauth.ui.oauthWebViewIntent
import
chat.rocket.common.util.ifNull
import
com.google.android.gms.auth.api.Auth
import
com.google.android.gms.auth.api.credentials.*
import
com.google.android.gms.common.api.CommonStatusCodes
import
com.google.android.gms.common.api.GoogleApiClient
import
com.google.android.gms.common.api.ResolvingResultCallbacks
import
com.google.android.gms.common.api.Status
import
dagger.android.support.AndroidSupportInjection
import
kotlinx.android.synthetic.main.fragment_authentication_log_in.*
import
timber.log.Timber
import
javax.inject.Inject
internal
const
val
REQUEST_CODE_FOR_CAS
=
4
internal
const
val
REQUEST_CODE_FOR_OAUTH
=
5
internal
const
val
REQUEST_CODE_FOR_CAS
=
1
internal
const
val
REQUEST_CODE_FOR_OAUTH
=
2
internal
const
val
MULTIPLE_CREDENTIALS_READ
=
3
internal
const
val
NO_CREDENTIALS_EXIST
=
4
internal
const
val
SAVE_CREDENTIALS
=
5
lateinit
var
googleApiClient
:
GoogleApiClient
class
LoginFragment
:
Fragment
(),
LoginView
,
GoogleApiClient
.
ConnectionCallbacks
{
class
LoginFragment
:
Fragment
(),
LoginView
{
@Inject
lateinit
var
presenter
:
LoginPresenter
private
var
isOauthViewEnable
=
false
private
val
layoutListener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
areLoginOptionsNeeded
()
}
private
var
isOauthSuccessful
=
false
private
var
isGlobalLayoutListenerSetUp
=
false
private
var
deepLinkInfo
:
LoginDeepLinkInfo
?
=
null
private
va
r
credentialsToBeSaved
:
Credential
?
=
null
private
va
l
credentialsClient
by
lazy
{
Credentials
.
getClient
(
requireActivity
())
}
companion
object
{
private
const
val
DEEP_LINK_INFO
=
"DeepLinkInfo"
...
...
@@ -73,17 +59,9 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
}
}
override
fun
onConnected
(
bundle
:
Bundle
?)
{
saveSmartLockCredentials
(
credentialsToBeSaved
)
}
override
fun
onConnectionSuspended
(
errorCode
:
Int
)
{
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
AndroidSupportInjection
.
inject
(
this
)
buildGoogleApiClient
()
deepLinkInfo
=
arguments
?.
getParcelable
(
DEEP_LINK_INFO
)
}
...
...
@@ -120,153 +98,37 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
if
(
resultCode
==
Activity
.
RESULT_OK
)
{
if
(
data
!=
null
)
{
when
(
requestCode
)
{
REQUEST_CODE_FOR_
CAS
->
data
.
apply
{
presenter
.
authenticateWithCas
(
getStringExtra
(
INTENT_CAS_TOKEN
))
REQUEST_CODE_FOR_
MULTIPLE_ACCOUNTS_RESOLUTION
->
{
onCredentialRetrieved
(
data
.
getParcelableExtra
(
Credential
.
EXTRA_KEY
))
}
REQUEST_CODE_FOR_OAUTH
->
{
isOauthSuccessful
=
true
data
.
apply
{
presenter
.
authenticateWithOauth
(
getStringExtra
(
INTENT_OAUTH_CREDENTIAL_TOKEN
),
getStringExtra
(
INTENT_OAUTH_CREDENTIAL_SECRET
)
)
}
REQUEST_CODE_FOR_SIGN_IN_REQUIRED
->
{
//use the hints to autofill sign in forms to reduce the info to be filled.
val
credential
:
Credential
=
data
.
getParcelableExtra
(
Credential
.
EXTRA_KEY
)
text_username_or_email
.
setText
(
credential
.
id
)
text_password
.
setText
(
credential
.
password
)
}
MULTIPLE_CREDENTIALS_READ
->
{
val
loginCredentials
:
Credential
=
data
.
getParcelableExtra
(
Credential
.
EXTRA_KEY
)
handleCredential
(
loginCredentials
)
REQUEST_CODE_FOR_SAVE_RESOLUTION
->
{
showMessage
(
getString
(
R
.
string
.
message_credentials_saved_successfully
))
}
NO_CREDENTIALS_EXIST
->
{
//use the hints to autofill sign in forms to reduce the info to be filled
val
loginCredentials
:
Credential
=
data
.
getParcelableExtra
(
Credential
.
EXTRA_KEY
)
val
email
=
loginCredentials
.
id
val
password
=
loginCredentials
.
password
text_username_or_email
.
setText
(
email
)
text_password
.
setText
(
password
)
REQUEST_CODE_FOR_CAS
->
{
presenter
.
authenticateWithCas
(
data
.
getStringExtra
(
INTENT_CAS_TOKEN
))
}
SAVE_CREDENTIALS
->
Toast
.
makeText
(
context
,
getString
(
R
.
string
.
message_credentials_saved_successfully
),
Toast
.
LENGTH_SHORT
).
show
()
}
}
}
//cancel button pressed by the user in case of reading from smart lock
else
if
(
resultCode
==
Activity
.
RESULT_CANCELED
&&
requestCode
==
REQUEST_CODE_FOR_OAUTH
)
{
Timber
.
d
(
"Returned from oauth"
)
}
}
override
fun
onDestroy
()
{
super
.
onDestroy
()
googleApiClient
.
let
{
activity
?.
let
{
it1
->
it
.
stopAutoManage
(
it1
)
}
it
.
disconnect
()
}
}
private
fun
buildGoogleApiClient
()
{
googleApiClient
=
GoogleApiClient
.
Builder
(
context
!!
)
.
enableAutoManage
(
activity
as
FragmentActivity
,
{
Timber
.
e
(
"ERROR: Connection to client failed"
)
})
.
addConnectionCallbacks
(
this
)
.
addApi
(
Auth
.
CREDENTIALS_API
)
.
build
()
}
override
fun
onStart
()
{
super
.
onStart
()
if
(!
isOauthSuccessful
)
{
requestCredentials
()
}
}
private
fun
requestCredentials
()
{
val
request
:
CredentialRequest
=
CredentialRequest
.
Builder
()
.
setPasswordLoginSupported
(
true
)
.
build
()
Auth
.
CredentialsApi
.
request
(
googleApiClient
,
request
)
.
setResultCallback
{
credentialRequestResult
->
val
status
=
credentialRequestResult
.
status
when
{
status
.
isSuccess
->
handleCredential
(
credentialRequestResult
.
credential
)
(
status
.
statusCode
==
CommonStatusCodes
.
RESOLUTION_REQUIRED
)
->
resolveResult
(
status
,
MULTIPLE_CREDENTIALS_READ
)
(
status
.
statusCode
==
CommonStatusCodes
.
SIGN_IN_REQUIRED
)
->
{
val
hintRequest
:
HintRequest
=
HintRequest
.
Builder
()
.
setHintPickerConfig
(
CredentialPickerConfig
.
Builder
()
.
setShowCancelButton
(
true
)
.
build
()
)
.
setEmailAddressIdentifierSupported
(
true
)
.
setAccountTypes
(
IdentityProviders
.
GOOGLE
)
.
build
()
val
intent
:
PendingIntent
=
Auth
.
CredentialsApi
.
getHintPickerIntent
(
googleApiClient
,
hintRequest
)
try
{
startIntentSenderForResult
(
intent
.
intentSender
,
NO_CREDENTIALS_EXIST
,
null
,
0
,
0
,
0
,
null
)
}
catch
(
e
:
IntentSender
.
SendIntentException
)
{
Timber
.
e
(
"ERROR: Could not start hint picker Intent"
)
}
REQUEST_CODE_FOR_OAUTH
->
{
presenter
.
authenticateWithOauth
(
data
.
getStringExtra
(
INTENT_OAUTH_CREDENTIAL_TOKEN
),
data
.
getStringExtra
(
INTENT_OAUTH_CREDENTIAL_SECRET
)
)
}
else
->
Timber
.
d
(
"ERROR: nothing happening"
)
}
}
}
private
fun
handleCredential
(
loginCredentials
:
Credential
)
{
if
(
loginCredentials
.
accountType
==
null
)
{
presenter
.
authenticateWithUserAndPassword
(
loginCredentials
.
id
,
loginCredentials
.
password
.
toString
()
)
}
}
private
fun
resolveResult
(
status
:
Status
,
requestCode
:
Int
)
{
try
{
status
.
startResolutionForResult
(
activity
,
requestCode
)
}
catch
(
e
:
IntentSender
.
SendIntentException
)
{
Timber
.
e
(
"Failed to send Credentials intent"
)
}
}
override
fun
saveSmartLockCredentials
(
loginCredential
:
Credential
?)
{
credentialsToBeSaved
=
loginCredential
if
(
credentialsToBeSaved
==
null
)
{
return
}
activity
?.
let
{
Auth
.
CredentialsApi
.
save
(
googleApiClient
,
credentialsToBeSaved
).
setResultCallback
(
object
:
ResolvingResultCallbacks
<
Status
>(
it
,
SAVE_CREDENTIALS
)
{
override
fun
onSuccess
(
status
:
Status
)
{
Timber
.
d
(
"credentials save:SUCCESS:$status"
)
credentialsToBeSaved
=
null
}
override
fun
onUnresolvableFailure
(
status
:
Status
)
{
Timber
.
e
(
"credentials save:FAILURE:$status"
)
credentialsToBeSaved
=
null
}
})
override
fun
onResume
()
{
super
.
onResume
()
image_key
.
setOnClickListener
{
requestStoredCredentials
()
image_key
.
isVisible
=
false
}
}
...
...
@@ -286,6 +148,24 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
}
}
private
fun
requestStoredCredentials
()
{
activity
?.
let
{
SmartLockHelper
.
requestStoredCredentials
(
credentialsClient
,
it
)
?.
let
{
onCredentialRetrieved
(
it
)
}
}
}
private
fun
onCredentialRetrieved
(
credential
:
Credential
)
{
presenter
.
authenticateWithUserAndPassword
(
credential
.
id
,
credential
.
password
.
toString
())
}
override
fun
saveSmartLockCredentials
(
id
:
String
,
password
:
String
)
{
activity
?.
let
{
SmartLockHelper
.
save
(
credentialsClient
,
it
,
id
,
password
)
}
}
override
fun
showLoading
()
{
ui
{
view_loading
.
isVisible
=
true
...
...
@@ -318,6 +198,7 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
ui
{
text_username_or_email
.
isVisible
=
true
text_password
.
isVisible
=
true
image_key
.
isVisible
=
true
}
}
...
...
app/src/main/java/chat/rocket/android/authentication/signup/presentation/SignupPresenter.kt
View file @
ae33779b
...
...
@@ -15,7 +15,6 @@ import chat.rocket.core.internal.rest.login
import
chat.rocket.core.internal.rest.me
import
chat.rocket.core.internal.rest.signup
import
chat.rocket.core.model.Myself
import
com.google.android.gms.auth.api.credentials.Credential
import
javax.inject.Inject
class
SignupPresenter
@Inject
constructor
(
...
...
@@ -64,10 +63,7 @@ class SignupPresenter @Inject constructor(
localRepository
.
save
(
LocalRepository
.
CURRENT_USERNAME_KEY
,
me
.
username
)
saveAccount
(
me
)
registerPushToken
()
val
loginCredentials
=
Credential
.
Builder
(
email
)
.
setPassword
(
password
)
.
build
()
view
.
saveSmartLockCredentials
(
loginCredentials
)
view
.
saveSmartLockCredentials
(
username
,
password
)
navigator
.
toChatList
()
}
catch
(
exception
:
RocketChatException
)
{
exception
.
message
?.
let
{
...
...
app/src/main/java/chat/rocket/android/authentication/signup/presentation/SignupView.kt
View file @
ae33779b
...
...
@@ -27,7 +27,7 @@ interface SignupView : LoadingView, MessageView {
fun
alertBlankEmail
()
/**
* Save
credentials via google smart lock
* Save
s Google Smart Lock credentials.
*/
fun
saveSmartLockCredentials
(
loginCredential
:
Credential
)
fun
saveSmartLockCredentials
(
id
:
String
,
password
:
String
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/authentication/signup/ui/SignupFragment.kt
View file @
ae33779b
package
chat.rocket.android.authentication.signup.ui
import
DrawableHelper
import
android.app.Activity
.RESULT_OK
import
android.app.Activity
import
android.content.Intent
import
android.os.Build
import
android.os.Bundle
...
...
@@ -11,30 +11,24 @@ import android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewTreeObserver
import
android.widget.Toast
import
chat.rocket.android.R
import
chat.rocket.android.
authentication.login.ui.googleApiClient
import
chat.rocket.android.
R.string.message_credentials_saved_successfully
import
chat.rocket.android.authentication.signup.presentation.SignupPresenter
import
chat.rocket.android.authentication.signup.presentation.SignupView
import
chat.rocket.android.helper.KeyboardHelper
import
chat.rocket.android.helper.SmartLockHelper
import
chat.rocket.android.helper.TextHelper
import
chat.rocket.android.util.extensions.*
import
com.google.android.gms.auth.api.Auth
import
com.google.android.gms.auth.api.credentials.Credential
import
com.google.android.gms.common.api.ResolvingResultCallbacks
import
com.google.android.gms.common.api.Status
import
com.google.android.gms.auth.api.credentials.Credentials
import
dagger.android.support.AndroidSupportInjection
import
kotlinx.android.synthetic.main.fragment_authentication_sign_up.*
import
timber.log.Timber
import
javax.inject.Inject
internal
const
val
SAVE_CREDENTIALS
=
1
class
SignupFragment
:
Fragment
(),
SignupView
{
@Inject
lateinit
var
presenter
:
SignupPresenter
private
lateinit
var
credentialsToBeSaved
:
Credential
private
val
layoutListener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
if
(
KeyboardHelper
.
isSoftKeyboardShown
(
relative_layout
.
rootView
))
{
bottom_container
.
setVisible
(
false
)
...
...
@@ -120,44 +114,16 @@ class SignupFragment : Fragment(), SignupView {
}
}
override
fun
saveSmartLockCredentials
(
loginCredential
:
Credential
)
{
credentialsToBeSaved
=
loginCredential
googleApiClient
.
let
{
if
(
it
.
isConnected
)
{
saveCredentials
()
}
}
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
if
(
requestCode
==
SAVE_CREDENTIALS
)
{
if
(
resultCode
==
RESULT_OK
)
{
Toast
.
makeText
(
context
,
getString
(
R
.
string
.
message_credentials_saved_successfully
),
Toast
.
LENGTH_SHORT
).
show
()
}
else
{
Timber
.
e
(
"ERROR: Cancelled by user"
)
if
(
resultCode
==
Activity
.
RESULT_OK
)
{
if
(
data
!=
null
)
{
if
(
requestCode
==
SAVE_CREDENTIALS
)
{
showMessage
(
getString
(
message_credentials_saved_successfully
))
}
}
}
}
private
fun
saveCredentials
()
{
activity
?.
let
{
Auth
.
CredentialsApi
.
save
(
googleApiClient
,
credentialsToBeSaved
).
setResultCallback
(
object
:
ResolvingResultCallbacks
<
Status
>(
it
,
SAVE_CREDENTIALS
)
{
override
fun
onSuccess
(
status
:
Status
)
{
Timber
.
d
(
"save:SUCCESS:$status"
)
}
override
fun
onUnresolvableFailure
(
status
:
Status
)
{
Timber
.
e
(
"save:FAILURE:$status"
)
}
})
}
}
override
fun
showLoading
()
{
ui
{
enableUserInput
(
false
)
...
...
@@ -188,6 +154,12 @@ class SignupFragment : Fragment(), SignupView {
showMessage
(
getString
(
R
.
string
.
msg_generic_error
))
}
override
fun
saveSmartLockCredentials
(
id
:
String
,
password
:
String
)
{
activity
?.
let
{
SmartLockHelper
.
save
(
Credentials
.
getClient
(
it
),
it
,
id
,
password
)
}
}
private
fun
tintEditTextDrawableStart
()
{
ui
{
val
personDrawable
=
...
...
app/src/main/java/chat/rocket/android/helper/SmartLockHelper.kt
0 → 100644
View file @
ae33779b
package
chat.rocket.android.helper
import
android.app.Activity
import
android.content.IntentSender
import
android.support.v4.app.FragmentActivity
import
com.google.android.gms.auth.api.credentials.*
import
com.google.android.gms.common.api.CommonStatusCodes
import
com.google.android.gms.common.api.ResolvableApiException
import
timber.log.Timber
const
val
REQUEST_CODE_FOR_SIGN_IN_REQUIRED
=
1
const
val
REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION
=
2
const
val
REQUEST_CODE_FOR_SAVE_RESOLUTION
=
3
/**
* This class handles some cases of Google Smart Lock for passwords like the request to retrieve
* credentials, to retrieve sign-in hints and to store the credentials.
*
* See https://developers.google.com/identity/smartlock-passwords/android/overview for futher
* information.
*/
object
SmartLockHelper
{
/**
* Requests for stored Google Smart Lock credentials.
* Note that in case of exception it will try to start a sign in
* ([REQUEST_CODE_FOR_SIGN_IN_REQUIRED]) or "multiple account"
* ([REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION]) resolution.
*
* @param credentialsClient The credential client.
* @param activity The activity.
* @return null or the [Credential] result.
*/
fun
requestStoredCredentials
(
credentialsClient
:
CredentialsClient
,
activity
:
Activity
):
Credential
?
{
var
credential
:
Credential
?
=
null
val
credentialRequest
=
CredentialRequest
.
Builder
()
.
setPasswordLoginSupported
(
true
)
.
build
()
credentialsClient
.
request
(
credentialRequest
)
.
addOnCompleteListener
{
when
{
it
.
isSuccessful
->
{
credential
=
it
.
result
.
credential
}
it
.
exception
is
ResolvableApiException
->
{
val
resolvableApiException
=
(
it
.
exception
as
ResolvableApiException
)
if
(
resolvableApiException
.
statusCode
==
CommonStatusCodes
.
SIGN_IN_REQUIRED
)
{
provideSignInHint
(
credentialsClient
,
activity
)
}
else
{
// This is most likely the case where the user has multiple saved
// credentials and needs to pick one. This requires showing UI to
// resolve the read request.
resolveResult
(
resolvableApiException
,
REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION
,
activity
)
}
}
}
}
return
credential
}
/**
* Saves a user credential to Google Smart Lock.
* Note that in case of exception it will try to start a save resolution,
* so the activity/fragment should expected for a request code
* ([REQUEST_CODE_FOR_SAVE_RESOLUTION]) on onActivityResult call.
*
* @param credentialsClient The credential client.
* @param activity The activity.
* @param id The user id credential.
* @param password The user password credential.
*/
fun
save
(
credentialsClient
:
CredentialsClient
,
activity
:
FragmentActivity
,
id
:
String
,
password
:
String
)
{
val
credential
=
Credential
.
Builder
(
id
)
.
setPassword
(
password
)
.
build
()
credentialsClient
.
save
(
credential
)
.
addOnCompleteListener
{
val
exception
=
it
.
exception
if
(
exception
is
ResolvableApiException
)
{
// Try to resolve the save request. This will prompt the user if
// the credential is new.
try
{
exception
.
startResolutionForResult
(
activity
,
REQUEST_CODE_FOR_SAVE_RESOLUTION
)
}
catch
(
e
:
IntentSender
.
SendIntentException
)
{
Timber
.
e
(
"Failed to send resolution. Exception is: $e"
)
}
}
}
}
private
fun
provideSignInHint
(
credentialsClient
:
CredentialsClient
,
activity
:
Activity
)
{
val
hintRequest
=
HintRequest
.
Builder
()
.
setHintPickerConfig
(
CredentialPickerConfig
.
Builder
()
.
setShowCancelButton
(
true
)
.
build
()
)
.
setEmailAddressIdentifierSupported
(
true
)
.
build
()
try
{
val
intent
=
credentialsClient
.
getHintPickerIntent
(
hintRequest
)
activity
.
startIntentSenderForResult
(
intent
.
intentSender
,
REQUEST_CODE_FOR_SIGN_IN_REQUIRED
,
null
,
0
,
0
,
0
,
null
)
}
catch
(
e
:
IntentSender
.
SendIntentException
)
{
Timber
.
e
(
"Could not start hint picker Intent. Exception is: $e"
)
}
}
private
fun
resolveResult
(
exception
:
ResolvableApiException
,
requestCode
:
Int
,
activity
:
Activity
)
{
try
{
exception
.
startResolutionForResult
(
activity
,
requestCode
)
}
catch
(
e
:
IntentSender
.
SendIntentException
)
{
Timber
.
e
(
"Failed to send resolution. Exception is: $e"
)
}
}
}
\ No newline at end of file
app/src/main/res/layout/fragment_authentication_log_in.xml
View file @
ae33779b
...
...
@@ -32,6 +32,18 @@
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/text_headline"
/>
<ImageView
android:id=
"@+id/image_key"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"10dp"
android:src=
"@drawable/ic_vpn_key_black_24dp"
android:tint=
"@color/colorDrawableTintGrey"
android:visibility=
"gone"
app:layout_constraintBottom_toBottomOf=
"@+id/text_username_or_email"
app:layout_constraintEnd_toEndOf=
"@+id/text_username_or_email"
app:layout_constraintTop_toTopOf=
"@+id/text_username_or_email"
/>
<EditText
android:id=
"@+id/text_password"
style=
"@style/Authentication.EditText"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment