Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e678f46e authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Query refinement feature in SearchView.

New method : setQueryRefinementEnabled() which will either enable all suggestions
to have the little query refinement icon in the right or just the ones that have
a bit set in the new SUGGEST_FLAGS column of the suggestion provider cursor.
parent 44c7197a
Loading
Loading
Loading
Loading
+46 −12
Original line number Diff line number Diff line
@@ -33240,6 +33240,17 @@
 visibility="public"
>
</field>
<field name="FLAG_QUERY_REFINEMENT"
 type="int"
 transient="false"
 volatile="false"
 value="1"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="INTENT_ACTION_GLOBAL_SEARCH"
 type="java.lang.String"
 transient="false"
@@ -33339,6 +33350,17 @@
 visibility="public"
>
</field>
<field name="SUGGEST_COLUMN_FLAGS"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;suggest_flags&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="SUGGEST_COLUMN_FORMAT"
 type="java.lang.String"
 transient="false"
@@ -234346,6 +234368,17 @@
 visibility="public"
>
</method>
<method name="isQueryRefinementEnabled"
 return="boolean"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="isSubmitButtonEnabled"
 return="boolean"
 abstract="false"
@@ -234437,6 +234470,19 @@
<parameter name="hint" type="java.lang.CharSequence">
</parameter>
</method>
<method name="setQueryRefinementEnabled"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="enable" type="boolean">
</parameter>
</method>
<method name="setSearchableInfo"
 return="void"
 abstract="false"
@@ -234477,18 +234523,6 @@
</parameter>
</method>
</class>
<interface name="SearchView.FilterableListAdapter"
 abstract="true"
 static="true"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<implements name="android.widget.Filterable">
</implements>
<implements name="android.widget.ListAdapter">
</implements>
</interface>
<interface name="SearchView.OnCloseListener"
 abstract="true"
 static="true"
+3 −13
Original line number Diff line number Diff line
@@ -1083,7 +1083,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
    protected void launchQuerySearch(int actionKey, String actionMsg)  {
        String query = mSearchAutoComplete.getText().toString();
        String action = Intent.ACTION_SEARCH;
        Intent intent = createIntent(action, null, null, query, null,
        Intent intent = createIntent(action, null, null, query,
                actionKey, actionMsg);
        launchIntent(intent);
    }
@@ -1185,11 +1185,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
            // use specific action if supplied, or default action if supplied, or fixed default
            String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION);

            // some items are display only, or have effect via the cursor respond click reporting.
            if (SearchManager.INTENT_ACTION_NONE.equals(action)) {
                return null;
            }

            if (action == null) {
                action = mSearchable.getSuggestIntentAction();
            }
