FileDocCategorySizeDatePackage
SearchRecentSuggestionsProvider.javaAPI DocAndroid 1.5 API15331Wed May 06 22:41:54 BST 2009android.content

SearchRecentSuggestionsProvider

public class SearchRecentSuggestionsProvider extends ContentProvider
This superclass can be used to create a simple search suggestions provider for your application. It creates suggestions (as the user types) based on recent queries and/or recent views.

In order to use this class, you must do the following.

  • Implement and test query search, as described in {@link android.app.SearchManager}. (This provider will send any suggested queries via the standard {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} Intent, which you'll already support once you have implemented and tested basic searchability.)
  • Create a Content Provider within your application by extending {@link android.content.SearchRecentSuggestionsProvider}. The class you create will be very simple - typically, it will have only a constructor. But the constructor has a very important responsibility: When it calls {@link #setupSuggestions(String, int)}, it configures the provider to match the requirements of your searchable activity.
  • Create a manifest entry describing your provider. Typically this would be as simple as adding the following lines:
    <!-- Content provider for search suggestions -->
    <provider android:name="YourSuggestionProviderClass"
    android:authorities="your.suggestion.authority" />
  • Please note that you do not instantiate this content provider directly from within your code. This is done automatically by the system Content Resolver, when the search dialog looks for suggestions.
  • In order for the Content Resolver to do this, you must update your searchable activity's XML configuration file with information about your content provider. The following additions are usually sufficient:
    android:searchSuggestAuthority="your.suggestion.authority"
    android:searchSuggestSelection=" ? "
  • In your searchable activities, capture any user-generated queries and record them for future searches by calling {@link android.provider.SearchRecentSuggestions#saveRecentQuery SearchRecentSuggestions.saveRecentQuery()}.
see
android.provider.SearchRecentSuggestions

Fields Summary
private static final String
TAG
private String
mAuthority
private int
mMode
private boolean
mTwoLineDisplay
private android.database.sqlite.SQLiteOpenHelper
mOpenHelper
private static final String
sDatabaseName
private static final String
sSuggestions
private static final String
ORDER_BY
private static final String
NULL_COLUMN
private static final int
DATABASE_VERSION
public static final int
DATABASE_MODE_QUERIES
This mode bit configures the database to record recent queries. required
public static final int
DATABASE_MODE_2LINES
This mode bit configures the database to include a 2nd annotation line with each entry. optional
private static final int
URI_MATCH_SUGGEST
private android.net.Uri
mSuggestionsUri
private UriMatcher
mUriMatcher
private String
mSuggestSuggestionClause
private String[]
mSuggestionProjection
Constructors Summary
Methods Summary
public intdelete(android.net.Uri uri, java.lang.String selection, java.lang.String[] selectionArgs)
This method is provided for use by the ContentResolver. Do not override, or directly call from your own code.

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();

        final int length = uri.getPathSegments().size();
        if (length != 1) {
            throw new IllegalArgumentException("Unknown Uri");
        }

        final String base = uri.getPathSegments().get(0);
        int count = 0;
        if (base.equals(sSuggestions)) {
            count = db.delete(sSuggestions, selection, selectionArgs);
        } else {
            throw new IllegalArgumentException("Unknown Uri");
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    
public java.lang.StringgetType(android.net.Uri uri)
This method is provided for use by the ContentResolver. Do not override, or directly call from your own code.

        if (mUriMatcher.match(uri) == URI_MATCH_SUGGEST) {
            return SearchManager.SUGGEST_MIME_TYPE;
        }
        int length = uri.getPathSegments().size();
        if (length >= 1) {
            String base = uri.getPathSegments().get(0);
            if (base.equals(sSuggestions)) {
                if (length == 1) {
                    return "vnd.android.cursor.dir/suggestion";
                } else if (length == 2) {
                    return "vnd.android.cursor.item/suggestion";
                }
            }
        }            
        throw new IllegalArgumentException("Unknown Uri");
    
public android.net.Uriinsert(android.net.Uri uri, ContentValues values)
This method is provided for use by the ContentResolver. Do not override, or directly call from your own code.

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();

        int length = uri.getPathSegments().size();
        if (length < 1) {
            throw new IllegalArgumentException("Unknown Uri");
        }
        // Note:  This table has on-conflict-replace semantics, so insert() may actually replace()
        long rowID = -1;
        String base = uri.getPathSegments().get(0);
        Uri newUri = null;
        if (base.equals(sSuggestions)) {
            if (length == 1) {
                rowID = db.insert(sSuggestions, NULL_COLUMN, values);
                if (rowID > 0) {
                    newUri = Uri.withAppendedPath(mSuggestionsUri, String.valueOf(rowID));
                }
            }
        }
        if (rowID < 0) {
            throw new IllegalArgumentException("Unknown Uri");
        }
        getContext().getContentResolver().notifyChange(newUri, null);
        return newUri;
    
public booleanonCreate()
This method is provided for use by the ContentResolver. Do not override, or directly call from your own code.

        if (mAuthority == null || mMode == 0) {
            throw new IllegalArgumentException("Provider not configured");
        }
        int mWorkingDbVersion = DATABASE_VERSION + mMode;
        mOpenHelper = new DatabaseHelper(getContext(), mWorkingDbVersion);
        
        return true;
    
public android.database.Cursorquery(android.net.Uri uri, java.lang.String[] projection, java.lang.String selection, java.lang.String[] selectionArgs, java.lang.String sortOrder)
This method is provided for use by the ContentResolver. Do not override, or directly call from your own code.

        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        
        // special case for actual suggestions (from search manager)
        if (mUriMatcher.match(uri) == URI_MATCH_SUGGEST) {
            String suggestSelection;
            String[] myArgs;
            if (TextUtils.isEmpty(selectionArgs[0])) {
                suggestSelection = null;
                myArgs = null;
            } else {
                String like = "%" + selectionArgs[0] + "%";
                if (mTwoLineDisplay) {
                    myArgs = new String [] { like, like };
                } else {
                    myArgs = new String [] { like };
                }
                suggestSelection = mSuggestSuggestionClause;
            }
            // Suggestions are always performed with the default sort order
            Cursor c = db.query(sSuggestions, mSuggestionProjection,
                    suggestSelection, myArgs, null, null, ORDER_BY, null);
            c.setNotificationUri(getContext().getContentResolver(), uri);
            return c;
        }

        // otherwise process arguments and perform a standard query
        int length = uri.getPathSegments().size();
        if (length != 1 && length != 2) {
            throw new IllegalArgumentException("Unknown Uri");
        }

        String base = uri.getPathSegments().get(0);
        if (!base.equals(sSuggestions)) {
            throw new IllegalArgumentException("Unknown Uri");
        }

        String[] useProjection = null;
        if (projection != null && projection.length > 0) {
            useProjection = new String[projection.length + 1];
            System.arraycopy(projection, 0, useProjection, 0, projection.length);
            useProjection[projection.length] = "_id AS _id";
        }

        StringBuilder whereClause = new StringBuilder(256);
        if (length == 2) {
            whereClause.append("(_id = ").append(uri.getPathSegments().get(1)).append(")");
        }

        // Tack on the user's selection, if present
        if (selection != null && selection.length() > 0) {
            if (whereClause.length() > 0) {
                whereClause.append(" AND ");
            }

            whereClause.append('(");
            whereClause.append(selection);
            whereClause.append(')");
        }
        
        // And perform the generic query as requested
        Cursor c = db.query(base, useProjection, whereClause.toString(),
                selectionArgs, null, null, sortOrder,
                null);
        c.setNotificationUri(getContext().getContentResolver(), uri);
        return c;
    
protected voidsetupSuggestions(java.lang.String authority, int mode)
In order to use this class, you must extend it, and call this setup function from your constructor. In your application or activities, you must provide the same values when you create the {@link android.provider.SearchRecentSuggestions} helper.

param
authority This must match the authority that you've declared in your manifest.
param
mode You can use mode flags here to determine certain functional aspects of your database. Note, this value should not change from run to run, because when it does change, your suggestions database may be wiped.
see
#DATABASE_MODE_QUERIES
see
#DATABASE_MODE_2LINES

        if (TextUtils.isEmpty(authority) || 
                ((mode & DATABASE_MODE_QUERIES) == 0)) {
            throw new IllegalArgumentException();
        }
        // unpack mode flags
        mTwoLineDisplay = (0 != (mode & DATABASE_MODE_2LINES));
            
        // saved values
        mAuthority = new String(authority);
        mMode = mode;
        
        // derived values
        mSuggestionsUri = Uri.parse("content://" + mAuthority + "/suggestions");
        mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        mUriMatcher.addURI(mAuthority, SearchManager.SUGGEST_URI_PATH_QUERY, URI_MATCH_SUGGEST);
        
        if (mTwoLineDisplay) {
            mSuggestSuggestionClause = "display1 LIKE ? OR display2 LIKE ?";

            mSuggestionProjection = new String [] {
                    "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
                    "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
                    "display2 AS " + SearchManager.SUGGEST_COLUMN_TEXT_2,
                    "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
                    "_id"
            };
        } else {
            mSuggestSuggestionClause = "display1 LIKE ?";

            mSuggestionProjection = new String [] {
                    "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
                    "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
                    "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
                    "_id"
            };
        }


    
public intupdate(android.net.Uri uri, ContentValues values, java.lang.String selection, java.lang.String[] selectionArgs)
This method is provided for use by the ContentResolver. Do not override, or directly call from your own code.

        throw new UnsupportedOperationException("Not implemented");