diff options
author | Douglas Sigelbaum <sigelbaum@google.com> | 2017-05-16 08:49:27 -0700 |
---|---|---|
committer | Douglas Sigelbaum <sigelbaum@google.com> | 2017-05-16 18:07:18 -0700 |
commit | c641d78425eebd911c539ed56a5b48a7e5b3ffff (patch) | |
tree | 3c3941cd3e11bd05103fff9652b4c9bb04189779 /input | |
parent | 9a56c2387d179d15f8567f57eed3c45c0271204e (diff) | |
download | android-c641d78425eebd911c539ed56a5b48a7e5b3ffff.tar.gz |
Neatening up autofill settings.
Also added auth and option to clear
data to settings, and fixed failed master-login issue.
Test: manual
Bug: 38182790, 37492778
Change-Id: I9f303f9573e4cba57626cc23b5c1dab102983b95
Diffstat (limited to 'input')
18 files changed, 410 insertions, 139 deletions
diff --git a/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml b/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml index e7d748e0..d17dce13 100644 --- a/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml +++ b/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml @@ -25,7 +25,7 @@ android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" - android:theme="@style/AppTheme"> + android:theme="@style/Theme.AppCompat.Light"> <activity android:name=".app.MainActivity" android:label="AF Main" @@ -90,7 +90,8 @@ --> <service android:name=".service.MyAutofillService" - android:permission="android.permission.BIND_AUTOFILL"> + android:permission="android.permission.BIND_AUTOFILL" + android:label="Sample Autofill Service"> <meta-data android:name="android.autofill" android:resource="@xml/autofill_service" /> diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardActivity.java index 6f5a2f3a..a82de4c8 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardActivity.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardActivity.java @@ -15,24 +15,18 @@ */ package com.example.android.autofillframework.app; -import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.IdRes; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; -import android.widget.EditText; import android.widget.Spinner; import com.example.android.autofillframework.R; -import java.util.List; - -public class CreditCardActivity extends Activity { +public class CreditCardActivity extends AppCompatActivity { private Spinner mCcExpirationDaySpinner; private Spinner mCcExpirationMonthSpinner; @@ -51,11 +45,11 @@ public class CreditCardActivity extends Activity { setContentView(R.layout.credit_card_activity); - mSubmitButton = findViewById(R.id.submit); - mClearButton = findViewById(R.id.clear); - mCcExpirationDaySpinner = findViewById(R.id.expirationDay); - mCcExpirationMonthSpinner = findViewById(R.id.expirationMonth); - mCcExpirationYearSpinner = findViewById(R.id.expirationYear); + mSubmitButton = (Button) findViewById(R.id.submit); + mClearButton = (Button) findViewById(R.id.clear); + mCcExpirationDaySpinner = (Spinner) findViewById(R.id.expirationDay); + mCcExpirationMonthSpinner = (Spinner) findViewById(R.id.expirationMonth); + mCcExpirationYearSpinner = (Spinner) findViewById(R.id.expirationYear); // Create an ArrayAdapter using the string array and a default spinner layout ArrayAdapter<CharSequence> dayAdapter = ArrayAdapter.createFromResource diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/LoginActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/LoginActivity.java index 051572a4..3ec87da0 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/LoginActivity.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/LoginActivity.java @@ -15,10 +15,10 @@ */ package com.example.android.autofillframework.app; -import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; @@ -26,7 +26,7 @@ import android.widget.Toast; import com.example.android.autofillframework.R; -public class LoginActivity extends Activity { +public class LoginActivity extends AppCompatActivity { private EditText mUsernameEditText; private EditText mPasswordEditText; @@ -44,10 +44,10 @@ public class LoginActivity extends Activity { setContentView(R.layout.login_activity); - mLoginButton = findViewById(R.id.login); - mClearButton = findViewById(R.id.clear); - mUsernameEditText = findViewById(R.id.usernameField); - mPasswordEditText = findViewById(R.id.passwordField); + mLoginButton = (Button) findViewById(R.id.login); + mClearButton = (Button) findViewById(R.id.clear); + mUsernameEditText = (EditText) findViewById(R.id.usernameField); + mPasswordEditText = (EditText) findViewById(R.id.passwordField); mLoginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java index 88c07eac..4b27010b 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java @@ -19,6 +19,7 @@ import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; import android.view.View; import com.example.android.autofillframework.R; @@ -26,7 +27,7 @@ import com.example.android.autofillframework.R; /** * This is used to launch sample activities that showcase autofill. */ -public class MainActivity extends Activity { +public class MainActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/VirtualLoginActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/VirtualLoginActivity.java index 744da2d3..5a4a4f4e 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/VirtualLoginActivity.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/VirtualLoginActivity.java @@ -19,13 +19,14 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Toast; import com.example.android.autofillframework.R; -public class VirtualLoginActivity extends Activity { +public class VirtualLoginActivity extends AppCompatActivity { private CustomVirtualView mCustomVirtualView; diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AuthActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AuthActivity.java index 5c00a304..9fc87969 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AuthActivity.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AuthActivity.java @@ -37,6 +37,7 @@ import com.example.android.autofillframework.R; import com.example.android.autofillframework.service.datasource.LocalAutofillRepository; import com.example.android.autofillframework.service.model.AutofillFieldsCollection; import com.example.android.autofillframework.service.model.ClientFormData; +import com.example.android.autofillframework.service.settings.MyPreferences; import java.util.HashMap; @@ -63,8 +64,7 @@ public class AuthActivity extends Activity { static IntentSender getAuthIntentSenderForResponse(Context context) { final Intent intent = new Intent(context, AuthActivity.class); - return PendingIntent.getActivity(context, 0, intent, - PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT) + return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) .getIntentSender(); } @@ -73,8 +73,7 @@ public class AuthActivity extends Activity { intent.putExtra(EXTRA_DATASET_NAME, datasetName); intent.putExtra(EXTRA_FOR_RESPONSE, false); return PendingIntent.getActivity(context, ++sDatasetPendingIntentId, intent, - PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT) - .getIntentSender(); + PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender(); } @Override @@ -103,10 +102,11 @@ public class AuthActivity extends Activity { } private void login() { - // TODO set master username/password in Settings. Editable password = mMasterPassword.getText(); - Log.d(TAG, "login: " + password); - if (password.length() == 0) { + Log.d(TAG, "PW entered: " + password); + Log.d(TAG, "Correct: " + MyPreferences.getInstance(AuthActivity.this).getMasterPassword()); + if (password.toString() + .equals(MyPreferences.getInstance(AuthActivity.this).getMasterPassword())) { onSuccess(); } else { Toast.makeText(this, "Password incorrect", Toast.LENGTH_SHORT).show(); diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/AutofillRepository.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/AutofillRepository.java index 5061210a..c79f61dc 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/AutofillRepository.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/AutofillRepository.java @@ -33,4 +33,9 @@ public interface AutofillRepository { * Saves LoginCredential under this datasetName. */ void saveClientFormData(ClientFormData clientFormData); + + /** + * Clear all data. + */ + void clear(); } diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/LocalAutofillRepository.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/LocalAutofillRepository.java index d7d7a3e0..8336fe1e 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/LocalAutofillRepository.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/LocalAutofillRepository.java @@ -44,7 +44,8 @@ public class LocalAutofillRepository implements AutofillRepository { // TODO prepend with autofill data set in Settings. private LocalAutofillRepository(Context context) { - mPrefs = context.getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE); + mPrefs = context.getApplicationContext() + .getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE); } public static LocalAutofillRepository getInstance(Context context) { @@ -95,6 +96,11 @@ public class LocalAutofillRepository implements AutofillRepository { incrementDatasetNumber(); } + @Override + public void clear() { + mPrefs.edit().remove(CLIENT_FORM_DATA_KEY).apply(); + } + private Set<String> getAllAutofillDataStringSet() { return mPrefs.getStringSet(CLIENT_FORM_DATA_KEY, new ArraySet<String>()); } diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/ClientFormData.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/ClientFormData.java index 5a7e76aa..7a3e7ac1 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/ClientFormData.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/ClientFormData.java @@ -113,7 +113,8 @@ public final class ClientFormData { for (int autofillFieldIndex = 0; autofillFieldIndex < autofillFields.size(); autofillFieldIndex++) { AutofillField autofillField = autofillFields.get(autofillFieldIndex); AutofillId autofillId = autofillField.getId(); - switch (autofillField.getAutofillType()) { + int autofillType = autofillField.getAutofillType(); + switch (autofillType) { case View.AUTOFILL_TYPE_LIST: int listValue = autofillField.getAutofillOptionIndex(hintMap.get(hint).getTextValue()); datasetBuilder.setValue(autofillId, AutofillValue.forList(listValue)); @@ -132,7 +133,7 @@ public final class ClientFormData { break; case View.AUTOFILL_TYPE_NONE: default: - Log.w(TAG, "Invalid autofill saveType"); + Log.w(TAG, "Invalid autofill type - " + autofillType); break; } } diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/MyPreferences.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/MyPreferences.java index 1425e7f6..3926530e 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/MyPreferences.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/MyPreferences.java @@ -19,14 +19,15 @@ import android.content.Context; import android.content.SharedPreferences; import android.service.autofill.Dataset; import android.service.autofill.FillResponse; -import android.util.Log; +import android.support.annotation.NonNull; public class MyPreferences { private static final String TAG = "MyPreferences"; - private static final String PREF_NUMBER_DATASET = "number_datasets"; - private static final String PREF_RESPONSE_AUTH = "response_auth"; - private static final String PREF_DATASET_AUTH = "dataset_auth"; + private static final String RESPONSE_AUTH_KEY = "response_auth"; + private static final String DATASET_AUTH_KEY = "dataset_auth"; + private static final String MASTER_PASSWORD_KEY = "master_password"; + private static MyPreferences sInstance; private final SharedPreferences mPrefs; @@ -43,34 +44,48 @@ public class MyPreferences { } /** - * Gets the number of {@link Dataset}s that should be added to a {@link FillResponse}. + * Gets whether {@link FillResponse}s should require authentication. */ - public int getNumberDatasets() { - return mPrefs.getInt(PREF_NUMBER_DATASET, 2); + public boolean isResponseAuth() { + return mPrefs.getBoolean(RESPONSE_AUTH_KEY, false); } /** - * Gets whether {@link FillResponse}s should require authentication. + * Enables/disables authentication for the entire autofill {@link FillResponse}. */ - public boolean isResponseAuth() { - return mPrefs.getBoolean(PREF_RESPONSE_AUTH, false); + public void setResponseAuth(boolean responseAuth) { + mPrefs.edit().putBoolean(RESPONSE_AUTH_KEY, responseAuth).apply(); } - /** * Gets whether {@link Dataset}s should require authentication. */ public boolean isDatasetAuth() { - return mPrefs.getBoolean(PREF_DATASET_AUTH, false); + return mPrefs.getBoolean(DATASET_AUTH_KEY, false); } - public void bulkEdit(int numberDatasets, boolean responseAuth, boolean datasetAuth) { - Log.v(TAG, "bulk edit:" + numberDatasets + ":" + responseAuth + ":" + datasetAuth); - mPrefs.edit() - .putInt(PREF_NUMBER_DATASET, numberDatasets) - .putBoolean(PREF_RESPONSE_AUTH, responseAuth) - .putBoolean(PREF_DATASET_AUTH, datasetAuth) - .apply(); + /** + * Enables/disables authentication for individual autofill {@link Dataset}s. + */ + public void setDatasetAuth(boolean datasetAuth) { + mPrefs.edit().putBoolean(DATASET_AUTH_KEY, datasetAuth).apply(); + } + + /** + * Gets autofill master username. + */ + public String getMasterPassword() { + return mPrefs.getString(MASTER_PASSWORD_KEY, null); + } + + /** + * Sets autofill master password. + */ + public void setMasterPassword(@NonNull String masterPassword) { + mPrefs.edit().putString(MASTER_PASSWORD_KEY, masterPassword).apply(); + } + public void clearCredentials() { + mPrefs.edit().remove(MASTER_PASSWORD_KEY).apply(); } } diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/SettingsActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/SettingsActivity.java index e771d185..21bb7be0 100644 --- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/SettingsActivity.java +++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/SettingsActivity.java @@ -15,58 +15,162 @@ */ package com.example.android.autofillframework.service.settings; -import android.app.Activity; +import android.content.DialogInterface; import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.view.LayoutInflater; import android.view.View; -import android.widget.Button; -import android.widget.CheckBox; +import android.view.ViewGroup; +import android.widget.CompoundButton; import android.widget.EditText; +import android.widget.ImageView; +import android.widget.Switch; +import android.widget.TextView; import com.example.android.autofillframework.R; +import com.example.android.autofillframework.service.datasource.LocalAutofillRepository; -import java.util.Locale; - -public class SettingsActivity extends Activity { - - private EditText mNumberDatasets; - private CheckBox mResponseAuth; - private CheckBox mDatasetAuth; - private Button mSave; - private Button mCancel; +public class SettingsActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.settings_activity); - mNumberDatasets = findViewById(R.id.number_datasets); - mResponseAuth = findViewById(R.id.response_auth); - mDatasetAuth = findViewById(R.id.dataset_auth); - mSave = findViewById(R.id.save); - mCancel = findViewById(R.id.cancel); + final MyPreferences preferences = MyPreferences.getInstance(this); + setupSettingsSwitch(R.id.settings_auth_responses_container, + R.id.settings_auth_responses_label, + R.id.settings_auth_responses_switch, + preferences.isResponseAuth(), + new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + preferences.setResponseAuth(b); + } + }); + setupSettingsSwitch(R.id.settings_auth_datasets_container, + R.id.settings_auth_datasets_label, + R.id.settings_auth_datasets_switch, + preferences.isDatasetAuth(), + new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + preferences.setDatasetAuth(b); + } + }); + setupSettingsButton(R.id.settings_clear_data_container, + R.id.settings_clear_data_label, + R.id.settings_clear_data_icon, + new View.OnClickListener() { + @Override + public void onClick(View view) { + buildClearDataDialog().show(); + } + }); - final MyPreferences p = MyPreferences.getInstance(this); + setupSettingsButton(R.id.settings_auth_credentials_container, + R.id.settings_auth_credentials_label, + R.id.settings_auth_credentials_icon, + new View.OnClickListener() { + @Override + public void onClick(View view) { + if (MyPreferences.getInstance(SettingsActivity.this).getMasterPassword() != null) { + buildCurrentCredentialsDialog().show(); + } else { + buildNewCredentialsDialog().show(); + } + } + }); + } - mNumberDatasets.setText(String.format(Locale.getDefault(), "%d", p.getNumberDatasets())); - mDatasetAuth.setChecked(p.isDatasetAuth()); - mResponseAuth.setChecked(p.isResponseAuth()); + private AlertDialog buildClearDataDialog() { + return new AlertDialog.Builder(SettingsActivity.this) + .setMessage(R.string.settings_clear_data_confirmation) + .setTitle(R.string.settings_clear_data_confirmation_title) + .setNegativeButton(R.string.cancel, null) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + LocalAutofillRepository.getInstance + (SettingsActivity.this).clear(); + MyPreferences.getInstance(SettingsActivity.this) + .clearCredentials(); + dialog.dismiss(); + } + }) + .create(); + } - mSave.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - MyPreferences.getInstance(SettingsActivity.this).bulkEdit( - Integer.parseInt(mNumberDatasets.getText().toString()), - mResponseAuth.isChecked(), - mDatasetAuth.isChecked()); - finish(); - } - }); + private AlertDialog.Builder prepareCredentialsDialog() { + return new AlertDialog.Builder(SettingsActivity.this) + .setTitle(R.string.settings_auth_change_credentials_title) + .setNegativeButton(R.string.cancel, null); + } + + private AlertDialog buildCurrentCredentialsDialog() { + final EditText currentPasswordField = LayoutInflater + .from(SettingsActivity.this) + .inflate(R.layout.settings_authentication_dialog, null) + .findViewById(R.id.master_password_field); + return prepareCredentialsDialog() + .setMessage(R.string.settings_auth_enter_current_password) + .setView(currentPasswordField) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String password = currentPasswordField.getText().toString(); + if (MyPreferences.getInstance(SettingsActivity.this).getMasterPassword() + .equals(password)) { + buildNewCredentialsDialog().show(); + dialog.dismiss(); + } + } + }) + .create(); + } - mCancel.setOnClickListener(new View.OnClickListener() { + private AlertDialog buildNewCredentialsDialog() { + final EditText newPasswordField = LayoutInflater + .from(SettingsActivity.this) + .inflate(R.layout.settings_authentication_dialog, null) + .findViewById(R.id.master_password_field); + return prepareCredentialsDialog() + .setMessage(R.string.settings_auth_enter_new_password) + .setView(newPasswordField) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String password = newPasswordField.getText().toString(); + MyPreferences.getInstance(SettingsActivity.this).setMasterPassword(password); + dialog.dismiss(); + } + }) + .create(); + } + + private void setupSettingsSwitch(int containerId, int labelId, int switchId, boolean checked, + CompoundButton.OnCheckedChangeListener checkedChangeListener) { + ViewGroup container = (ViewGroup) findViewById(containerId); + String switchLabel = ((TextView) container.findViewById(labelId)).getText().toString(); + final Switch switchView = container.findViewById(switchId); + switchView.setContentDescription(switchLabel); + switchView.setChecked(checked); + container.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { - finish(); + public void onClick(View v) { + switchView.performClick(); } }); + switchView.setOnCheckedChangeListener(checkedChangeListener); + } + + private void setupSettingsButton(int containerId, int labelId, int imageViewId, + final View.OnClickListener onClickListener) { + ViewGroup container = (ViewGroup) findViewById(containerId); + String buttonLabel = ((TextView) container.findViewById(labelId)).getText().toString(); + final ImageView imageView = container.findViewById(imageViewId); + imageView.setContentDescription(buttonLabel); + container.setOnClickListener(onClickListener); } } diff --git a/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_delete_forever_black_24dp.xml b/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_delete_forever_black_24dp.xml new file mode 100644 index 00000000..06d61218 --- /dev/null +++ b/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_delete_forever_black_24dp.xml @@ -0,0 +1,5 @@ +<vector android:alpha="0.50" android:height="24dp" + android:viewportHeight="24.0" android:viewportWidth="24.0" + android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="#FF000000" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z"/> +</vector> diff --git a/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_person_black_24dp.xml b/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_person_black_24dp.xml new file mode 100644 index 00000000..7a0dcd36 --- /dev/null +++ b/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_person_black_24dp.xml @@ -0,0 +1,5 @@ +<vector android:alpha="0.50" android:height="24dp" + android:viewportHeight="24.0" android:viewportWidth="24.0" + android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/> +</vector> diff --git a/input/autofill/AutofillFramework/Application/src/main/res/layout/settings_activity.xml b/input/autofill/AutofillFramework/Application/src/main/res/layout/settings_activity.xml index 5a0f7283..5a3076da 100644 --- a/input/autofill/AutofillFramework/Application/src/main/res/layout/settings_activity.xml +++ b/input/autofill/AutofillFramework/Application/src/main/res/layout/settings_activity.xml @@ -1,71 +1,143 @@ <?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/settingsLayout" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:orientation="vertical"> + Copyright 2017 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. + --> +<android.support.v4.widget.NestedScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:scrollbarStyle="insideOverlay" + android:scrollbars="vertical" + android:importantForAutofill="no"> <LinearLayout android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - + android:layout_height="match_parent" + android:orientation="vertical" + android:paddingBottom="@dimen/spacing_large" + android:paddingTop="@dimen/spacing_large"> <TextView + style="@style/Settings.Header" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Number datasets: " /> + android:text="@string/settings_authentication_header"/> - <EditText - android:id="@+id/number_datasets" - android:layout_width="50dip" - android:layout_height="wrap_content" - android:inputType="number" - android:maxLength="1" /> - </LinearLayout> + <LinearLayout + android:id="@+id/settings_auth_responses_container" + style="@style/Settings.Container" + android:layout_width="match_parent" + android:layout_height="wrap_content"> - <CheckBox - android:id="@+id/response_auth" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="Authenticate responses" /> + <TextView + android:id="@+id/settings_auth_responses_label" + style="@style/Settings.Label" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:importantForAccessibility="no" + android:text="@string/settings_authenticate_responses" /> - <CheckBox - android:id="@+id/dataset_auth" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="Authenticate datasets" /> + <Switch + android:id="@+id/settings_auth_responses_switch" + style="@style/Settings.Switch" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minHeight="@dimen/a11y_min_touch_target_dimen" + android:layout_marginStart="@dimen/padding_normal" /> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> + </LinearLayout> - <Button - android:id="@+id/cancel" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Cancel" /> + <LinearLayout + android:id="@+id/settings_auth_datasets_container" + style="@style/Settings.Container" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/settings_auth_datasets_label" + style="@style/Settings.Label" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:importantForAccessibility="no" + android:text="@string/settings_authenticate_datasets" /> + + <Switch + android:id="@+id/settings_auth_datasets_switch" + style="@style/Settings.Switch" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minHeight="@dimen/a11y_min_touch_target_dimen" + android:layout_marginStart="@dimen/padding_normal" /> + + </LinearLayout> + + <LinearLayout + android:id="@+id/settings_auth_credentials_container" + style="@style/Settings.Container" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/settings_auth_credentials_label" + style="@style/Settings.Label" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/settings_auth_credentials_label" /> - <Button - android:id="@+id/save" + <ImageView + android:id="@+id/settings_auth_credentials_icon" + style="@style/Settings.Switch" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minHeight="@dimen/a11y_min_touch_target_dimen" + android:layout_marginStart="@dimen/padding_normal" + android:src="@drawable/ic_person_black_24dp"/> + </LinearLayout> + + <TextView + style="@style/Settings.Header" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Save" /> + android:paddingTop="@dimen/spacing_normal" + android:text="@string/settings_data_header"/> + + <LinearLayout + android:id="@+id/settings_clear_data_container" + style="@style/Settings.Container" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/settings_clear_data_label" + style="@style/Settings.Label" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/settings_clear_data_label" /> + + <ImageView + android:id="@+id/settings_clear_data_icon" + style="@style/Settings.Switch" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minHeight="@dimen/a11y_min_touch_target_dimen" + android:layout_marginStart="@dimen/padding_normal" + android:src="@drawable/ic_delete_forever_black_24dp"/> + </LinearLayout> </LinearLayout> -</LinearLayout>
\ No newline at end of file +</android.support.v4.widget.NestedScrollView> diff --git a/input/autofill/AutofillFramework/Application/src/main/res/layout/settings_authentication_dialog.xml b/input/autofill/AutofillFramework/Application/src/main/res/layout/settings_authentication_dialog.xml new file mode 100644 index 00000000..edb293f1 --- /dev/null +++ b/input/autofill/AutofillFramework/Application/src/main/res/layout/settings_authentication_dialog.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<EditText xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/master_password_field" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="@dimen/spacing_normal" + android:importantForAutofill="no" + android:padding="@dimen/spacing_normal"> + + <requestFocus /> +</EditText> diff --git a/input/autofill/AutofillFramework/Application/src/main/res/values/dimens.xml b/input/autofill/AutofillFramework/Application/src/main/res/values/dimens.xml index d9e5ea5c..961725d5 100644 --- a/input/autofill/AutofillFramework/Application/src/main/res/values/dimens.xml +++ b/input/autofill/AutofillFramework/Application/src/main/res/values/dimens.xml @@ -19,4 +19,10 @@ <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> + <dimen name="spacing_normal">8dp</dimen> + <dimen name="spacing_micro">4dp</dimen> + <dimen name="padding_normal">16dp</dimen> + <dimen name="padding_normal_button">12dp</dimen> + <dimen name="spacing_large">32dp</dimen> + <dimen name="a11y_min_touch_target_dimen">48dp</dimen> </resources> diff --git a/input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml b/input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml index 71c5bede..b5611ae1 100644 --- a/input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml +++ b/input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml @@ -27,6 +27,23 @@ <string name="credit_card_number_label">CC Number</string> <string name="credit_card_expiration_label">CC Exp</string> <string name="credit_card_security_code_label">CC Security Code</string> + <string name="settings_cancel">Cancel</string> + <string name="settings_save">Save</string> + <string name="settings_authenticate_responses">Authenticate responses</string> + <string name="settings_authenticate_datasets">Authenticate datasets</string> + <string name="settings_clear_data_label">Clear all data (including credentials)</string> + <string name="settings_clear_data_confirmation">Are you sure you want to delete all autofill + data from the sample service? + </string> + <string name="settings_clear_data_confirmation_title">Confirmation</string> + <string name="ok">OK</string> + <string name="cancel">Cancel</string> + <string name="settings_authentication_header">Authentication</string> + <string name="settings_data_header">Data</string> + <string name="settings_auth_credentials_label">Update credentials</string> + <string name="settings_auth_enter_current_password">Enter current password</string> + <string name="settings_auth_enter_new_password">Enter new password</string> + <string name="settings_auth_change_credentials_title">Change credentials</string> <string-array name="month_array"> <item>Jan</item> <item>Feb</item> diff --git a/input/autofill/AutofillFramework/Application/src/main/res/values/styles.xml b/input/autofill/AutofillFramework/Application/src/main/res/values/styles.xml new file mode 100644 index 00000000..73fccaf3 --- /dev/null +++ b/input/autofill/AutofillFramework/Application/src/main/res/values/styles.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="Settings.Label" parent=""> + <item name="android:ellipsize">end</item> + <item name="android:lines">1</item> + <item name="android:paddingBottom">@dimen/spacing_normal</item> + <item name="android:paddingTop">@dimen/spacing_normal</item> + </style> + <style name="Settings.Container" parent=""> + <item name="android:background">?android:selectableItemBackground</item> + <item name="android:gravity">center_vertical</item> + <item name="android:minHeight">?android:listPreferredItemHeightSmall</item> + <item name="android:orientation">horizontal</item> + <item name="android:paddingEnd">?android:listPreferredItemPaddingEnd</item> + <item name="android:paddingStart">?android:listPreferredItemPaddingStart</item> + </style> + <style name="Settings.Switch" parent=""> + <!-- We make the parent view clickable instead for better touch feedback --> + <item name="android:background">@null</item> + <item name="android:clickable">false</item> + </style> + + <style name="Settings.Header" parent="@style/TextAppearance.AppCompat.Large"> + <item name="android:paddingStart">?android:listPreferredItemPaddingStart</item> + <item name="android:paddingBottom">@dimen/spacing_normal</item> + </style> +</resources>
\ No newline at end of file |