aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Sigelbaum <sigelbaum@google.com>2017-05-11 23:44:42 -0700
committerDouglas Sigelbaum <sigelbaum@google.com>2017-05-16 18:06:48 -0700
commit5525a586f56baeb2310dbacfe34a96afd3dd3f0f (patch)
tree6c76b03f8e46b64ff4337a48880f3381b918170f
parent283fd752a6066e4d91bf668a5eacc38f29d411e7 (diff)
downloadandroid-5525a586f56baeb2310dbacfe34a96afd3dd3f0f.tar.gz
Added hints and save info to Autofill service.
Test: manual Bug: 38182790 Change-Id: Ifd0b6b970e5357814376149bc76457ec33ec1e1a
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml2
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.java6
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/LoginActivity.java14
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AuthActivity.java24
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillData.java72
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillField.java60
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillHelper.java113
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/LoginCredential.java60
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/MyAutofillService.java47
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/StructureParser.java56
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/AutofillRepository.java33
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/LocalAutofillRepository.java69
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/AutofillField.java118
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/DatasetModel.java (renamed from input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/DatasetModel.java)2
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/LoginCredential.java95
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/MyPreferences.java (renamed from input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/MyPreferences.java)14
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/SettingsActivity.java (renamed from input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/SettingsActivity.java)12
-rw-r--r--input/autofill/AutofillFramework/gradle/wrapper/gradle-wrapper.properties2
18 files changed, 486 insertions, 313 deletions
diff --git a/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml b/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml
index e6985b01..a9f3558d 100644
--- a/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml
+++ b/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml
@@ -60,7 +60,7 @@
Not necessary for a real service.
-->
<activity
- android:name=".service.SettingsActivity"
+ android:name=".service.settings.SettingsActivity"
android:exported="true"
android:label="@string/settings_name"
android:taskAffinity=".SettingsActivity" >
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.java
index bec2c25b..6b01039e 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CustomVirtualView.java
@@ -241,13 +241,11 @@ public class CustomVirtualView extends View {
private final class Line {
+ // Boundaries of the text field, relative to the CustomView
+ final Rect bounds = new Rect();
private Item labelItem;
private Item fieldTextItem;
private String idEntry;
-
- // Boundaries of the text field, relative to the CustomView
- final Rect bounds = new Rect();
-
private boolean focused;
private Line(String idEntry, String label, String text, boolean sanitized) {
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 9a1e00cd..cb7192eb 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
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
+import android.view.autofill.AutofillManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
@@ -44,10 +45,14 @@ public class LoginActivity extends Activity {
setContentView(R.layout.login_activity);
- 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 = findViewById(R.id.login);
+ mClearButton = findViewById(R.id.clear);
+ mUsernameEditText = findViewById(R.id.usernameField);
+ mPasswordEditText = findViewById(R.id.passwordField);
+ mUsernameEditText.setAutofillHints(View.AUTOFILL_HINT_USERNAME);
+ mPasswordEditText.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);
+ mUsernameEditText.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES);
+ mPasswordEditText.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES);
mLoginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -77,6 +82,7 @@ public class LoginActivity extends Activity {
if (valid) {
Intent intent = WelcomeActivity.getStartActivityIntent(LoginActivity.this);
startActivity(intent);
+ finish();
} else {
Toast.makeText(this, "Authentication failed.", Toast.LENGTH_SHORT).show();
}
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 2ea3f1aa..356fa678 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
@@ -29,14 +29,17 @@ import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.autofill.AutofillId;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.example.android.autofillframework.R;
+import com.example.android.autofillframework.service.datasource.LocalAutofillRepository;
+import com.example.android.autofillframework.service.model.AutofillField;
+import com.example.android.autofillframework.service.model.LoginCredential;
-import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
import static android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE;
import static android.view.autofill.AutofillManager.EXTRA_AUTHENTICATION_RESULT;
@@ -133,12 +136,11 @@ public class AuthActivity extends Activity {
AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
StructureParser parser = new StructureParser(structure);
parser.parse();
- AutofillId usernameId = parser.getUsernameField().getId();
- AutofillId passwordId = parser.getPasswordField().getId();
- Map<String, LoginCredential> loginCredentialMap =
- AutofillData.getInstance().getCredentialsMap(this);
- if (usernameId == null || passwordId == null || loginCredentialMap == null ||
- loginCredentialMap.isEmpty()) {
+ List<AutofillField> autofillFields = parser.getAutofillFields();
+ HashMap<String, LoginCredential> loginCredentialMap =
+ LocalAutofillRepository.getInstance(this).getLoginCredentials();
+ int saveType = parser.getSaveTypes();
+ if (loginCredentialMap == null || loginCredentialMap.isEmpty()) {
Log.d(TAG, "No Autofill data found for this Activity.");
return;
}
@@ -146,8 +148,8 @@ public class AuthActivity extends Activity {
if (forResponse) {
// The response protected by auth, so we can send the entire response since we
// passed auth.
- FillResponse response = AutofillHelper.newCredentialsResponse(this, false, usernameId,
- passwordId, loginCredentialMap);
+ FillResponse response = AutofillHelper
+ .newCredentialResponse(this, false, autofillFields, saveType, loginCredentialMap);
if (response != null) {
mReplyIntent.putExtra(EXTRA_AUTHENTICATION_RESULT, response);
}
@@ -157,7 +159,7 @@ public class AuthActivity extends Activity {
if (loginCredentialMap.containsKey(datasetName)) {
LoginCredential credential = loginCredentialMap.get(datasetName);
Dataset dataset = AutofillHelper
- .newCredentialDataset(this, credential, usernameId, passwordId);
+ .newCredentialDataset(this, autofillFields, credential);
mReplyIntent.putExtra(EXTRA_AUTHENTICATION_RESULT, dataset);
}
}
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillData.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillData.java
deleted file mode 100644
index 9eb41147..00000000
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillData.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.service;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import static com.example.android.autofillframework.CommonUtil.TAG;
-
-/**
- * Singleton holding Autofill data. In this simple Autofill service, it only holds LoginCredentials
- * for every client app that uses the service.
- */
-final class AutofillData {
-
- private static AutofillData sAutoFillData;
-
- // Structure: {<packageName> : {<datasetName> : <loginCredential object>, ...}, ...}
- private final Map<String, Map<String, LoginCredential>> mLoginCredentials =
- new LinkedHashMap<>();
-
- private AutofillData() {
- }
-
- public static AutofillData getInstance() {
- if (sAutoFillData == null) {
- sAutoFillData = new AutofillData();
- }
- return sAutoFillData;
- }
-
- /**
- * Get all login credentials associated with the caller's package.
- */
- public Map<String, LoginCredential> getCredentialsMap(Context context) {
- int numDatasets = MyPreferences.getInstance(context).getNumberDatasets();
- for (int i = 0; i < numDatasets; i++) {
- LoginCredential loginCredential =
- new LoginCredential("user" + i, "user" + i);
- updateCredentials(context.getPackageName(), loginCredential);
- }
- return mLoginCredentials.get(context.getPackageName());
- }
-
- /**
- * Add a loginCredential mapped to the caller's package (maintaining idempotency).
- */
- public void updateCredentials(String packageName, LoginCredential loginCredential) {
- if (!mLoginCredentials.containsKey(packageName)) {
- mLoginCredentials.put(packageName, new LinkedHashMap<String, LoginCredential>());
- }
- mLoginCredentials.get(packageName).put(loginCredential.getDatasetName(), loginCredential);
- Log.d(TAG, "Creating credentials for " + packageName + ":" +
- loginCredential.getDatasetName());
- }
-}
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillField.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillField.java
deleted file mode 100644
index 450480b4..00000000
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillField.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.service;
-
-import android.app.assist.AssistStructure;
-import android.view.autofill.AutofillId;
-
-/**
- * Class that represents a field that can be autofilled. It will contain a description
- * (what type data the field holds), an AutoFillId (an ID unique to the rest of the ViewStructure),
- * and a value (what data is currently in the field).
- */
-public class AutofillField {
- private final String description;
- private AutofillId id;
-
- // For simplicity, we will only support text values.
- private String value;
-
- public AutofillField(String description) {
- this.description = description;
- }
-
- void setFrom(AssistStructure.ViewNode view) {
- id = view.getAutofillId();
- CharSequence text = view.getText();
- value = text == null ? null : text.toString();
- }
-
- public String getDescription() {
- return description;
- }
-
- public AutofillId getId() {
- return id;
- }
-
- public String getValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return "AutofillField: [id=" + id + ", value=" + value + "]";
- }
-
-}
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillHelper.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillHelper.java
index 8b6297e8..8087843e 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillHelper.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/AutofillHelper.java
@@ -19,14 +19,19 @@ import android.content.Context;
import android.content.IntentSender;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
+import android.service.autofill.SaveInfo;
import android.util.Log;
+import android.view.View;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.widget.RemoteViews;
import com.example.android.autofillframework.R;
+import com.example.android.autofillframework.service.model.AutofillField;
+import com.example.android.autofillframework.service.model.LoginCredential;
-import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
import java.util.Set;
import static com.example.android.autofillframework.CommonUtil.TAG;
@@ -35,61 +40,81 @@ import static com.example.android.autofillframework.CommonUtil.TAG;
* This is a class containing helper methods for building Autofill Datasets and Responses.
*/
public final class AutofillHelper {
+
/**
- * Wraps autofill data in a Dataset object which can then be sent back to the client View.
+ * Wraps autofill data in a LoginCredential Dataset object which can then be sent back to the
+ * client View.
*/
- public static Dataset newCredentialDataset(Context context,
- LoginCredential loginCredential, AutofillId usernameId,
- AutofillId passwordId) {
- String datasetName = loginCredential.getDatasetName();
- RemoteViews presentation = new RemoteViews(context.getPackageName(),
- R.layout.list_item);
- presentation.setTextViewText(R.id.text1, datasetName);
- Dataset.Builder datasetBuilder = new Dataset.Builder(presentation);
- datasetBuilder.setValue(usernameId, AutofillValue.forText(loginCredential.getUsername()));
- datasetBuilder.setValue(passwordId, AutofillValue.forText(loginCredential.getPassword()));
+ public static Dataset newCredentialDataset(Context context, List<AutofillField> autofillFields, LoginCredential loginCredential) {
+ Dataset.Builder datasetBuilder = new Dataset.Builder
+ (newRemoteViews(context.getPackageName(), loginCredential.getDatasetName()));
+ // Not using enhanced for loop on Collection to prevent extra iterator allocation.
+ for (int i = 0; i < autofillFields.size(); i++) {
+ AutofillField field = autofillFields.get(i);
+ boolean shouldBreak = false;
+ for (String autofillHint : field.getHints()) {
+ switch (autofillHint) {
+ case View.AUTOFILL_HINT_USERNAME:
+ datasetBuilder.setValue(field.getId(), AutofillValue.forText(loginCredential.getUsername()));
+ shouldBreak = true;
+ break;
+ case View.AUTOFILL_HINT_PASSWORD:
+ datasetBuilder.setValue(field.getId(), AutofillValue.forText(loginCredential.getPassword()));
+ shouldBreak = true;
+ break;
+ }
+ if (shouldBreak) {
+ break;
+ }
+ }
+ }
return datasetBuilder.build();
}
+ public static RemoteViews newRemoteViews(String packageName, String remoteViewsText) {
+ RemoteViews presentation = new RemoteViews(packageName, R.layout.list_item);
+ presentation.setTextViewText(R.id.text1, remoteViewsText);
+ return presentation;
+ }
+
/**
* Wraps autofill data in a Response object (essentially a series of Datasets) which can then
* be sent back to the client View.
*/
- public static FillResponse newCredentialsResponse(Context context,
- boolean datasetAuth, AutofillId usernameId, AutofillId passwordId,
- Map<String, LoginCredential> credentialsMap) {
+ public static FillResponse newCredentialResponse(Context context, boolean datasetAuth,
+ List<AutofillField> autofillFields, int saveType,
+ HashMap<String, LoginCredential> loginCredentialMap) {
FillResponse.Builder responseBuilder = new FillResponse.Builder();
- if (usernameId == null || passwordId == null ||
- credentialsMap == null || credentialsMap.isEmpty()) {
- // Activity does not have usernameField and passwordField, can't do anything
- return null;
- } else {
- int numReplies = 0;
- Set<Map.Entry<String, LoginCredential>> credentialSet = credentialsMap.entrySet();
- for (Map.Entry<String, LoginCredential> credential : credentialSet) {
- if (datasetAuth) {
- String datasetName = credential.getKey();
- RemoteViews presentation = new RemoteViews(context.getPackageName(),
- R.layout.list_item);
- presentation.setTextViewText(R.id.text1, datasetName);
- Dataset.Builder datasetBuilder = new Dataset.Builder(presentation);
- IntentSender sender =
- AuthActivity.getAuthIntentSenderForDataset(context, datasetName);
- datasetBuilder.setAuthentication(sender);
- responseBuilder.addDataset(datasetBuilder.build());
- } else {
- Dataset dataset = newCredentialDataset(context,
- credential.getValue(), usernameId, passwordId);
- responseBuilder.addDataset(dataset);
- }
- numReplies++;
- }
- if (numReplies > 0) {
- return responseBuilder.build();
+ Set<String> datasetNames = loginCredentialMap.keySet();
+ for (String datasetName : datasetNames) {
+ LoginCredential loginCredential = loginCredentialMap.get(datasetName);
+ if (datasetAuth) {
+ Dataset.Builder datasetBuilder =
+ new Dataset.Builder(newRemoteViews(context.getPackageName(), loginCredential.getDatasetName()));
+ IntentSender sender =
+ AuthActivity.getAuthIntentSenderForDataset(context, loginCredential.getDatasetName());
+ datasetBuilder.setAuthentication(sender);
+ responseBuilder.addDataset(datasetBuilder.build());
} else {
- Log.d(TAG, "No Autofill data found.");
- return null;
+ Dataset dataset = newCredentialDataset(context, autofillFields, loginCredential);
+ responseBuilder.addDataset(dataset);
}
}
+ if (saveType != 0) {
+ AutofillId[] autofillIds = getAutofillIds(autofillFields);
+ responseBuilder.setSaveInfo(new SaveInfo.Builder(saveType, autofillIds).build());
+ return responseBuilder.build();
+ } else {
+ Log.d(TAG, "No Autofill data found.");
+ return null;
+ }
+ }
+
+ public static AutofillId[] getAutofillIds(List<AutofillField> autofillFields) {
+ AutofillId[] autofillIds = new AutofillId[autofillFields.size()];
+ for (int i = 0; i < autofillFields.size(); i++) {
+ autofillIds[i] = autofillFields.get(i).getId();
+ }
+ return autofillIds;
}
}
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/LoginCredential.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/LoginCredential.java
deleted file mode 100644
index 4e3efe9a..00000000
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/LoginCredential.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.service;
-
-
-public class LoginCredential implements DatasetModel {
- private final String username;
- private final String password;
-
- LoginCredential(String username, String password) {
- this.username = username;
- this.password = password;
- }
-
- @Override
- public String getDatasetName() {
- return username;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- LoginCredential that = (LoginCredential) o;
-
- if (username != null ? !username.equals(that.username) : that.username != null) {
- return false;
- }
- return password != null ? password.equals(that.password) : that.password == null;
- }
-
- @Override
- public int hashCode() {
- int result = username != null ? username.hashCode() : 0;
- result = 31 * result + (password != null ? password.hashCode() : 0);
- return result;
- }
-
- public String getUsername() {
- return username;
- }
-
- public String getPassword() {
- return password;
- }
-}
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/MyAutofillService.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/MyAutofillService.java
index a502f8e6..aa0d38e3 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/MyAutofillService.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/MyAutofillService.java
@@ -31,10 +31,14 @@ import android.view.autofill.AutofillId;
import android.widget.RemoteViews;
import com.example.android.autofillframework.R;
+import com.example.android.autofillframework.service.datasource.LocalAutofillRepository;
+import com.example.android.autofillframework.service.model.AutofillField;
+import com.example.android.autofillframework.service.model.LoginCredential;
+import com.example.android.autofillframework.service.settings.MyPreferences;
-import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+import java.util.Set;
import static com.example.android.autofillframework.CommonUtil.TAG;
import static com.example.android.autofillframework.CommonUtil.bundleToString;
@@ -61,6 +65,7 @@ public class MyAutofillService extends AutofillService {
Log.d(TAG, "onFillRequest(): data=" + bundleToString(data));
// Temporary hack for disabling autofill for components in this autofill service.
+ // i.e. we don't want to autofill components in AuthActivity.
if (structure.getActivityComponent().toShortString()
.contains("com.example.android.autofillframework.service")) {
callback.onSuccess(null);
@@ -75,8 +80,11 @@ public class MyAutofillService extends AutofillService {
// Parse AutoFill data in Activity
StructureParser parser = new StructureParser(structure);
parser.parse();
- AutofillId usernameId = parser.getUsernameField().getId();
- AutofillId passwordId = parser.getPasswordField().getId();
+ List<AutofillField> autofillFields = parser.getAutofillFields();
+ HashMap<String, LoginCredential> loginCredentialMap =
+ LocalAutofillRepository.getInstance(this).getLoginCredentials();
+ AutofillId[] autofillIds = AutofillHelper.getAutofillIds(autofillFields);
+ int saveTypes = parser.getSaveTypes();
FillResponse.Builder responseBuilder = new FillResponse.Builder();
// Check user's settings for authenticating Responses and Datasets
@@ -85,26 +93,19 @@ public class MyAutofillService extends AutofillService {
// If the entire Autofill Response is authenticated, AuthActivity is used
// to generate Response
IntentSender sender = AuthActivity.getAuthIntentSenderForResponse(this);
- RemoteViews presentation = new RemoteViews(getPackageName(), R.layout.list_item);
- presentation.setTextViewText(R.id.text1, getString(R.string.autofill_sign_in_prompt));
- responseBuilder.setAuthentication(new AutofillId[]{usernameId, passwordId},
- sender, presentation);
+ RemoteViews presentation = AutofillHelper
+ .newRemoteViews(getPackageName(), getString(R.string.autofill_sign_in_prompt));
+ responseBuilder.setAuthentication
+ (autofillIds, sender, presentation);
callback.onSuccess(responseBuilder.build());
} else {
boolean datasetAuth = MyPreferences.getInstance(this).isDatasetAuth();
- Map<String, LoginCredential> credentialsMap =
- AutofillData.getInstance().getCredentialsMap(this);
- if (usernameId == null || passwordId == null ||
- credentialsMap == null || credentialsMap.isEmpty()) {
- // Activity does not have usernameField and passwordField fields, or service does not
- // have any usernameField and passwordField autofill data.
- Log.d(TAG, "No Autofill data found for this Activity");
- callback.onSuccess(null);
- return;
+ FillResponse response = null;
+ if (parser.isLoginPage()) {
+ response = AutofillHelper.newCredentialResponse(
+ this, datasetAuth, autofillFields, saveTypes, loginCredentialMap);
}
- FillResponse response = AutofillHelper.newCredentialsResponse(
- this, datasetAuth, usernameId, passwordId, credentialsMap);
callback.onSuccess(response);
}
}
@@ -114,14 +115,10 @@ public class MyAutofillService extends AutofillService {
List<FillContext> context = request.getFillContexts();
final AssistStructure structure = context.get(context.size() - 1).getStructure();
final Bundle data = request.getClientState();
- Log.d(TAG, "onSaveFillRequest(): data=" + bundleToString(data));
+ Log.d(TAG, "onSaveRequest(): data=" + bundleToString(data));
StructureParser parser = new StructureParser(structure);
parser.parse();
- String packageName = structure.getActivityComponent().getPackageName();
- String username = parser.getUsernameField().getValue();
- String password = parser.getPasswordField().getValue();
- LoginCredential loginCredential = new LoginCredential(username, password);
- AutofillData.getInstance().updateCredentials(packageName, loginCredential);
+ List<AutofillField> autofillFields = parser.getAutofillFields();
}
@Override
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/StructureParser.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/StructureParser.java
index 11f80faf..ea3f7630 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/StructureParser.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/StructureParser.java
@@ -19,6 +19,14 @@ import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.WindowNode;
import android.util.Log;
+import android.view.View;
+
+import com.example.android.autofillframework.service.datasource.AutofillRepository;
+import com.example.android.autofillframework.service.model.AutofillField;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
import static com.example.android.autofillframework.CommonUtil.TAG;
@@ -30,14 +38,13 @@ import static com.example.android.autofillframework.CommonUtil.TAG;
*/
final class StructureParser {
- // This simple AutoFill service is capable of parsing these fields:
- private final AutofillField usernameField = new AutofillField("usernameField");
- private final AutofillField passwordField = new AutofillField("passwordField");
- private final AssistStructure structure;
-
+ private AssistStructure structure;
+ private int mSaveTypes = 0;
+ private List<AutofillField> mAutofillFields;
StructureParser(AssistStructure structure) {
this.structure = structure;
+ mAutofillFields = new ArrayList<>();
}
/**
@@ -46,23 +53,30 @@ final class StructureParser {
*/
void parse() {
Log.d(TAG, "Parsing structure for " + structure.getActivityComponent());
- final int nodes = structure.getWindowNodeCount();
+ int nodes = structure.getWindowNodeCount();
for (int i = 0; i < nodes; i++) {
WindowNode node = structure.getWindowNodeAt(i);
ViewNode view = node.getRootViewNode();
parseLocked(view);
}
+ updateSaveTypes();
+ }
+
+ private void updateSaveTypes() {
+ mSaveTypes = 0;
+ for (int i = 0; i < mAutofillFields.size(); i++) {
+ AutofillField field = mAutofillFields.get(i);
+ mSaveTypes |= field.getSaveType();
+ }
}
private void parseLocked(ViewNode view) {
- final String resourceId = view.getIdEntry();
- Log.d(TAG, "resourceId == " + resourceId);
- if (resourceId != null && resourceId.equals(usernameField.getDescription())) {
- usernameField.setFrom(view);
- } else if (resourceId != null && resourceId.equals(passwordField.getDescription())) {
- passwordField.setFrom(view);
+ if (view.getAutofillType() != View.AUTOFILL_TYPE_NONE) {
+ AutofillField field = new AutofillField();
+ field.setFrom(view);
+ mAutofillFields.add(field);
}
- final int childrenSize = view.getChildCount();
+ int childrenSize = view.getChildCount();
if (childrenSize > 0) {
for (int i = 0; i < childrenSize; i++) {
parseLocked(view.getChildAt(i));
@@ -70,11 +84,19 @@ final class StructureParser {
}
}
- public AutofillField getUsernameField() {
- return usernameField;
+ public List<AutofillField> getAutofillFields() {
+ return mAutofillFields;
+ }
+
+ public int getSaveTypes() {
+ return mSaveTypes;
}
- public AutofillField getPasswordField() {
- return passwordField;
+ /**
+ * Is this View structure
+ */
+ public boolean isLoginPage() {
+ // TODO remove this.
+ return true;
}
}
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
new file mode 100644
index 00000000..b10bc8ef
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/AutofillRepository.java
@@ -0,0 +1,33 @@
+/*
+ * 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.service.datasource;
+
+import com.example.android.autofillframework.service.model.LoginCredential;
+
+import java.util.HashMap;
+
+public interface AutofillRepository {
+
+ /**
+ * Gets LoginCredential that was originally saved with this {@code datasetName}.
+ */
+ HashMap<String, LoginCredential> getLoginCredentials();
+
+ /**
+ * Saves LoginCredential under this datasetName.
+ */
+ void saveLoginCredential(LoginCredential loginCredential);
+}
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
new file mode 100644
index 00000000..6c00c81f
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/datasource/LocalAutofillRepository.java
@@ -0,0 +1,69 @@
+package com.example.android.autofillframework.service.datasource;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.ArraySet;
+
+import com.example.android.autofillframework.service.model.LoginCredential;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Set;
+
+/**
+ * Singleton autofill data repository, that stores autofill fields to SharedPreferences.
+ * DISCLAIMER, you should not store sensitive fields like user data unencrypted. This is only done
+ * here for simplicity and learning purposes.
+ */
+public class LocalAutofillRepository implements AutofillRepository {
+ private static final String SHARED_PREF_KEY = "com.example.android.autofillframework.service";
+ private static final String LOGIN_CREDENTIAL_DATASETS_KEY = "loginCredentialDatasetNames";
+
+ private static LocalAutofillRepository sInstance;
+
+ private final SharedPreferences mPrefs;
+ private int datasetNumber = 0;
+
+ private LocalAutofillRepository(Context context) {
+ mPrefs = context.getSharedPreferences(SHARED_PREF_KEY,
+ Context.MODE_PRIVATE);
+ }
+
+ public static LocalAutofillRepository getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new LocalAutofillRepository(context);
+ }
+ return sInstance;
+ }
+
+ @Override
+ public HashMap<String, LoginCredential> getLoginCredentials() {
+ try {
+ HashMap<String, LoginCredential> loginCredentials = new HashMap<>();
+ Set<String> loginCredentialStringSet =
+ mPrefs.getStringSet(LOGIN_CREDENTIAL_DATASETS_KEY, new ArraySet<String>());
+ for (String loginCredentialString : loginCredentialStringSet) {
+ LoginCredential loginCredential = LoginCredential
+ .fromJson(new JSONObject(loginCredentialString));
+ if (loginCredential != null) {
+ loginCredentials.put(loginCredential.getDatasetName(), loginCredential);
+ }
+ }
+ return loginCredentials;
+ } catch (JSONException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public void saveLoginCredential(LoginCredential loginCredential) {
+ String datasetName = "dataset-" + datasetNumber++;
+ loginCredential.setDatasetName(datasetName);
+ Set<String> loginCredentialStringSet =
+ mPrefs.getStringSet(LOGIN_CREDENTIAL_DATASETS_KEY, new ArraySet<String>());
+ loginCredentialStringSet.add(loginCredential.toJson().toString());
+ mPrefs.edit().putStringSet(LOGIN_CREDENTIAL_DATASETS_KEY, loginCredentialStringSet).apply();
+ }
+} \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/AutofillField.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/AutofillField.java
new file mode 100644
index 00000000..648eb797
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/AutofillField.java
@@ -0,0 +1,118 @@
+/*
+ * 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.service.model;
+
+import android.app.assist.AssistStructure;
+import android.service.autofill.SaveInfo;
+import android.view.View;
+import android.view.autofill.AutofillId;
+
+/**
+ * Class that represents a field that can be autofilled. It will contain a description
+ * (what type data the field holds), an AutoFillId (an ID unique to the rest of the ViewStructure),
+ * and a value (what data is currently in the field).
+ */
+public class AutofillField {
+ private int saveType = 0;
+ private String[] hints;
+ private AutofillId id;
+
+ // For simplicity, we will only support text values.
+ // TODO support multiple value types.
+ private String value;
+
+ public AutofillField() {
+ }
+
+ public void setFrom(AssistStructure.ViewNode view) {
+ id = view.getAutofillId();
+ setHints(view.getAutofillHints());
+ }
+
+ public String[] getHints() {
+ return hints;
+ }
+
+ public void setHints(String[] hints) {
+ this.hints = hints;
+ updateSaveTypeFromHints();
+ }
+
+ public int getSaveType() {
+ return saveType;
+ }
+
+ public AutofillId getId() {
+ return id;
+ }
+
+ public void setId(AutofillId id) {
+ this.id = id;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "AutofillField: [id=" + id + ", value=" + value + "]";
+ }
+
+ private void updateSaveTypeFromHints() {
+ saveType = 0;
+ if(hints == null) {
+ return;
+ }
+ for (String hint : hints) {
+ switch (hint) {
+ case View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE:
+ case View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY:
+ case View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH:
+ case View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR:
+ case View.AUTOFILL_HINT_CREDIT_CARD_NUMBER:
+ case View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE:
+ saveType |= SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD;
+ break;
+ case View.AUTOFILL_HINT_EMAIL_ADDRESS:
+ saveType |= SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS;
+ break;
+ case View.AUTOFILL_HINT_NAME:
+ saveType |= SaveInfo.SAVE_DATA_TYPE_GENERIC;
+ break;
+ case View.AUTOFILL_HINT_PASSWORD:
+ saveType |= SaveInfo.SAVE_DATA_TYPE_PASSWORD;
+ saveType &= ~SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS;
+ saveType &= ~SaveInfo.SAVE_DATA_TYPE_USERNAME;
+ break;
+ case View.AUTOFILL_HINT_PHONE:
+ saveType |= SaveInfo.SAVE_DATA_TYPE_GENERIC;
+ break;
+ case View.AUTOFILL_HINT_POSTAL_ADDRESS:
+ case View.AUTOFILL_HINT_POSTAL_CODE:
+ saveType |= SaveInfo.SAVE_DATA_TYPE_ADDRESS;
+ break;
+ case View.AUTOFILL_HINT_USERNAME:
+ saveType |= SaveInfo.SAVE_DATA_TYPE_USERNAME;
+ break;
+ }
+ }
+ }
+}
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/DatasetModel.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/DatasetModel.java
index c2c9e662..218e916b 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/DatasetModel.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/DatasetModel.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.autofillframework.service;
+package com.example.android.autofillframework.service.model;
/**
* Blueprint for Objects that are the underlying data model for Autofill Datasets. In this basic
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/LoginCredential.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/LoginCredential.java
new file mode 100644
index 00000000..742c7582
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/model/LoginCredential.java
@@ -0,0 +1,95 @@
+/*
+ * 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.service.model;
+
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class LoginCredential implements DatasetModel {
+ private final String username;
+ private final String password;
+ private String datasetName;
+
+ LoginCredential(String username, String password) {
+ this(username, password, null);
+ }
+
+ LoginCredential(String username, String password, String datasetName) {
+ this.username = username;
+ this.password = password;
+ }
+
+ public static LoginCredential fromJson(JSONObject jsonObject) {
+ LoginCredential loginCredential = null;
+ try {
+ loginCredential = new LoginCredential(jsonObject.getString("username"),
+ jsonObject.getString("password"));
+ } catch (JSONException e) {
+ return null;
+ }
+ return loginCredential;
+ }
+
+ @Override
+ public String getDatasetName() {
+ return username;
+ }
+
+ public void setDatasetName(String datasetName) {
+ this.datasetName = datasetName;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public JSONObject toJson() {
+ JSONObject jsonObject = new JSONObject();
+ try {
+ jsonObject.put("username", username);
+ jsonObject.put("password", password);
+ } catch (JSONException e) {
+ return null;
+ }
+ return jsonObject;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ LoginCredential that = (LoginCredential) o;
+
+ if (!username.equals(that.username)) return false;
+ if (!password.equals(that.password)) return false;
+ return datasetName != null ? datasetName.equals(that.datasetName) : that.datasetName == null;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = username.hashCode();
+ result = 31 * result + password.hashCode();
+ result = 31 * result + (datasetName != null ? datasetName.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/MyPreferences.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/MyPreferences.java
index 9533da79..92fac4ec 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/MyPreferences.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/MyPreferences.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.autofillframework.service;
+package com.example.android.autofillframework.service.settings;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
-final class MyPreferences {
+public class MyPreferences {
private static final String TAG = "MyPreferences";
private static final String PREF_NUMBER_DATASET = "number_datasets";
@@ -33,7 +33,7 @@ final class MyPreferences {
Context.MODE_PRIVATE);
}
- static MyPreferences getInstance(Context context) {
+ public static MyPreferences getInstance(Context context) {
if (sInstance == null) {
sInstance = new MyPreferences(context);
}
@@ -43,14 +43,14 @@ final class MyPreferences {
/**
* Gets the number of {@link Dataset}s that should be added to a {@link FillResponse}.
*/
- int getNumberDatasets() {
+ public int getNumberDatasets() {
return mPrefs.getInt(PREF_NUMBER_DATASET, 2);
}
/**
* Gets whether {@link FillResponse}s should require authentication.
*/
- boolean isResponseAuth() {
+ public boolean isResponseAuth() {
return mPrefs.getBoolean(PREF_RESPONSE_AUTH, false);
}
@@ -58,11 +58,11 @@ final class MyPreferences {
/**
* Gets whether {@link Dataset}s should require authentication.
*/
- boolean isDatasetAuth() {
+ public boolean isDatasetAuth() {
return mPrefs.getBoolean(PREF_DATASET_AUTH, false);
}
- void bulkEdit(int numberDatasets, boolean responseAuth, boolean datasetAuth) {
+ public void bulkEdit(int numberDatasets, boolean responseAuth, boolean datasetAuth) {
Log.v(TAG, "bulk edit:" + numberDatasets + ":" + responseAuth + ":" + datasetAuth);
mPrefs.edit()
.putInt(PREF_NUMBER_DATASET, numberDatasets)
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/SettingsActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/SettingsActivity.java
index 599fed4f..e771d185 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/SettingsActivity.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/service/settings/SettingsActivity.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.example.android.autofillframework.service;
+package com.example.android.autofillframework.service.settings;
import android.app.Activity;
import android.os.Bundle;
@@ -39,11 +39,11 @@ public class SettingsActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
- mNumberDatasets = (EditText) findViewById(R.id.number_datasets);
- mResponseAuth = (CheckBox) findViewById(R.id.response_auth);
- mDatasetAuth = (CheckBox) findViewById(R.id.dataset_auth);
- mSave = (Button) findViewById(R.id.save);
- mCancel = (Button) findViewById(R.id.cancel);
+ 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 p = MyPreferences.getInstance(this);
diff --git a/input/autofill/AutofillFramework/gradle/wrapper/gradle-wrapper.properties b/input/autofill/AutofillFramework/gradle/wrapper/gradle-wrapper.properties
index 1081cc34..eaba3011 100644
--- a/input/autofill/AutofillFramework/gradle/wrapper/gradle-wrapper.properties
+++ b/input/autofill/AutofillFramework/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip