2010-08-04 68 views
2

我想在我的应用程序中实现搜索方法。我有一个数据库,我想使用快速搜索框在该数据库中进行搜索。请帮我完成这个任务。如何在我的Android应用程序中使用QuickSearchBox?

+0

有一个博客帖子在http://android-developers.blogspot.com/2009/09/introducing-quick-search- box-for.html,但没有详细介绍,因此请参阅下面的代码示例。 – 2010-08-04 04:39:41

回答

3

三个文件相关,DataProvider,DataIndex,更改为AndroidManifest。 在我的情况下,我想在数据库中查找的数据对象是'位置'数据对象,因此我的类的名称,但您可以将它应用于您的逻辑没有问题。

LocationProvider.java:

package com.myapp.android.search; 

import android.app.SearchManager; 
import android.content.ContentProvider; 
import android.content.ContentValues; 
import android.content.UriMatcher; 
import android.content.res.Resources; 
import android.database.Cursor; 
import android.database.MatrixCursor; 
import android.net.Uri; 
import android.text.TextUtils; 
import android.util.Log; 
import com.myapp.android.MyApp; 
import com.myapp.android.model.Location; 

import java.util.ArrayList; 

/** 
* Provides search suggestions for a list of words and their definitions. 
*/ 
public class LocationProvider extends ContentProvider { 

    public static String AUTHORITY = "myapp_locations"; 

    private static final int SEARCH_SUGGEST = 0; 
    private static final int SHORTCUT_REFRESH = 1; 
    private static final UriMatcher sURIMatcher = buildUriMatcher(); 

    /** 
    * The columns we'll include in our search suggestions. There are others that could be used 
    * to further customize the suggestions, see the docs in {@link SearchManager} for the details 
    * on additional columns that are supported. 
    */ 
    private static final String[] COLUMNS = { 
      "_id", // must include this column 
      SearchManager.SUGGEST_COLUMN_TEXT_1, 
      SearchManager.SUGGEST_COLUMN_TEXT_2, 
      SearchManager.SUGGEST_COLUMN_INTENT_DATA, 
      }; 

    /** 
    * Sets up a uri matcher for search suggestion and shortcut refresh queries. 
    */ 
    private static UriMatcher buildUriMatcher() { 
     UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); 
     matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST); 
     matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST); 
     matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT, SHORTCUT_REFRESH); 
     matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", SHORTCUT_REFRESH); 
     return matcher; 
    } 

    @Override 
    public boolean onCreate() { 
     Resources resources = getContext().getResources(); 
     // LocationIndex.getInstance(this.getContext()).ensureLoaded(resources); 
     return true; 
    } 

    @Override 
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 
      String sortOrder) { 
     if (!TextUtils.isEmpty(selection)) { 
      throw new IllegalArgumentException("selection not allowed for " + uri); 
     } 
     if (selectionArgs != null && selectionArgs.length != 0) { 
      throw new IllegalArgumentException("selectionArgs not allowed for " + uri); 
     } 
     if (!TextUtils.isEmpty(sortOrder)) { 
      throw new IllegalArgumentException("sortOrder not allowed for " + uri); 
     } 
     switch (sURIMatcher.match(uri)) { 
      case SEARCH_SUGGEST: 
       String query = null; 
       if (uri.getPathSegments().size() > 1) { 
        query = uri.getLastPathSegment().toLowerCase(); 
       } 
       return getSuggestions(query, projection); 
      case SHORTCUT_REFRESH: 
       String shortcutId = null; 
       if (uri.getPathSegments().size() > 1) { 
        shortcutId = uri.getLastPathSegment(); 
       } 
       return refreshShortcut(shortcutId, projection); 
      default: 
       throw new IllegalArgumentException("Unknown URL " + uri); 
     } 
    } 

    private Cursor getSuggestions(String query, String[] projection) { 
     String processedQuery = query == null ? "" : query.toLowerCase(); 
     ArrayList<Location> words = LocationIndex.getInstance().getMatches(processedQuery); 
     MatrixCursor cursor = new MatrixCursor(COLUMNS); 
     long id = 0; 
     for (Location word : words) { 
      cursor.addRow(columnValuesOfWord(id++, word)); 
     } 
     return cursor; 
    } 

    private Object[] columnValuesOfWord(long id, Location loc) { 
     return new Object[] { 
       id,      // _id 
       loc.getTitle(),   // text1 
       loc.getDescription(),  // text2 
       loc.getTitle(),   // intent_data (included when clicking on item) 
     }; 
    } 

    /** 
    * Note: this is unused as is, but if we included 
    * {@link SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} as a column in our results, we 
    * could expect to receive refresh queries on this uri for the id provided, in which case we 
    * would return a cursor with a single item representing the refreshed suggestion data. 
    */ 
    private Cursor refreshShortcut(String shortcutId, String[] projection) { 
     return null; 
    } 

    /** 
    * All queries for this provider are for the search suggestion and shortcut refresh mime type. 
    */ 
    public String getType(Uri uri) { 
     switch (sURIMatcher.match(uri)) { 
      case SEARCH_SUGGEST: 
       return SearchManager.SUGGEST_MIME_TYPE; 
      case SHORTCUT_REFRESH: 
       return SearchManager.SHORTCUT_MIME_TYPE; 
      default: 
       throw new IllegalArgumentException("Unknown URL " + uri); 
     } 
    } 

    public Uri insert(Uri uri, ContentValues values) { 
     throw new UnsupportedOperationException(); 
    } 

    public int delete(Uri uri, String selection, String[] selectionArgs) { 
     throw new UnsupportedOperationException(); 
    } 

    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 
     throw new UnsupportedOperationException(); 
    } 
} 

