diff options
9 files changed, 255 insertions, 18 deletions
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml index eb1f43c2..787a6dba 100644 --- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml @@ -16,9 +16,9 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.android.autofillframework" - android:versionCode="1" - android:versionName="1.0"> + package="com.example.android.autofillframework" + android:versionCode="1" + android:versionName="1.0"> <application android:allowBackup="true" @@ -36,14 +36,19 @@ </intent-filter> </activity> <activity - android:name=".app.LoginActivity" + android:name=".app.StandardSignInActivity" android:label="AF StandardLogin" - android:taskAffinity=".LoginActivity"> + android:taskAffinity=".StandardSignInActivity"> </activity> <activity - android:name=".app.VirtualLoginActivity" + android:name=".app.StandardAutoCompleteSignInActivity" + android:label="AF StandardLogin" + android:taskAffinity=".StandardAutoCompleteSignInActivity" /> + <activity + android:name=".app.VirtualSignInActivity" android:label="AF VirtualLogin" - android:taskAffinity=".VirtualLoginActivity"> + android:taskAffinity=".VirtualSignInActivity"> + </activity> <activity android:name=".app.WelcomeActivity" /> <activity diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt index bef16afe..b230db47 100644 --- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.kt @@ -183,8 +183,8 @@ class CustomVirtualView(context: Context, attrs: AttributeSet) : View(context, a } private class Item internal constructor(val line: Line, val id: Int, val hints: Array<String>?, - val type: Int, var text: CharSequence, - val editable: Boolean, val sanitized: Boolean) { + val type: Int, var text: CharSequence, + val editable: Boolean, val sanitized: Boolean) { var focused = false override fun toString(): String { @@ -199,7 +199,7 @@ class CustomVirtualView(context: Context, attrs: AttributeSet) : View(context, a } private inner class Line constructor(val idEntry: String, label: String, hints: Array<String>, - text: String, sanitized: Boolean) { + text: String, sanitized: Boolean) { // Boundaries of the text field, relative to the CustomView internal val bounds = Rect() diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt index 1759de25..c7c458d4 100644 --- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt @@ -19,6 +19,7 @@ import android.os.Bundle import android.support.v7.app.AppCompatActivity import com.example.android.autofillframework.R import kotlinx.android.synthetic.main.activity_main.creditCardCheckoutButton +import kotlinx.android.synthetic.main.activity_main.standardLoginWithAutoCompleteButton import kotlinx.android.synthetic.main.activity_main.standardViewSignInButton import kotlinx.android.synthetic.main.activity_main.virtualViewSignInButton @@ -33,6 +34,7 @@ class MainActivity : AppCompatActivity() { standardViewSignInButton.setOnClickListener { standardViewSignIn() } virtualViewSignInButton.setOnClickListener { virtualViewSignIn() } creditCardCheckoutButton.setOnClickListener { creditCardCheckout() } + standardLoginWithAutoCompleteButton.setOnClickListener { standardAutoCompleteSignIn() } } private fun creditCardCheckout() { @@ -41,12 +43,17 @@ class MainActivity : AppCompatActivity() { } private fun standardViewSignIn() { - val intent = LoginActivity.getStartActivityIntent(this) + val intent = StandardSignInActivity.getStartActivityIntent(this) + startActivity(intent) + } + + private fun standardAutoCompleteSignIn() { + val intent = StandardAutoCompleteSignInActivity.getStartActivityIntent(this) startActivity(intent) } private fun virtualViewSignIn() { - val intent = VirtualLoginActivity.getStartActivityIntent(this) + val intent = VirtualSignInActivity.getStartActivityIntent(this) startActivity(intent) } }
\ No newline at end of file diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/StandardAutoCompleteSignInActivity.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/StandardAutoCompleteSignInActivity.kt new file mode 100644 index 00000000..21eb4d70 --- /dev/null +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/StandardAutoCompleteSignInActivity.kt @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * 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.example.android.autofillframework.app + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.util.Log +import android.view.View +import android.view.autofill.AutofillManager +import android.widget.ArrayAdapter +import android.widget.AutoCompleteTextView +import android.widget.Toast +import com.example.android.autofillframework.CommonUtil.TAG +import com.example.android.autofillframework.R +import kotlinx.android.synthetic.main.login_with_autocomplete_activity.clear +import kotlinx.android.synthetic.main.login_with_autocomplete_activity.login +import kotlinx.android.synthetic.main.login_with_autocomplete_activity.passwordField +import kotlinx.android.synthetic.main.login_with_autocomplete_activity.usernameField + +class StandardAutoCompleteSignInActivity : AppCompatActivity() { + private var mAutofillReceived = false + private var mAutofillCallback: AutofillManager.AutofillCallback? = null + private var mAutofillManager: AutofillManager? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContentView(R.layout.login_with_autocomplete_activity) + + login.setOnClickListener { submitLogin() } + clear.setOnClickListener { resetFields() } + mAutofillCallback = MyAutofillCallback() + mAutofillManager = getSystemService(AutofillManager::class.java) + val mockAutocompleteAdapter = ArrayAdapter.createFromResource(this, R.array.mock_autocomplete_sign_in_suggestions, + android.R.layout.simple_dropdown_item_1line) + usernameField.setAdapter(mockAutocompleteAdapter) + } + + override fun onResume() { + super.onResume() + mAutofillManager?.registerCallback(mAutofillCallback) + } + + override fun onPause() { + super.onPause() + mAutofillManager?.unregisterCallback(mAutofillCallback) + } + + private fun resetFields() { + usernameField.setText("") + passwordField.setText("") + } + + /** + * Emulates a login action. + */ + private fun submitLogin() { + val username = usernameField.text.toString() + val password = passwordField.text.toString() + val valid = isValidCredentials(username, password) + if (valid) { + val intent = WelcomeActivity.getStartActivityIntent(this@StandardAutoCompleteSignInActivity) + startActivity(intent) + finish() + } else { + Toast.makeText(this, "Authentication failed.", Toast.LENGTH_SHORT).show() + } + } + + /** + * Dummy implementation for demo purposes. A real service should use secure mechanisms to + * authenticate users. + */ + fun isValidCredentials(username: String?, password: String?): Boolean { + return username != null && password != null && username == password + } + + private inner class MyAutofillCallback : AutofillManager.AutofillCallback() { + override fun onAutofillEvent(view: View, event: Int) { + super.onAutofillEvent(view, event) + if (view is AutoCompleteTextView) { + when (event) { + AutofillManager.AutofillCallback.EVENT_INPUT_UNAVAILABLE, + AutofillManager.AutofillCallback.EVENT_INPUT_HIDDEN -> if (!mAutofillReceived) { + view.showDropDown() + } + AutofillManager.AutofillCallback.EVENT_INPUT_SHOWN -> { + mAutofillReceived = true + view.setAdapter(null) + } + else -> Log.d(TAG, "Unexpected callback: " + event) + } + } + } + } + + companion object { + + fun getStartActivityIntent(context: Context): Intent { + val intent = Intent(context, StandardAutoCompleteSignInActivity::class.java) + return intent + } + } +}
\ No newline at end of file diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/LoginActivity.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/StandardSignInActivity.kt index 8bdc1c33..971bd167 100644 --- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/LoginActivity.kt +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/StandardSignInActivity.kt @@ -28,7 +28,7 @@ import kotlinx.android.synthetic.main.login_activity.passwordField import kotlinx.android.synthetic.main.login_activity.usernameField -class LoginActivity : AppCompatActivity() { +class StandardSignInActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -50,7 +50,7 @@ class LoginActivity : AppCompatActivity() { val password = passwordField.text.toString() val valid = isValidCredentials(username, password) if (valid) { - val intent = WelcomeActivity.getStartActivityIntent(this@LoginActivity) + val intent = WelcomeActivity.getStartActivityIntent(this@StandardSignInActivity) startActivity(intent) finish() } else { @@ -69,7 +69,7 @@ class LoginActivity : AppCompatActivity() { companion object { fun getStartActivityIntent(context: Context): Intent { - val intent = Intent(context, LoginActivity::class.java) + val intent = Intent(context, StandardSignInActivity::class.java) return intent } } diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/VirtualLoginActivity.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/VirtualSignInActivity.kt index 52081afd..6d86da95 100644 --- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/VirtualLoginActivity.kt +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/VirtualSignInActivity.kt @@ -26,7 +26,7 @@ import kotlinx.android.synthetic.main.virtual_login_activity.custom_view import kotlinx.android.synthetic.main.virtual_login_activity.login -class VirtualLoginActivity : AppCompatActivity() { +class VirtualSignInActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,7 +49,7 @@ class VirtualLoginActivity : AppCompatActivity() { val password = custom_view.passwordText.toString() val valid = isValidCredentials(username, password) if (valid) { - val intent = WelcomeActivity.getStartActivityIntent(this@VirtualLoginActivity) + val intent = WelcomeActivity.getStartActivityIntent(this@VirtualSignInActivity) startActivity(intent) finish() } else { @@ -68,7 +68,7 @@ class VirtualLoginActivity : AppCompatActivity() { companion object { fun getStartActivityIntent(context: Context): Intent { - val intent = Intent(context, VirtualLoginActivity::class.java) + val intent = Intent(context, VirtualSignInActivity::class.java) return intent } } diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml index 26d0657d..b2510b07 100644 --- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml @@ -30,6 +30,12 @@ android:text="@string/standard_view_sign_in" /> <Button + android:id="@+id/standardLoginWithAutoCompleteButton" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/standard_view_autocomplete_sign_in"/> + + <Button android:id="@+id/virtualViewSignInButton" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/login_with_autocomplete_activity.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/login_with_autocomplete_activity.xml new file mode 100644 index 00000000..1906790a --- /dev/null +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/login_with_autocomplete_activity.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright (C) 2017 The Android Open Source Project + * + * 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. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/standardLoginLayout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:focusable="true" + android:focusableInTouchMode="true" + android:orientation="vertical" + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin"> + + <RelativeLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"> + + <TextView + android:id="@+id/usernameLabel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="20dp" + android:importantForAutofill="no" + android:labelFor="@+id/usernameField" + android:text="@string/username_label" /> + + <AutoCompleteTextView + android:id="@+id/usernameField" + android:layout_width="200sp" + android:layout_height="wrap_content" + android:layout_alignBaseline="@+id/usernameLabel" + android:layout_toEndOf="@id/usernameLabel" + android:autofillHints="username" + android:inputType="textPersonName" /> + + <TextView + android:id="@+id/passwordLabel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignStart="@+id/usernameLabel" + android:layout_below="@+id/usernameLabel" + android:layout_marginTop="20dp" + android:importantForAutofill="no" + android:text="@string/password_label" + android:labelFor="@+id/passwordField"/> + + <EditText + android:id="@+id/passwordField" + android:layout_width="200sp" + android:layout_height="wrap_content" + android:layout_alignBaseline="@+id/passwordLabel" + android:layout_alignStart="@+id/usernameField" + android:autofillHints="password" + android:inputType="textPassword" /> + </RelativeLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:gravity="center" + android:orientation="horizontal"> + + <Button + android:id="@+id/clear" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Clear" /> + + <Button + android:id="@+id/login" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Login" /> + </LinearLayout> + +</LinearLayout>
\ No newline at end of file diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml index f9448a74..ffb8495a 100644 --- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml +++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml @@ -22,6 +22,8 @@ <string name="password_label">Password</string> <string name="welcome_text">You have successfully signed in!</string> <string name="standard_view_sign_in">Sign in using standard views</string> + <string name="standard_view_autocomplete_sign_in">Sign in using standard views that + trigger AutoComplete dialogs when focused</string> <string name="virtual_view_sign_in">Sign in using virtual views</string> <string name="credit_card_checkout">Credit Card check out</string> <string name="autofill_sign_in_prompt">Tap to sign in.</string> @@ -104,4 +106,9 @@ <item>2024</item> </string-array> + <string-array name="mock_autocomplete_sign_in_suggestions"> + <item>user-1</item> + <item>user-2</item> + </string-array> + </resources> |