Use URL as package name for app/website settings and match Chrome using URL. But use site title for automatching attempts when URL match not found

This commit is contained in:
Matthew Wong 2015-12-31 03:47:51 -05:00
parent cdf27fc24d
commit 1c3a4fe763
6 changed files with 224 additions and 187 deletions

View file

@ -16,6 +16,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ListView; import android.widget.ListView;
import android.widget.RadioButton; import android.widget.RadioButton;
@ -27,7 +28,8 @@ import com.zeapo.pwdstore.R;
public class AutofillFragment extends DialogFragment { public class AutofillFragment extends DialogFragment {
private static final int MATCH_WITH = 777; private static final int MATCH_WITH = 777;
ArrayAdapter<String> adapter; private ArrayAdapter<String> adapter;
private boolean isWeb;
public AutofillFragment() { public AutofillFragment() {
} }
@ -37,28 +39,27 @@ public class AutofillFragment extends DialogFragment {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// this fragment is only created from the settings page (AutofillPreferenceActivity) // this fragment is only created from the settings page (AutofillPreferenceActivity)
// need to interact with the recyclerAdapter which is a member of activity // need to interact with the recyclerAdapter which is a member of activity
final AutofillPreferenceActivity callingActivity = (AutofillPreferenceActivity) getActivity(); AutofillPreferenceActivity callingActivity = (AutofillPreferenceActivity) getActivity();
LayoutInflater inflater = callingActivity.getLayoutInflater(); LayoutInflater inflater = callingActivity.getLayoutInflater();
final View view = inflater.inflate(R.layout.fragment_autofill, null); final View view = inflater.inflate(R.layout.fragment_autofill, null);
builder.setView(view); builder.setView(view);
String packageName = getArguments().getString("packageName", ""); String packageName = getArguments().getString("packageName");
String appName = getArguments().getString("appName", ""); String appName = getArguments().getString("appName");
isWeb = getArguments().getBoolean("isWeb");
final boolean isWebsite = appName.equals(packageName);
// set the dialog icon and title or webName editText // set the dialog icon and title or webName editText
String iconPackageName; String iconPackageName;
if (!isWebsite) { if (!isWeb) {
iconPackageName = packageName; iconPackageName = packageName;
builder.setTitle(appName); builder.setTitle(appName);
view.findViewById(R.id.webName).setVisibility(View.GONE); view.findViewById(R.id.webURL).setVisibility(View.GONE);
} else { } else {
iconPackageName = "com.android.browser"; iconPackageName = "com.android.browser";
builder.setTitle("Website"); builder.setTitle("Website");
((EditText) view.findViewById(R.id.webName)).setText(packageName); ((EditText) view.findViewById(R.id.webURL)).setText(packageName);
} }
try { try {
builder.setIcon(callingActivity.getPackageManager().getApplicationIcon(iconPackageName)); builder.setIcon(callingActivity.getPackageManager().getApplicationIcon(iconPackageName));
@ -89,13 +90,12 @@ public class AutofillFragment extends DialogFragment {
// set the existing preference, if any // set the existing preference, if any
SharedPreferences prefs; SharedPreferences prefs;
String preference; if (!isWeb) {
if (!isWebsite) {
prefs = getActivity().getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE); prefs = getActivity().getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE);
} else { } else {
prefs = getActivity().getApplicationContext().getSharedPreferences("autofill_web", Context.MODE_PRIVATE); prefs = getActivity().getApplicationContext().getSharedPreferences("autofill_web", Context.MODE_PRIVATE);
} }
preference = prefs.getString(packageName, ""); String preference = prefs.getString(packageName, "");
switch (preference) { switch (preference) {
case "": case "":
((RadioButton) view.findViewById(R.id.use_default)).toggle(); ((RadioButton) view.findViewById(R.id.use_default)).toggle();
@ -125,88 +125,108 @@ public class AutofillFragment extends DialogFragment {
view.findViewById(R.id.matchButton).setOnClickListener(matchPassword); view.findViewById(R.id.matchButton).setOnClickListener(matchPassword);
// write to preferences when OK clicked // write to preferences when OK clicked
final SharedPreferences.Editor editor = prefs.edit();
builder.setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() { builder.setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
String key;
String packageName = getArguments().getString("packageName", "");
if (!isWebsite) {
key = packageName;
} else {
key = ((EditText) view.findViewById(R.id.webName)).getText().toString();
// if key.equals("") show error
// if new packageName/appName/website name/website title/key
// is different than old, remove the old one. Basically,
// "edit" the old one.
if (!key.equals(packageName) && !packageName.equals("")) {
editor.remove(packageName);
if (callingActivity.recyclerAdapter != null) {
if (callingActivity.recyclerAdapter.getPosition(packageName) != -1) {
callingActivity.recyclerAdapter.removeWebsite(packageName);
}
}
}
}
RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.autofill_radiogroup);
switch (radioGroup.getCheckedRadioButtonId()) {
case R.id.use_default:
editor.remove(key);
break;
case R.id.first:
editor.putString(key, "/first");
break;
case R.id.never:
editor.putString(key, "/never");
break;
default:
StringBuilder paths = new StringBuilder();
for (int i = 0; i < adapter.getCount(); i++) {
paths.append(adapter.getItem(i));
if (i != adapter.getCount()) {
paths.append("\n");
}
}
editor.putString(key, paths.toString());
}
editor.apply();
// if recyclerAdapter has not loaded yet, there is no need to notify
if (callingActivity.recyclerAdapter != null) {
int position;
if (!isWebsite) {
String appName = getArguments().getString("appName", "");
position = callingActivity.recyclerAdapter.getPosition(appName);
callingActivity.recyclerAdapter.notifyItemChanged(position);
} else {
String appName = ((EditText) view.findViewById(R.id.webName)).getText().toString();
position = callingActivity.recyclerAdapter.getPosition(appName);
switch (radioGroup.getCheckedRadioButtonId()) {
// remove if existed, else do nothing
case R.id.use_default:
if (position != -1) {
callingActivity.recyclerAdapter.removeWebsite(appName);
}
break;
// change if existed, else add
default:
if (position != -1) {
callingActivity.recyclerAdapter.notifyItemChanged(position);
} else {
callingActivity.recyclerAdapter.addWebsite(appName);
}
}
}
}
} }
}); });
builder.setNegativeButton(R.string.dialog_cancel, null); builder.setNegativeButton(R.string.dialog_cancel, null);
return builder.create(); return builder.create();
} }
// need to the onClick here for buttons to dismiss dialog only when wanted
@Override
public void onStart() {
super.onStart();
AlertDialog ad = (AlertDialog) getDialog();
if(ad != null) {
Button positiveButton = ad.getButton(Dialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AutofillPreferenceActivity callingActivity = (AutofillPreferenceActivity) getActivity();
Dialog dialog = getDialog();
SharedPreferences prefs;
if (!isWeb) {
prefs = getActivity().getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE);
} else {
prefs = getActivity().getApplicationContext().getSharedPreferences("autofill_web", Context.MODE_PRIVATE);
}
SharedPreferences.Editor editor = prefs.edit();
String packageName = getArguments().getString("packageName", "");
if (isWeb) {
packageName = ((EditText) dialog.findViewById(R.id.webURL)).getText().toString();
// handle some errors
EditText webURL = (EditText) dialog.findViewById(R.id.webURL);
if (packageName.equals("")) {
webURL.setError("URL cannot be blank");
return;
}
String oldPackageName = getArguments().getString("packageName", "");
int position = callingActivity.recyclerAdapter.getPosition(packageName);
if (!oldPackageName.equals(packageName) && position != -1) {
webURL.setError("URL already exists");
return;
}
}
RadioGroup radioGroup = (RadioGroup) dialog.findViewById(R.id.autofill_radiogroup);
switch (radioGroup.getCheckedRadioButtonId()) {
case R.id.use_default:
if (!isWeb) {
editor.remove(packageName);
} else {
editor.putString(packageName, "");
}
break;
case R.id.first:
editor.putString(packageName, "/first");
break;
case R.id.never:
editor.putString(packageName, "/never");
break;
default:
StringBuilder paths = new StringBuilder();
for (int i = 0; i < adapter.getCount(); i++) {
paths.append(adapter.getItem(i));
if (i != adapter.getCount()) {
paths.append("\n");
}
}
editor.putString(packageName, paths.toString());
}
editor.apply();
// if recyclerAdapter has not loaded yet, there is no need to notify
if (callingActivity.recyclerAdapter != null) {
int position;
if (!isWeb) {
String appName = getArguments().getString("appName", "");
position = callingActivity.recyclerAdapter.getPosition(appName);
callingActivity.recyclerAdapter.notifyItemChanged(position);
} else {
position = callingActivity.recyclerAdapter.getPosition(packageName);
String oldPackageName = getArguments().getString("packageName", "");
if (oldPackageName.equals(packageName)) {
callingActivity.recyclerAdapter.notifyItemChanged(position);
} else if (oldPackageName.equals("")){
callingActivity.recyclerAdapter.addWebsite(packageName);
} else {
editor.remove(oldPackageName);
callingActivity.recyclerAdapter.updateWebsite(oldPackageName, packageName);
}
}
}
dismiss();
}
});
}
}
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {

View file

@ -28,7 +28,7 @@ import java.util.Map;
public class AutofillPreferenceActivity extends AppCompatActivity { public class AutofillPreferenceActivity extends AppCompatActivity {
private RecyclerView recyclerView; RecyclerView recyclerView;
AutofillRecyclerAdapter recyclerAdapter; // let fragment have access AutofillRecyclerAdapter recyclerAdapter; // let fragment have access
private RecyclerView.LayoutManager layoutManager; private RecyclerView.LayoutManager layoutManager;
@ -56,7 +56,7 @@ public class AutofillPreferenceActivity extends AppCompatActivity {
if (extras != null) { if (extras != null) {
recreate = true; recreate = true;
showDialog(extras.getString("packageName"), extras.getString("appName")); showDialog(extras.getString("packageName"), extras.getString("appName"), extras.getBoolean("isWeb"));
} }
setTitle("Autofill Apps"); setTitle("Autofill Apps");
@ -65,7 +65,7 @@ public class AutofillPreferenceActivity extends AppCompatActivity {
fab.setOnClickListener(new View.OnClickListener() { fab.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
showDialog("", ""); showDialog("", "", true);
} }
}); });
} }
@ -85,16 +85,16 @@ public class AutofillPreferenceActivity extends AppCompatActivity {
for (ResolveInfo app : allAppsResolveInfo) { for (ResolveInfo app : allAppsResolveInfo) {
allApps.add(new AutofillRecyclerAdapter.AppInfo(app.activityInfo.packageName allApps.add(new AutofillRecyclerAdapter.AppInfo(app.activityInfo.packageName
, app.loadLabel(pm).toString(), app.loadIcon(pm))); , app.loadLabel(pm).toString(), false, app.loadIcon(pm)));
} }
SharedPreferences prefs = getSharedPreferences("autofill_web", Context.MODE_PRIVATE); SharedPreferences prefs = getSharedPreferences("autofill_web", Context.MODE_PRIVATE);
Map<String, ?> prefsMap = prefs.getAll(); Map<String, ?> prefsMap = prefs.getAll();
for (String key : prefsMap.keySet()) { for (String key : prefsMap.keySet()) {
try { try {
allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, pm.getApplicationIcon("com.android.browser"))); allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, true, pm.getApplicationIcon("com.android.browser")));
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, null)); allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, true, null));
} }
} }
@ -158,11 +158,12 @@ public class AutofillPreferenceActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
public void showDialog(String packageName, String appName) { public void showDialog(String packageName, String appName, boolean isWeb) {
DialogFragment df = new AutofillFragment(); DialogFragment df = new AutofillFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("packageName", packageName); args.putString("packageName", packageName);
args.putString("appName", appName); args.putString("appName", appName);
args.putBoolean("isWeb", isWeb);
df.setArguments(args); df.setArguments(args);
df.show(getFragmentManager(), "autofill_dialog"); df.show(getFragmentManager(), "autofill_dialog");
} }