LocationIndex.java

package com.myapp.android.search; 

import com.myapp.android.model.Location; 

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.concurrent.ConcurrentHashMap; 

public class LocationIndex { 

    private boolean mLoaded = false; 
    private static final LocationIndex sInstance = new LocationIndex(); 
    private ArrayList<Location> locations; 
    private final ConcurrentHashMap<String, ArrayList<Location>> mDict = new ConcurrentHashMap<String, ArrayList<Location>>(); 

    public static LocationIndex getInstance() { 
     return sInstance; 
    } 

    public synchronized void loadWords(ArrayList<Location> locations) { //throws IOException, Resources resources 
     if (mLoaded) return; 
     this.locations = locations; 
     for (Iterator<Location> iter=locations.iterator();iter.hasNext();) {    
      Location loc = iter.next(); 
      if (loc!=null) addLocation(loc); 
     } 
     mLoaded = true; 

    } 

    public ArrayList<Location> getMatches(String query) { 
     ArrayList<Location> list = mDict.get(query); 
     return list == null ? new ArrayList<Location>() : list; 
    } 

    private void addLocation(Location loc) { 
     final int len = loc.getTitle().length(); 
     for (int i = 0; i < len; i++) { 
      final String prefix = loc.getTitle().substring(0, len - i); 
      addMatch(prefix, loc); 
     } 
    } 

    private void addMatch(String query, Location loc) {  
     ArrayList<Location> matches = mDict.get(query); 
     if (matches == null) { 
      matches = new ArrayList<Location>(); 
      mDict.put(query.toLowerCase(), matches); 
     } 
     matches.add(loc); 
    } 

    public ConcurrentHashMap<String, ArrayList<Location>> getmDict() { 
     return mDict; 
    } 
} 

AndroidManifest.xml中

以下内容添加到您的清单......

<!-- Provides search suggestions for words and their definitions. --> 
<provider android:name=".search.LocationProvider" 
      android:authorities="myapp_locations" 
      android:syncable="false"/> 

<provider android:name=".content.LocalFileContentProvider" 
      android:authorities="com.myapp.android.localfile" 
      android:syncable="false"/> 

和在在活动10吨过滤器要激活搜索(也许所有):

<intent-filter> 
    <action android:name="android.intent.action.SEARCH"/> 
    <category android:name="android.intent.category.DEFAULT"/> 
</intent-filter> 
+0

我尝试了这些行,并且还查看了可搜索的字典。但是我无法从显示的建议中获得正确的建议ID。你能否告诉我,如果你有一个想法,我可能会出错。 http://stackoverflow.com/questions/4090228/intent-is-not-sending-the-id-of-the-search-suggestion-to-content-provider。谢谢 – achie 2010-11-03 20:12:24

相关问题