Universal search

Android 8.0 adds expanded search capabilities for the Settings menu. This document describes how to add a setting and ensure it is properly indexed for Settings search.

Creating indexable settings

Each Settings fragment that needs to be indexed implements the Indexableinterface, AND requires the static field:

public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER

Once you have your fragment set up for indexing, add it to SearchIndexableResources found at:
packages/apps/Settings/src/com/android/settings/search/SearchIndexableResources.java

Optional methods

This SearchIndexProviderinterface has four optional methods.

getXmlResourcesToIndex

  • Override this if your fragment content is from: preference xml
  • Returns an XML preference as a list to be indexed.

XML resources example:

public List<SearchIndexableResource> getXmlResourcesToIndex(Context context, boolean enabled) {
    ArrayList<SearchIndexableResource> result =  new ArrayList<SearchIndexableResource>();
SearchIndexableResource sir = new SearchIndexableResource(context);
	sir.xmlResId = R.xml.display_settings;
	result.add(sir);

    return result;
}

getRawDataToIndex

  • Override this if your fragment content is NOT from: preference xml
  • Returns a list of Raw data (SearchIndexableRaw) to be indexed.

Raw data example:

public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
              final List<SearchIndexableRaw> result = new ArrayList<>();
              final Resources res = context.getResources();

              // Add fragment title
       SearchIndexableRaw data = new SearchIndexableRaw(context);
       data.title = res.getString(R.string.wifi_settings);
       data.screenTitle = res.getString(R.string.wifi_settings);
       data.keywords = res.getString(R.string.keywords_wifi);
       data.key = DATA_KEY_REFERENCE;
       result.add(data);

       return result;
}

getNonIndexableKeys

  • If your fragment is a DashboardFragment, you rarely need to override this.
  • Returns a list of keys that corresponds to results that should not show up for the given user, device, configuration, etc.The keys provided here should match the KEY field in SearchIndexableResource and SearchIndexableRaw.
  • For example: Data Usage should not show up for users who have never had a SIM card in their device.

Non-indexable keys example:

public List<String> getNonIndexableKeys(Context context) {
      final List<String> keys = super.getNonIndexableKeys(context);
              if (!checkIntentAction(context, "android.settings.TERMS")) {
                  keys.add(KEY_TERMS);
              }
              if (!checkIntentAction(context, "android.settings.LICENSE")) {
                  keys.add(KEY_LICENSE);
              }
              if (!checkIntentAction(context, "android.settings.COPYRIGHT")) {
                  keys.add(KEY_COPYRIGHT);
              }
              if (!checkIntentAction(context, "android.settings.WEBVIEW_LICENSE")) {
                  keys.add(KEY_WEBVIEW_LICENSE);
              }
              return keys;
}

getPreferenceControllers

Returns a list of preference controllers associated with this fragment. This list is used to form inline results, update non-indexables, etc.

Thus, everything you want to show up in search must be included in either getXmlResourcesToIndex or getRawDataToIndex.

Adding keywords for your settings

To ensure a setting is easily searchable, add keywords that are relevant for the setting that a user may use to search for the setting.

Things to consider when adding keywords:

  • Keywords are a list of words that the user does not necessarily see but may be part of their mental model for how the setting works.
  • These are words that the user might type to get to your setting.
  • They can be synonyms or any words associated to the setting can be used.
  • For example, "mute" might be used to find the Volume setting.

Avoiding duplication

If you are unconditionally suppressing a settings page, remove the indexing of the original page to avoid duplication of results.

  1. Find the PreferenceFragment of the page you are suppressing.
  2. Remove the SearchIndexProvider.

Validation

To test the searchability of a new setting:

  1. Instal a recent version of O on the device.
  2. Reindex the database by selecting:
  3. Settings > Apps & Notifications > Apps info > Settings > Storage > Clear Data
  4. Verify the target settings shows up in search.
    Searching for a prefix of the title of a setting will match it.

These robolectric tests may be run to validate the implementation of this feature:
packages/apps/Settings/tests/robotests/src/com/android/settings/search

The build target is: RunSettingsRoboTests