1. 前言
Android系统提供了的一种搜索服务,利用此服务可以实现对系统中的应用、联系人、SMS等进行搜索,也提供转入浏览器中的搜索。Android Develop Blog中有一篇文章赞美了Android搜索功能的强大快捷——《Introducing Quick Search Box for Android》。
SearchManager是搜索服务的入口,可以通过context.getSystemService(Context.SEARCH_SERVICE)获取SearchManager对象。SearchManager像其他ActivityManager、PackageManager等服务一样,是随系统启动一起启动的服务,并且启动后向ServiceManager注册自己,客户端最终获取搜索服务的途径也是通过binder机制向ServiceManager获取的。
从搜索的角度来看,应用可分为三类: unsearchable 类型应用、Query-Search 类型应用和 Filter-Search 类型应用。大部分应用是属于后两种。不过,即便是第一种类型,应用也仍旧支持对搜索的调用。后两种的区分就在于,Query-Search 类型应用执行 batch-mode 搜索,每一个查询字符串都被转化成结果列表;Filter-Search 类型应用则提供 filter-as-you-type 搜索。通常来讲,对基于网络的数据进行 Query Search,而对本地数据,则需要 Filter Search。
2. 整体类图
从上面的类图可以看出SearchManager提供的搜索服务最终是由ISearchManager这个接口的实现类提供的。同时SearchManager又实现了Dialog相关的两个接口OnDismissListener和OnCancelListener,以及内置一个SearchDialog,这些是为了搜索框实现服务的,因为在Android系统中的搜索服务界面就是一个Quick Search Box。下面我们就来先分析一个ISearchManager这一块提供了什么样的搜索服务以及如何提供搜索服务。
3. SearchManagerService 提供搜索服务
ISearchManager是利用AIDL定义的,因此它的代码利用aapt编译生成的,组织方式使用了代理模式。ISearchManager.Stub的实现类是SearchManagerService,所以真正提供搜索服务的是这个类。
ISearchManager接口中定义搜索相关的基础服务,有如下的方法:
- public SearchableInfo getSearchableInfo(ComponentName launchActivity) throws RemoteException;
- public List<SearchableInfo> getSearchablesInGlobalSearch() throws RemoteException;
- public ComponentName getGlobalSearchActivity() throws RemoteException;
- public ComponentName getWebSearchActivity() throws RemoteException;
// This field is initialized lazily in getSearchables(), and then never modified. private Searchables mSearchables;
private synchronized Searchables getSearchables() { if (mSearchables == null) { Log.i(TAG, "Building list of searchable activities"); new MyPackageMonitor().register(mContext, true); mSearchables = new Searchables(mContext); mSearchables.buildSearchableList(); } return mSearchables; }
class MyPackageMonitor extends PackageMonitor { @Override public void onSomePackagesChanged() { // Update list of searchable activities getSearchables().buildSearchableList(); // Inform all listeners that the list of searchables has been updated. Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); mContext.sendBroadcast(intent); } }
private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null; private ArrayList<SearchableInfo> mSearchablesList = null; private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null; private ComponentName mGlobalSearchActivity = null; private ComponentName mWebSearchActivity = null;
final PackageManager pm = mContext.getPackageManager(); // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers. List<ResolveInfo> searchList; final Intent intent = new Intent(Intent.ACTION_SEARCH); searchList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA); List<ResolveInfo> webSearchInfoList; final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH); webSearchInfoList = pm.queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);然后分别取遍历searchList和webSearchInfoList去填充mSearchablesMap对象、mSearchablesList对象
if (searchList != null || webSearchInfoList != null) { int search_count = (searchList == null ? 0 : searchList.size()); int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size()); int count = search_count + web_search_count; for (int ii = 0; ii < count; ii++) { // for each component, try to find metadata ResolveInfo info = (ii < search_count) ? searchList.get(ii) : webSearchInfoList.get(ii - search_count); ActivityInfo ai = info.activityInfo; // Check first to avoid duplicate entries. if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) { SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai); if (searchable != null) { newSearchablesList.add(searchable); newSearchablesMap.put(searchable.getSearchActivity(), searchable); if (searchable.shouldIncludeInGlobalSearch()) { newSearchablesInGlobalSearchList.add(searchable); } } } } }
com.android.contacts.SearchResultsActivity
com.android.browser.BookmarkSearch
com.android.music.QueryBrowserActivity
4. SearchManager提供搜索相关操作
SearchManager是搜索服务的入口,客户端获取SearchManager对象可以调用getSystemService方法来获得。
SearchManager searchManager = (SearchManager)this.getSystemService(SEARCH_SERVICE);
可以看到SearchManager内部定义了两个回调接口OnDismissListener和OnCancelListener,并且实现了DialogInterface.OnDismissListener和DialogInterface.OnCancelListener接口,客户端可以通过setOnDismissListener和setOnCancelListener来设置搜索框消失和取消时的事件处理。
SearchManager有个SearchDialog类型的对象mSearchDialog,它就是搜索时显示的搜索框。
看一下SearchManager中的一些重要方法,
- public void startSearch(String initialQuery, boolean selectInitialQuery, ComponentName launchActivity, Bundle appSearchData, boolean globalSearch)
public void startSearch(String initialQuery, boolean selectInitialQuery, ComponentName launchActivity, Bundle appSearchData, boolean globalSearch) { if (globalSearch) { startGlobalSearch(initialQuery, selectInitialQuery, appSearchData); return; } ensureSearchDialog(); mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData); }
/* package */ void startGlobalSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData) { ComponentName globalSearchActivity = getGlobalSearchActivity(); if (globalSearchActivity == null) { Log.w(TAG, "No global search activity found."); return; } Intent intent = new Intent(INTENT_ACTION_GLOBAL_SEARCH); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setComponent(globalSearchActivity); // Make sure that we have a Bundle to put source in if (appSearchData == null) { appSearchData = new Bundle(); } else { appSearchData = new Bundle(appSearchData); } // Set source to package name of app that starts global search, if not set already. if (!appSearchData.containsKey("source")) { appSearchData.putString("source", mContext.getPackageName()); } intent.putExtra(APP_DATA, appSearchData); if (!TextUtils.isEmpty(initialQuery)) { intent.putExtra(QUERY, initialQuery); } if (selectInitialQuery) { intent.putExtra(EXTRA_SELECT_QUERY, selectInitialQuery); } try { if (DBG) Log.d(TAG, "Starting global search: " + intent.toUri(0)); mContext.startActivity(intent); } catch (ActivityNotFoundException ex) { Log.e(TAG, "Global search activity not found: " + globalSearchActivity); } }可以看到startGlobalSearch做的事情就是打开globalSearchActivity,上面我分析可以知道globalSearchActivity就是com.android.quicksearchbox.SearchActivity,其实就是打开了QuickSearchBox应用的首界面。
- public void triggerSearch(String query, ComponentName launchActivity, Bundle appSearchData)
- public void stopSearch()
- public Cursor getSuggestions(SearchableInfo searchable, String query, int limit)
这个方法被标为@hide的,是android内部的api。
5. SuggestionsAdapter填充SearchDialog的下拉框数据
6. SearchRecentSuggestions与SearchRecentSuggestionsProvider辅助实现搜索的历史记录
7. 搜索在系统组件中的分布
Activity中有方法onSearchRequested
8. meta-data标签的使用
参考:http://blog.csdn.net/happy_6678/article/details/6556771
9. 与ContentProvider相关
参考:http://www.cnblogs.com/over140/archive/2011/12/28/2304393.html
相关推荐
在Android开发中,SearchManager是一个非常重要的组件,它主要用于实现应用程序内的全局搜索功能。这个功能让用户可以在不离开当前界面的情况下快速查找和访问应用中的数据。本文将深入探讨SearchManager的工作原理...
本教程将深入探讨如何使用SearchManager来创建一个浮动搜索框,以及相关的源码分析。 一、SearchManager概述 SearchManager是Android系统提供的服务,用于管理系统的全局搜索配置和启动搜索活动。它可以帮助开发者...
在安卓开发中,集成百度...综上所述,“安卓Android源码——百度地图搜索Search.zip”项目涵盖了地图应用的核心功能,通过学习和分析这些源码,开发者可以深入了解如何在Android应用中集成并优化百度地图的搜索功能。
对于开发者,Android提供了`SearchManager`类,用于获取和设置搜索相关的信息,如获取搜索建议,启动搜索活动等。 总的来说,QuickSearchBox是Android系统中不可或缺的一部分,它通过高效地整合系统内外的各种搜索...
本压缩包“安卓Android源码——百度地图API 之 定位周边搜索POI.zip”显然包含了实现这些功能的源代码示例,主要聚焦在用户位置的获取和周围兴趣点(POI)的搜索上。 首先,我们来讨论一下“定位”这一关键知识点。...
这个压缩包文件“安卓Android源码——安卓调用百度地图,实现定位和搜索功能.zip”提供了示例代码,帮助开发者了解如何在Android应用中调用百度地图服务。以下是对这些功能的详细讲解: 首先,我们需要在项目中添加...
本项目"基于Android的浮动搜索框(SearchManager)"是专为Android初学者和毕业生设计的学习资源,适用于使用Android Studio、IntelliJ IDEA以及Eclipse等IDE的开发者,尤其是推荐使用Android Studio,因为它是目前...
通过研究"浮动搜索框(SearchManager).doc"中的源码,你可以深入了解SearchManager的工作原理,学习如何在自己的应用中实现一个高效且用户友好的浮动搜索框。这份文档应该包含了具体的代码示例和实现细节,可以帮助...
在Android开发中,有时我们需要集成硬件设备,如扫描枪,以实现快速的条形码或二维码读取功能。"Android监听扫描枪设备自带扫描键DemoT"是一个针对此类需求的示例项目,它展示了如何在Android应用中监听并处理扫描枪...
在Android开发中,`SearchManager` 是一个非常重要的组件,它提供了一种高效且用户友好的方式来实现全局搜索功能。浮动搜索框通常指的是在应用界面中可以浮现在其他视图之上,允许用户快速输入查询内容的搜索框。在...
本项目聚焦于“安卓app开发项目-浮动搜索框(SearchManager)”,它提供了源码,适合安卓开发的学习者进行毕业设计或者实践。以下是关于这个项目及其相关知识点的详细说明。 1. **浮动搜索框(Floating Search View...
《深入解析Android QuickSearchBox程序源码》 在Android系统中,QuickSearchBox(QSB)是一个非常重要的组件,它提供了...通过对源码的学习,我们可以更好地理解系统的运作机制,进而创造出更加智能、高效的搜索功能。
通过研究这些源码,学生不仅可以学习到如何使用SearchManager实现浮动搜索框,还能了解到Android Intent、Activity生命周期、UI组件的使用等基础知识,对于提升Android开发技能非常有帮助。 总结,这个毕业设计项目...
对于搜索功能,Android提供了SearchManager和Intent ACTION_SEARCH等工具,使得用户可以方便地搜索联系人。 总之,Android系统的Contacts模块是一个综合性的组件,它涉及UI设计、数据管理、用户交互等多个方面。...
Android---浮动搜索框(SearchManager)(An-Beer工作室)借鉴.pdf