Add indexing for ListPreferences

- now support ListPreferences and save the "entries" attribute
- update Index database schema (and increment its version)
- do some clever stuff when showing Search results: if there is
a "$s" or "%s" in the summary (replacement strings), just use
the entries instead

Change-Id: If36595c3816706b6349faff7d3c2e725d3ea33f4
This commit is contained in:
Fabrice Di Meglio
2014-04-02 19:05:45 -07:00
parent f66eb7a8c8
commit a41707200b
5 changed files with 109 additions and 39 deletions

View File

@@ -24,7 +24,6 @@ import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.app.FragmentManager; import android.app.FragmentManager;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.app.SearchManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;

View File

@@ -197,15 +197,17 @@ public class SearchResultsSummary extends Fragment {
public String title; public String title;
public String summaryOn; public String summaryOn;
public String summaryOff; public String summaryOff;
public String entries;
public int iconResId; public int iconResId;
public Context context; public Context context;
public SearchResult(Context context, String title, String summaryOn, String summaryOff, public SearchResult(Context context, String title, String summaryOn, String summaryOff,
int iconResId) { String entries, int iconResId) {
this.context = context; this.context = context;
this.title = title; this.title = title;
this.summaryOn = summaryOn; this.summaryOn = summaryOn;
this.summaryOff = summaryOff; this.summaryOff = summaryOff;
this.entries = entries;
this.iconResId = iconResId; this.iconResId = iconResId;
} }
} }
@@ -218,6 +220,9 @@ public class SearchResultsSummary extends Fragment {
private Context mContext; private Context mContext;
private HashMap<String, Context> mContextMap = new HashMap<String, Context>(); private HashMap<String, Context> mContextMap = new HashMap<String, Context>();
private static final String PERCENT_RECLACE = "%s";
private static final String DOLLAR_REPLACE = "$s";
public SearchResultsAdapter(Context context) { public SearchResultsAdapter(Context context) {
mContext = context; mContext = context;
mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -252,6 +257,7 @@ public class SearchResultsSummary extends Fragment {
final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE); final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE);
final String summaryOn = mCursor.getString(Index.COLUMN_INDEX_SUMMARY_ON); final String summaryOn = mCursor.getString(Index.COLUMN_INDEX_SUMMARY_ON);
final String summaryOff = mCursor.getString(Index.COLUMN_INDEX_SUMMARY_OFF); final String summaryOff = mCursor.getString(Index.COLUMN_INDEX_SUMMARY_OFF);
final String entries = mCursor.getString(Index.COLUMN_INDEX_ENTRIES);
final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON); final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON);
final String className = mCursor.getString( final String className = mCursor.getString(
Index.COLUMN_INDEX_CLASS_NAME); Index.COLUMN_INDEX_CLASS_NAME);
@@ -273,9 +279,12 @@ public class SearchResultsSummary extends Fragment {
} else { } else {
packageContext = mContext; packageContext = mContext;
} }
final int iconResId = TextUtils.isEmpty(iconResStr) ? final int iconResId = TextUtils.isEmpty(iconResStr) ?
R.drawable.empty_icon : Integer.parseInt(iconResStr); R.drawable.empty_icon : Integer.parseInt(iconResStr);
return new SearchResult(packageContext, title, summaryOn, summaryOff, iconResId);
return new SearchResult(packageContext, title, summaryOn, summaryOff,
entries, iconResId);
} }
return null; return null;
} }
@@ -312,10 +321,26 @@ public class SearchResultsSummary extends Fragment {
SearchResult result = (SearchResult) getItem(position); SearchResult result = (SearchResult) getItem(position);
textTitle.setText(result.title); textTitle.setText(result.title);
final StringBuilder sb = new StringBuilder(result.summaryOn);
if (!TextUtils.isEmpty(result.summaryOff)) { String summaryOn = result.summaryOn;
sb.append(" | "); String summaryOff = result.summaryOff;
sb.append(result.summaryOff); String entries = result.entries;
final StringBuilder sb = new StringBuilder();
if (!TextUtils.isEmpty(summaryOn) &&
!summaryOn.contains(PERCENT_RECLACE) && !summaryOn.contains(DOLLAR_REPLACE)) {
sb.append(summaryOn);
if (!TextUtils.isEmpty(summaryOff) &&
!summaryOff.contains(PERCENT_RECLACE) &&
!summaryOff.contains(DOLLAR_REPLACE)) {
sb.append(" \n ");
sb.append(summaryOff);
}
}
if (!TextUtils.isEmpty(entries)) {
sb.append(" \n ");
sb.append(entries);
} }
textSummary.setText(sb.toString()); textSummary.setText(sb.toString());
if (result.iconResId != R.drawable.empty_icon) { if (result.iconResId != R.drawable.empty_icon) {

View File

@@ -60,14 +60,15 @@ public class Index {
public static final int COLUMN_INDEX_TITLE = 1; public static final int COLUMN_INDEX_TITLE = 1;
public static final int COLUMN_INDEX_SUMMARY_ON = 2; public static final int COLUMN_INDEX_SUMMARY_ON = 2;
public static final int COLUMN_INDEX_SUMMARY_OFF = 3; public static final int COLUMN_INDEX_SUMMARY_OFF = 3;
public static final int COLUMN_INDEX_KEYWORDS = 4; public static final int COLUMN_INDEX_ENTRIES = 4;
public static final int COLUMN_INDEX_CLASS_NAME = 5; public static final int COLUMN_INDEX_KEYWORDS = 5;
public static final int COLUMN_INDEX_SCREEN_TITLE = 6; public static final int COLUMN_INDEX_CLASS_NAME = 6;
public static final int COLUMN_INDEX_ICON = 7; public static final int COLUMN_INDEX_SCREEN_TITLE = 7;
public static final int COLUMN_INDEX_INTENT_ACTION = 8; public static final int COLUMN_INDEX_ICON = 8;
public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 9; public static final int COLUMN_INDEX_INTENT_ACTION = 9;
public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 10; public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 10;
public static final int COLUMN_INDEX_ENABLED = 11; public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 11;
public static final int COLUMN_INDEX_ENABLED = 12;
// If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values // If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values
private static final String[] SELECT_COLUMNS = new String[] { private static final String[] SELECT_COLUMNS = new String[] {
@@ -75,13 +76,14 @@ public class Index {
IndexColumns.DATA_TITLE, // 1 IndexColumns.DATA_TITLE, // 1
IndexColumns.DATA_SUMMARY_ON, // 2 IndexColumns.DATA_SUMMARY_ON, // 2
IndexColumns.DATA_SUMMARY_OFF, // 3 IndexColumns.DATA_SUMMARY_OFF, // 3
IndexColumns.DATA_KEYWORDS, // 4 IndexColumns.DATA_ENTRIES, // 4
IndexColumns.CLASS_NAME, // 5 IndexColumns.DATA_KEYWORDS, // 5
IndexColumns.SCREEN_TITLE, // 6 IndexColumns.CLASS_NAME, // 6
IndexColumns.ICON, // 7 IndexColumns.SCREEN_TITLE, // 7
IndexColumns.INTENT_ACTION, // 8 IndexColumns.ICON, // 8
IndexColumns.INTENT_TARGET_PACKAGE, // 9 IndexColumns.INTENT_ACTION, // 9
IndexColumns.INTENT_TARGET_CLASS // 10 IndexColumns.INTENT_TARGET_PACKAGE, // 10
IndexColumns.INTENT_TARGET_CLASS // 11
}; };
private static final String[] MATCH_COLUMNS = { private static final String[] MATCH_COLUMNS = {
@@ -91,6 +93,7 @@ public class Index {
IndexColumns.DATA_SUMMARY_ON_NORMALIZED, IndexColumns.DATA_SUMMARY_ON_NORMALIZED,
IndexColumns.DATA_SUMMARY_OFF, IndexColumns.DATA_SUMMARY_OFF,
IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, IndexColumns.DATA_SUMMARY_OFF_NORMALIZED,
IndexColumns.DATA_ENTRIES,
IndexColumns.DATA_KEYWORDS IndexColumns.DATA_KEYWORDS
}; };
@@ -103,6 +106,7 @@ public class Index {
private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen"; private static final String NODE_NAME_PREFERENCE_SCREEN = "PreferenceScreen";
private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference"; private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference";
private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference";
private static Index sInstance; private static Index sInstance;
private final AtomicBoolean mIsAvailable = new AtomicBoolean(false); private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
@@ -348,22 +352,24 @@ public class Index {
final String title = cursor.getString(1); final String title = cursor.getString(1);
final String summaryOn = cursor.getString(2); final String summaryOn = cursor.getString(2);
final String summaryOff = cursor.getString(3); final String summaryOff = cursor.getString(3);
final String keywords = cursor.getString(4); final String entries = cursor.getString(4);
final String keywords = cursor.getString(5);
final String screenTitle = cursor.getString(5); final String screenTitle = cursor.getString(6);
final String className = cursor.getString(6); final String className = cursor.getString(7);
final int iconResId = cursor.getInt(7); final int iconResId = cursor.getInt(8);
final String action = cursor.getString(8); final String action = cursor.getString(9);
final String targetPackage = cursor.getString(9); final String targetPackage = cursor.getString(10);
final String targetClass = cursor.getString(10); final String targetClass = cursor.getString(11);
SearchIndexableRaw data = new SearchIndexableRaw(packageContext); SearchIndexableRaw data = new SearchIndexableRaw(packageContext);
data.rank = rank; data.rank = rank;
data.title = title; data.title = title;
data.summaryOn = summaryOn; data.summaryOn = summaryOn;
data.summaryOff = summaryOff; data.summaryOff = summaryOff;
data.entries = entries;
data.keywords = keywords; data.keywords = keywords;
data.screenTitle = screenTitle; data.screenTitle = screenTitle;
data.className = className; data.className = className;
@@ -487,8 +493,8 @@ public class Index {
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing // Insert rows for the main PreferenceScreen node. Rewrite the data for removing
// hyphens. // hyphens.
updateOneRowWithFilteredData(database, localeStr, title, summary, null, fragmentName, updateOneRowWithFilteredData(database, localeStr, title, summary, null, null,
screenTitle, iconResId, rank, keywords, fragmentName, screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass, true); intentAction, intentTargetPackage, intentTargetClass, true);
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -505,16 +511,21 @@ public class Index {
if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) { if (!nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) {
summary = getDataSummary(context, attrs); summary = getDataSummary(context, attrs);
String entries = null;
if (nodeName.endsWith(NODE_NAME_LIST_PREFERENCE)) {
entries = getDataEntries(context, attrs);
}
// Insert rows for the child nodes of PreferenceScreen // Insert rows for the child nodes of PreferenceScreen
updateOneRowWithFilteredData(database, localeStr, title, summary, null, updateOneRowWithFilteredData(database, localeStr, title, summary, null, entries,
fragmentName, screenTitle, iconResId, rank, keywords, fragmentName, screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass, true); intentAction, intentTargetPackage, intentTargetClass, true);
} else { } else if (nodeName.equals(NODE_NAME_CHECK_BOX_PREFERENCE)) {
final String summaryOn = getDataSummaryOn(context, attrs); final String summaryOn = getDataSummaryOn(context, attrs);
final String summaryOff = getDataSummaryOff(context, attrs); final String summaryOff = getDataSummaryOff(context, attrs);
updateOneRowWithFilteredData(database, localeStr, title, summaryOn, summaryOff, updateOneRowWithFilteredData(database, localeStr, title, summaryOn, summaryOff,
fragmentName, screenTitle, iconResId, rank, keywords, null, fragmentName, screenTitle, iconResId, rank, keywords,
intentAction, intentTargetPackage, intentTargetClass, true); intentAction, intentTargetPackage, intentTargetClass, true);
} }
} }
@@ -539,6 +550,7 @@ public class Index {
raw.title, raw.title,
raw.summaryOn, raw.summaryOn,
raw.summaryOff, raw.summaryOff,
raw.entries,
raw.className, raw.className,
raw.screenTitle, raw.screenTitle,
raw.iconResId, raw.iconResId,
@@ -575,6 +587,7 @@ public class Index {
raw.title, raw.title,
raw.summaryOn, raw.summaryOn,
raw.summaryOff, raw.summaryOff,
raw.entries,
sir.className, sir.className,
raw.screenTitle, raw.screenTitle,
sir.iconResId, sir.iconResId,
@@ -617,8 +630,8 @@ public class Index {
} }
private void updateOneRowWithFilteredData(SQLiteDatabase database, String locale, private void updateOneRowWithFilteredData(SQLiteDatabase database, String locale,
String title, String summaryOn, String summaryOff, String className, String screenTitle, String title, String summaryOn, String summaryOff, String entries, String className,
int iconResId, int rank, String keywords, String screenTitle, int iconResId, int rank, String keywords,
String intentAction, String intentTargetPackage, String intentTargetClass, String intentAction, String intentTargetPackage, String intentTargetClass,
boolean enabled) { boolean enabled) {
@@ -650,14 +663,14 @@ public class Index {
updateOneRow(database, locale, updateOneRow(database, locale,
updatedTitle, normalizedTitle, updatedSummaryOn, normalizedSummaryOn, updatedTitle, normalizedTitle, updatedSummaryOn, normalizedSummaryOn,
updatedSummaryOff, normalizedSummaryOff, className, screenTitle, iconResId, updatedSummaryOff, normalizedSummaryOff, entries, className, screenTitle, iconResId,
rank, keywords, intentAction, intentTargetPackage, intentTargetClass, enabled); rank, keywords, intentAction, intentTargetPackage, intentTargetClass, enabled);
} }
private void updateOneRow(SQLiteDatabase database, String locale, private void updateOneRow(SQLiteDatabase database, String locale,
String updatedTitle, String normalizedTitle, String updatedTitle, String normalizedTitle,
String updatedSummaryOn, String normalizedSummaryOn, String updatedSummaryOn, String normalizedSummaryOn,
String updatedSummaryOff, String normalizedSummaryOff, String className, String updatedSummaryOff, String normalizedSummaryOff, String entries, String className,
String screenTitle, int iconResId, int rank, String keywords, String screenTitle, int iconResId, int rank, String keywords,
String intentAction, String intentTargetPackage, String intentTargetClass, String intentAction, String intentTargetPackage, String intentTargetClass,
boolean enabled) { boolean enabled) {
@@ -676,6 +689,7 @@ public class Index {
values.put(IndexColumns.DATA_SUMMARY_ON_NORMALIZED, normalizedSummaryOn); values.put(IndexColumns.DATA_SUMMARY_ON_NORMALIZED, normalizedSummaryOn);
values.put(IndexColumns.DATA_SUMMARY_OFF, updatedSummaryOff); values.put(IndexColumns.DATA_SUMMARY_OFF, updatedSummaryOff);
values.put(IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, normalizedSummaryOff); values.put(IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, normalizedSummaryOff);
values.put(IndexColumns.DATA_ENTRIES, entries);
values.put(IndexColumns.DATA_KEYWORDS, keywords); values.put(IndexColumns.DATA_KEYWORDS, keywords);
values.put(IndexColumns.CLASS_NAME, className); values.put(IndexColumns.CLASS_NAME, className);
values.put(IndexColumns.SCREEN_TITLE, screenTitle); values.put(IndexColumns.SCREEN_TITLE, screenTitle);
@@ -712,6 +726,12 @@ public class Index {
com.android.internal.R.styleable.CheckBoxPreference_summaryOff); com.android.internal.R.styleable.CheckBoxPreference_summaryOff);
} }
private String getDataEntries(Context context, AttributeSet attrs) {
return getDataEntries(context, attrs,
com.android.internal.R.styleable.ListPreference,
com.android.internal.R.styleable.ListPreference_entries);
}
private String getDataKeywords(Context context, AttributeSet attrs) { private String getDataKeywords(Context context, AttributeSet attrs) {
return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords); return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
} }
@@ -731,6 +751,28 @@ public class Index {
return (data != null) ? data.toString() : null; return (data != null) ? data.toString() : null;
} }
private String getDataEntries(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray sa = context.obtainStyledAttributes(set, attrs);
final TypedValue tv = sa.peekValue(resId);
String[] data = null;
if (tv != null && tv.type == TypedValue.TYPE_REFERENCE) {
if (tv.resourceId != 0) {
data = context.getResources().getStringArray(tv.resourceId);
}
}
final int count = (data == null ) ? 0 : data.length;
if (count == 0) {
return null;
}
final StringBuilder result = new StringBuilder();
for (int n = 0; n < count; n++) {
result.append(data[n]);
result.append(" ");
}
return result.toString();
}
private int getResId(Context context, AttributeSet set, int[] attrs, int resId) { private int getResId(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray sa = context.obtainStyledAttributes(set, attrs); final TypedArray sa = context.obtainStyledAttributes(set, attrs);
final TypedValue tv = sa.peekValue(resId); final TypedValue tv = sa.peekValue(resId);

View File

@@ -28,7 +28,7 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "IndexDatabaseHelper"; private static final String TAG = "IndexDatabaseHelper";
private static final String DATABASE_NAME = "search_index.db"; private static final String DATABASE_NAME = "search_index.db";
private static final int DATABASE_VERSION = 104; private static final int DATABASE_VERSION = 105;
public interface Tables { public interface Tables {
public static final String TABLE_PREFS_INDEX = "prefs_index"; public static final String TABLE_PREFS_INDEX = "prefs_index";
@@ -45,6 +45,7 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
public static final String DATA_SUMMARY_ON_NORMALIZED = "data_summary_on_normalized"; public static final String DATA_SUMMARY_ON_NORMALIZED = "data_summary_on_normalized";
public static final String DATA_SUMMARY_OFF = "data_summary_off"; public static final String DATA_SUMMARY_OFF = "data_summary_off";
public static final String DATA_SUMMARY_OFF_NORMALIZED = "data_summary_off_normalized"; public static final String DATA_SUMMARY_OFF_NORMALIZED = "data_summary_off_normalized";
public static final String DATA_ENTRIES = "data_entries";
public static final String DATA_KEYWORDS = "data_keywords"; public static final String DATA_KEYWORDS = "data_keywords";
public static final String CLASS_NAME = "class_name"; public static final String CLASS_NAME = "class_name";
public static final String SCREEN_TITLE = "screen_title"; public static final String SCREEN_TITLE = "screen_title";
@@ -78,6 +79,8 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
", " + ", " +
IndexColumns.DATA_SUMMARY_OFF_NORMALIZED + IndexColumns.DATA_SUMMARY_OFF_NORMALIZED +
", " + ", " +
IndexColumns.DATA_ENTRIES +
", " +
IndexColumns.DATA_KEYWORDS + IndexColumns.DATA_KEYWORDS +
", " + ", " +
IndexColumns.SCREEN_TITLE + IndexColumns.SCREEN_TITLE +

View File

@@ -31,6 +31,7 @@ public class SearchIndexableRaw extends SearchIndexableData {
public String title; public String title;
public String summaryOn; public String summaryOn;
public String summaryOff; public String summaryOff;
public String entries;
public String keywords; public String keywords;
public String screenTitle; public String screenTitle;