View file

@ -24,6 +24,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
private ArrayList<AppInfo> allApps; // for filtering, maintain a list of all private ArrayList<AppInfo> allApps; // for filtering, maintain a list of all
private PackageManager pm; private PackageManager pm;
private AutofillPreferenceActivity activity; private AutofillPreferenceActivity activity;
Drawable browserIcon = null;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public View view; public View view;
@ -32,6 +33,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
public ImageView icon; public ImageView icon;
public String packageName; public String packageName;
public String appName; public String appName;
public Boolean isWeb;
public ViewHolder(View view) { public ViewHolder(View view) {
super(view); super(view);
@ -44,7 +46,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
@Override @Override
public void onClick(View v) { public void onClick(View v) {
activity.showDialog(packageName, appName); activity.showDialog(packageName, appName, isWeb);
} }
} }
@ -52,11 +54,13 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
public static class AppInfo { public static class AppInfo {
public String packageName; public String packageName;
public String appName; public String appName;
public boolean isWeb;
public Drawable icon; public Drawable icon;
public AppInfo(String packageName, String appName, Drawable icon) { public AppInfo(String packageName, String appName, boolean isWeb, Drawable icon) {
this.packageName = packageName; this.packageName = packageName;
this.appName = appName; this.appName = appName;
this.isWeb = isWeb;
this.icon = icon; this.icon = icon;
} }
@ -91,6 +95,11 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
this.allApps = new ArrayList<>(allApps); this.allApps = new ArrayList<>(allApps);
this.pm = pm; this.pm = pm;
this.activity = activity; this.activity = activity;
try {
browserIcon = activity.getPackageManager().getApplicationIcon("com.android.browser");
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
} }
@Override @Override
@ -105,6 +114,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
AppInfo app = apps.get(position); AppInfo app = apps.get(position);
holder.packageName = app.packageName; holder.packageName = app.packageName;
holder.appName = app.appName; holder.appName = app.appName;
holder.isWeb = app.isWeb;
holder.icon.setImageDrawable(app.icon); holder.icon.setImageDrawable(app.icon);
holder.name.setText(app.appName); holder.name.setText(app.appName);
@ -147,23 +157,24 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
} }
public int getPosition(String appName) { public int getPosition(String appName) {
return apps.indexOf(new AppInfo(null, appName, null)); return apps.indexOf(new AppInfo(null, appName, false, null));
} }
public void addWebsite(String appName) { // for websites, URL = packageName == appName
Drawable icon = null; public void addWebsite(String packageName) {
try { apps.add(new AppInfo(packageName, packageName, true, browserIcon));
icon = activity.getPackageManager().getApplicationIcon("com.android.browser"); allApps.add(new AppInfo(packageName, packageName, true, browserIcon));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
apps.add(new AppInfo(appName, appName, icon));
allApps.add(new AppInfo(appName, appName, icon));
} }
public void removeWebsite(String appName) { public void removeWebsite(String packageName) {
apps.remove(new AppInfo(null, appName, null)); apps.remove(new AppInfo(null, packageName, false, null));
allApps.remove(new AppInfo(null, appName, null)); // compare with equals allApps.remove(new AppInfo(null, packageName, false, null)); // compare with equals
}
public void updateWebsite(String oldPackageName, String packageName) {
apps.updateItemAt(getPosition(oldPackageName), new AppInfo (packageName, packageName, true, browserIcon));
allApps.remove(new AppInfo(null, oldPackageName, false, null)); // compare with equals
allApps.add(new AppInfo(null, packageName, false, null));
} }
public void filter(String s) { public void filter(String s) {

View file

@ -156,8 +156,11 @@ public class AutofillService extends AccessibilityService {
window = info.getWindow(); window = info.getWindow();
} }
String packageName;
String appName; String appName;
if (webViewTitle == null) { if (webViewTitle == null) {
packageName = info.getPackageName().toString();
// get the app name and find a corresponding password // get the app name and find a corresponding password
PackageManager packageManager = getPackageManager(); PackageManager packageManager = getPackageManager();
ApplicationInfo applicationInfo; ApplicationInfo applicationInfo;
@ -169,9 +172,10 @@ public class AutofillService extends AccessibilityService {
appName = (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : "").toString(); appName = (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : "").toString();
setMatchingPasswords(appName, info.getPackageName().toString()); setMatchingPasswords(appName, info.getPackageName().toString());
} else { } else {
appName = setMatchingPasswordsWeb(webViewTitle); packageName = setMatchingPasswordsWeb(webViewTitle, webViewURL);
appName = packageName;
} }
// if autofill_always checked, show dialog even if no matches (automatic // if autofill_always checked, show dialog even if no matches (automatic
@ -179,7 +183,7 @@ public class AutofillService extends AccessibilityService {
if (items.isEmpty() && !settings.getBoolean("autofill_always", false)) { if (items.isEmpty() && !settings.getBoolean("autofill_always", false)) {
return; return;
} }
showDialog(appName); showDialog(packageName, appName);
} }
private String searchWebView(AccessibilityNodeInfo source) { private String searchWebView(AccessibilityNodeInfo source) {
@ -244,17 +248,19 @@ public class AutofillService extends AccessibilityService {
} }
} }
// return key for opening its Settings. Otherwise just use the title // Return the the matched preference's key, which isn't necessarily equal to
private String setMatchingPasswordsWeb(String webViewTitle) { // the URL, if a preference is matched so it can be accessed with Settings.
private String setMatchingPasswordsWeb(String webViewTitle, String webViewURL) {
SharedPreferences prefs = getSharedPreferences("autofill_web", Context.MODE_PRIVATE); SharedPreferences prefs = getSharedPreferences("autofill_web", Context.MODE_PRIVATE);
Map<String, ?> prefsMap = prefs.getAll(); Map<String, ?> prefsMap = prefs.getAll();
for (String key : prefsMap.keySet()) { for (String key : prefsMap.keySet()) {
if (webViewTitle.toLowerCase().contains(key.toLowerCase())) { if (webViewURL.toLowerCase().contains(key.toLowerCase())) {
getPreferredPasswords(prefs.getString(key, "")); getPreferredPasswords(prefs.getString(key, ""));
return key; return key;
} }
} }
// possible user-defined match not found, try default setting
// no user-defined match found, maybe auto match using title, not URL
if (settings.getBoolean("autofill_default", true)) { if (settings.getBoolean("autofill_default", true)) {
if (!PasswordRepository.isInitialized()) { if (!PasswordRepository.isInitialized()) {
PasswordRepository.initialize(this); PasswordRepository.initialize(this);
@ -263,7 +269,7 @@ public class AutofillService extends AccessibilityService {
} else { } else {
items = new ArrayList<>(); items = new ArrayList<>();
} }
return webViewTitle; return webViewURL;
} }
// Put the newline separated list of passwords from the SharedPreferences // Put the newline separated list of passwords from the SharedPreferences
@ -305,7 +311,7 @@ public class AutofillService extends AccessibilityService {
return items; return items;
} }
private void showDialog(final String appName) { private void showDialog(final String packageName, final String appName) {
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog); AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog);
builder.setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener() { builder.setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener() {
@Override @Override
@ -320,12 +326,11 @@ public class AutofillService extends AccessibilityService {
// the user will have to return to the app themselves. // the user will have to return to the app themselves.
Intent intent = new Intent(AutofillService.this, AutofillPreferenceActivity.class); Intent intent = new Intent(AutofillService.this, AutofillPreferenceActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
if (webViewTitle == null) { intent.putExtra("packageName", packageName);
intent.putExtra("packageName", info.getPackageName());
} else {
intent.putExtra("packageName", appName);
}
intent.putExtra("appName", appName); intent.putExtra("appName", appName);
if (webViewTitle != null) {
intent.putExtra("isWeb", true);
}
startActivity(intent); startActivity(intent);
} }
}); });

View file

@ -1,79 +1,79 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="20dp" android:paddingBottom="20dp"
android:paddingLeft="24dp" android:paddingLeft="24dp"
android:paddingRight="24dp" android:paddingRight="24dp"
android:paddingTop="20dp"> android:paddingTop="20dp">
<android.support.design.widget.TextInputLayout xmlns:app="http://schemas.android.com/apk/res-auto" <android.support.design.widget.TextInputLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:hintTextAppearance="@style/TextAppearance.AppCompat"> app:hintTextAppearance="@style/TextAppearance.AppCompat">
<EditText <EditText
android:id="@+id/webName" android:id="@+id/webURL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/autofill_webname_hint"
android:inputType="textPersonName"/>
</android.support.design.widget.TextInputLayout>
<RadioGroup
android:id="@+id/autofill_radiogroup"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:hint="@string/autofill_webURL_hint"
android:inputType="textUri"/>
</android.support.design.widget.TextInputLayout>
<RadioButton <RadioGroup
android:id="@+id/use_default" android:id="@+id/autofill_radiogroup"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_default" />
<RadioButton <RadioButton
android:id="@+id/first" android:id="@+id/use_default"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:checked="false" android:checked="false"
android:text="@string/autofill_apps_first" /> android:text="@string/autofill_apps_default" />
<RadioButton <RadioButton
android:id="@+id/match" android:id="@+id/first"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:checked="false" android:checked="false"
android:text="@string/autofill_apps_match_ellipsis" /> android:text="@string/autofill_apps_first" />
<ListView <RadioButton
android:id="@+id/matched" android:id="@+id/match"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_vertical"
android:layout_weight="1"/> android:checked="false"
android:text="@string/autofill_apps_match_ellipsis" />
<Button <ListView
style="?android:attr/buttonStyleSmall" android:id="@+id/matched"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="+" android:layout_gravity="center_horizontal"
android:id="@+id/matchButton" android:layout_weight="1"/>
android:layout_gravity="center_horizontal"/>
<RadioButton <Button
android:id="@+id/never" style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:text="+"
android:checked="false" android:id="@+id/matchButton"
android:text="@string/autofill_apps_never"/> android:layout_gravity="center_horizontal"/>
</RadioGroup> <RadioButton
android:id="@+id/never"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_never"/>
</LinearLayout> </RadioGroup>
</LinearLayout>

View file

@ -171,5 +171,5 @@
<string name="autofill_apps_match_ellipsis">Match with…</string> <string name="autofill_apps_match_ellipsis">Match with…</string>
<string name="autofill_apps_match">Match with</string> <string name="autofill_apps_match">Match with</string>
<string name="autofill_apps_never">Never match</string> <string name="autofill_apps_never">Never match</string>
<string name="autofill_webname_hint">Name</string> <string name="autofill_webURL_hint">URL</string>
</resources> </resources>