@@ -1211,14 +1206,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
            }
            Uri dataUri = (data == null) ? null : Uri.parse(data);

            String componentName = getColumnString(
                    c, SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME);

            String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY);
            String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);

            return createIntent(action, dataUri, extraData, query, componentName, actionKey,
                    actionMsg);
            return createIntent(action, dataUri, extraData, query, actionKey, actionMsg);
        } catch (RuntimeException e ) {
            int rowNum;
            try {                       // be really paranoid now
@@ -1239,7 +1230,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
     * @param data Intent data, or <code>null</code>.
     * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>.
     * @param query Intent query, or <code>null</code>.
     * @param componentName Data for {@link SearchManager#COMPONENT_NAME_KEY} or <code>null</code>.
     * @param actionKey The key code of the action key that was pressed,
     *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
     * @param actionMsg The message for the action key that was pressed,
@@ -1249,7 +1239,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
     * @return The intent.
     */
    private Intent createIntent(String action, Uri data, String extraData, String query,
            String componentName, int actionKey, String actionMsg) {
            int actionKey, String actionMsg) {
        // Now build the Intent
        Intent intent = new Intent(action);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+61 −71
Original line number Diff line number Diff line
@@ -16,16 +16,12 @@

package android.app;

import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -158,6 +154,14 @@ public class SearchManager
     */
    public final static String ACTION_MSG = "action_msg";

    /**
     * Flag to specify that the entry can be used for query refinement, i.e., the query text
     * in the search field can be replaced with the text in this entry, when a query refinement
     * icon is clicked. The suggestion list should show such a clickable icon beside the entry.
     * <p>Use this flag as a bit-field for {@link #SUGGEST_COLUMN_FLAGS}.
     */
    public final static int FLAG_QUERY_REFINEMENT = 1 << 0;

    /**
     * Uri path for queried suggestions data.  This is the path that the search manager
     * will use when querying your content provider for suggestions data based on user input
@@ -275,12 +279,6 @@ public class SearchManager
     * an extra under the key {@link #EXTRA_DATA_KEY}.
     */
    public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data";
    /**
     * TODO: Remove
     *
     * @hide
     */
    public final static String SUGGEST_COLUMN_INTENT_COMPONENT_NAME = "suggest_intent_component";
    /**
     * Column name for suggestions cursor.  <i>Optional.</i>  If this column exists <i>and</i>
     * this element exists at the given row, then "/" and this value will be appended to the data
@@ -306,15 +304,6 @@ public class SearchManager
     */
    public final static String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id";

    /**
     * Column name for suggestions cursor. <i>Optional.</i>  This column is used to specify the
     * cursor item's background color if it needs a non-default background color. A non-zero value
     * indicates a valid background color to override the default.
     *
     * @hide For internal use, not part of the public API.
     */
    public final static String SUGGEST_COLUMN_BACKGROUND_COLOR = "suggest_background_color";
    
    /**
     * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify
     * that a spinner should be shown in lieu of an icon2 while the shortcut of this suggestion
@@ -323,6 +312,15 @@ public class SearchManager
    public final static String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING =
            "suggest_spinner_while_refreshing";

    /**
     * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify
     * additional flags per item. Multiple flags can be specified.
     * <p>
     * Must be one of {@link #FLAG_QUERY_REFINEMENT} or 0 to indicate no flags.
     * </p>
     */
    public final static String SUGGEST_COLUMN_FLAGS = "suggest_flags";

    /**
     * Column value for suggestion column {@link #SUGGEST_COLUMN_SHORTCUT_ID} when a suggestion
     * should not be stored as a shortcut in global search.
@@ -377,14 +375,6 @@ public class SearchManager
    public final static String INTENT_ACTION_SEARCH_SETTINGS_CHANGED
            = "android.search.action.SETTINGS_CHANGED";

    /**
     * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
     * the search dialog will take no action.
     *
     * @hide
     */
    public final static String INTENT_ACTION_NONE = "android.search.action.ZILCH";

    /**
     * This means that context is voice, and therefore the SearchDialog should
     * continue showing the microphone until the user indicates that he/she does
+1 −54
Original line number Diff line number Diff line
@@ -68,7 +68,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
    private SearchableInfo mSearchable;
    private Context mProviderContext;
    private WeakHashMap<String, Drawable.ConstantState> mOutsideDrawablesCache;
    private SparseArray<Drawable.ConstantState> mBackgroundsCache;
    private boolean mClosed = false;

    // URL color
@@ -80,7 +79,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
    private int mText2UrlCol;
    private int mIconName1Col;
    private int mIconName2Col;
    private int mBackgroundColorCol;

    static final int NONE = -1;

@@ -109,7 +107,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
        mProviderContext = mSearchable.getProviderContext(mContext, activityContext);

        mOutsideDrawablesCache = outsideDrawablesCache;
        mBackgroundsCache = new SparseArray<Drawable.ConstantState>();

        mStartSpinnerRunnable = new Runnable() {
                public void run() {
@@ -243,8 +240,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
                mText2UrlCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL);
                mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
                mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
                mBackgroundColorCol =
                        c.getColumnIndex(SearchManager.SUGGEST_COLUMN_BACKGROUND_COLOR);
            }
        } catch (Exception e) {
            Log.e(LOG_TAG, "error changing cursor and caching columns", e);
@@ -283,13 +278,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
    public void bindView(View view, Context context, Cursor cursor) {
        ChildViewCache views = (ChildViewCache) view.getTag();

        int backgroundColor = 0;
        if (mBackgroundColorCol != -1) {
            backgroundColor = cursor.getInt(mBackgroundColorCol);
        }
        Drawable background = getItemBackground(backgroundColor);
        view.setBackgroundDrawable(background);

        if (views.mText1 != null) {
            String text1 = getStringOrNull(cursor, mText1Col);
            setViewText(views.mText1, text1);
@@ -342,33 +330,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
        return text;
    }

    /**
     * Gets a drawable with no color when selected or pressed, and the given color when
     * neither selected nor pressed.
     *
     * @return A drawable, or {@code null} if the given color is transparent.
     */
    private Drawable getItemBackground(int backgroundColor) {
        if (backgroundColor == 0) {
            return null;
        } else {
            Drawable.ConstantState cachedBg = mBackgroundsCache.get(backgroundColor);
            if (cachedBg != null) {
                if (DBG) Log.d(LOG_TAG, "Background cache hit for color " + backgroundColor);
                return cachedBg.newDrawable(mProviderContext.getResources());
            }
            if (DBG) Log.d(LOG_TAG, "Creating new background for color " + backgroundColor);
            ColorDrawable transparent = new ColorDrawable(0);
            ColorDrawable background = new ColorDrawable(backgroundColor);
            StateListDrawable newBg = new StateListDrawable();
            newBg.addState(new int[]{android.R.attr.state_selected}, transparent);
            newBg.addState(new int[]{android.R.attr.state_pressed}, transparent);
            newBg.addState(new int[]{}, background);
            mBackgroundsCache.put(backgroundColor, newBg.getConstantState());
            return newBg;
        }
    }

    private void setViewText(TextView v, CharSequence text) {
        // Set the text even if it's null, since we need to clear any previous text.
        v.setText(text);
@@ -601,21 +562,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
     * @return A non-null drawable.
     */
    private Drawable getDefaultIcon1(Cursor cursor) {
        // First check the component that the suggestion is originally from
        String c = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME);
        if (c != null) {
            ComponentName component = ComponentName.unflattenFromString(c);
            if (component != null) {
                Drawable drawable = getActivityIconWithCache(component);
                if (drawable != null) {
                    return drawable;
                }
            } else {
                Log.w(LOG_TAG, "Bad component name: " + c);
            }
        }

        // Then check the component that gave us the suggestion
        // Check the component that gave us the suggestion
        Drawable drawable = getActivityIconWithCache(mSearchable.getSearchActivity());
        if (drawable != null) {
            return drawable;
+46 −15
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ public class SearchView extends LinearLayout {
    private AutoCompleteTextView mQueryTextView;
    private boolean mSubmitButtonEnabled;
    private CharSequence mQueryHint;
    private boolean mQueryRefinement;

    private SearchableInfo mSearchable;

@@ -282,7 +283,34 @@ public class SearchView extends LinearLayout {
        return mSubmitButtonEnabled;
    }

    public interface FilterableListAdapter extends ListAdapter, Filterable {
    /**
     * Specifies if a query refinement button should be displayed alongside each suggestion
     * or if it should depend on the flags set in the individual items retrieved from the
     * suggestions provider. Clicking on the query refinement button will replace the text
     * in the query text field with the text from the suggestion. This flag only takes effect
     * if a SearchableInfo has been specified with {@link #setSearchableInfo(SearchableInfo)}
     * and not when using a custom adapter.
     *
     * @param enable true if all items should have a query refinement button, false if only
     * those items that have a query refinement flag set should have the button.
     *
     * @see SearchManager#SUGGEST_COLUMN_FLAGS
     * @see SearchManager#FLAG_QUERY_REFINEMENT
     */
    public void setQueryRefinementEnabled(boolean enable) {
        mQueryRefinement = enable;
        if (mSuggestionsAdapter instanceof SuggestionsAdapter) {
            ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement(
                    enable ? SuggestionsAdapter.REFINE_ALL : SuggestionsAdapter.REFINE_BY_ENTRY);
        }
    }

    /**
     * Returns whether query refinement is enabled for all items or only specific ones.
     * @return true if enabled for all items, false otherwise.
     */
    public boolean isQueryRefinementEnabled() {
        return mQueryRefinement;
    }

    /**
@@ -333,6 +361,14 @@ public class SearchView extends LinearLayout {
        }
    }

    /**
     * Called by the SuggestionsAdapter
     * @hide
     */
    /* package */void onQueryRefine(CharSequence queryText) {
        setQuery(queryText);
    }

    private final OnClickListener mOnClickListener = new OnClickListener() {

        public void onClick(View v) {
@@ -403,6 +439,9 @@ public class SearchView extends LinearLayout {
            mSuggestionsAdapter = new SuggestionsAdapter(getContext(),
                    this, mSearchable, mOutsideDrawablesCache);
            mQueryTextView.setAdapter(mSuggestionsAdapter);
            ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement(
                    mQueryRefinement ? SuggestionsAdapter.REFINE_ALL
                    : SuggestionsAdapter.REFINE_BY_ENTRY);
        }
    }

@@ -555,12 +594,14 @@ public class SearchView extends LinearLayout {
     * Sets the text in the query box, without updating the suggestions.
     */
    private void setQuery(CharSequence query) {
        mQueryTextView.setText(query, false);
        mQueryTextView.setText(query, true);
        // Move the cursor to the end
        mQueryTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length());
    }

    private void launchQuerySearch(int actionKey, String actionMsg, String query) {
        String action = Intent.ACTION_SEARCH;
        Intent intent = createIntent(action, null, null, query, null, actionKey, actionMsg);
        Intent intent = createIntent(action, null, null, query, actionKey, actionMsg);
        getContext().startActivity(intent);
    }

@@ -571,7 +612,6 @@ public class SearchView extends LinearLayout {
     * @param data Intent data, or <code>null</code>.
     * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>.
     * @param query Intent query, or <code>null</code>.
     * @param componentName Data for {@link SearchManager#COMPONENT_NAME_KEY} or <code>null</code>.
     * @param actionKey The key code of the action key that was pressed,
     *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
     * @param actionMsg The message for the action key that was pressed,
@@ -581,7 +621,7 @@ public class SearchView extends LinearLayout {
     * @return The intent.
     */
    private Intent createIntent(String action, Uri data, String extraData, String query,
            String componentName, int actionKey, String actionMsg) {
            int actionKey, String actionMsg) {
        // Now build the Intent
        Intent intent = new Intent(action);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -624,11 +664,6 @@ public class SearchView extends LinearLayout {
            // use specific action if supplied, or default action if supplied, or fixed default
            String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION);

            // some items are display only, or have effect via the cursor respond click reporting.
            if (SearchManager.INTENT_ACTION_NONE.equals(action)) {
                return null;
            }

            if (action == null) {
                action = mSearchable.getSuggestIntentAction();
            }
@@ -650,14 +685,10 @@ public class SearchView extends LinearLayout {
            }
            Uri dataUri = (data == null) ? null : Uri.parse(data);

            String componentName = getColumnString(
                    c, SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME);

            String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY);
            String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);

            return createIntent(action, dataUri, extraData, query, componentName, actionKey,
                    actionMsg);
            return createIntent(action, dataUri, extraData, query, actionKey, actionMsg);
        } catch (RuntimeException e ) {
            int rowNum;
            try {                       // be really paranoid now
Loading