Merge "Clean up global search and web search activity finding"
This commit is contained in:
committed by
Android (Google) Code Review
commit
cfe79e9220
@@ -24,9 +24,8 @@ import android.os.Bundle;
|
||||
|
||||
/** @hide */
|
||||
interface ISearchManager {
|
||||
SearchableInfo getSearchableInfo(in ComponentName launchActivity, boolean globalSearch);
|
||||
SearchableInfo getSearchableInfo(in ComponentName launchActivity);
|
||||
List<SearchableInfo> getSearchablesInGlobalSearch();
|
||||
List<SearchableInfo> getSearchablesForWebSearch();
|
||||
SearchableInfo getDefaultSearchableForWebSearch();
|
||||
void setDefaultWebSearch(in ComponentName component);
|
||||
ComponentName getGlobalSearchActivity();
|
||||
ComponentName getWebSearchActivity();
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
|
||||
SearchManager searchManager = (SearchManager)
|
||||
mContext.getSystemService(Context.SEARCH_SERVICE);
|
||||
// Try to get the searchable info for the provided component.
|
||||
mSearchable = searchManager.getSearchableInfo(componentName, false);
|
||||
mSearchable = searchManager.getSearchableInfo(componentName);
|
||||
|
||||
if (mSearchable == null) {
|
||||
return false;
|
||||
|
||||
@@ -137,21 +137,11 @@ import java.util.List;
|
||||
* setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); // search within your activity
|
||||
* setDefaultKeyMode(DEFAULT_KEYS_SEARCH_GLOBAL); // search using platform global search</pre>
|
||||
*
|
||||
* <p><b>How to enable global search with Quick Search Box.</b> In addition to searching within
|
||||
* <p><b>How to start global search.</b> In addition to searching within
|
||||
* your activity or application, you can also use the Search Manager to invoke a platform-global
|
||||
* search, which uses Quick Search Box to search across the device and the web. There are two ways
|
||||
* to do this:
|
||||
* <ul><li>You can simply define "search" within your application or activity to mean global search.
|
||||
* This is described in more detail in the
|
||||
* <a href="#SearchabilityMetadata">Searchability Metadata</a> section. Briefly, you will
|
||||
* add a single meta-data entry to your manifest, declaring that the default search
|
||||
* for your application is "*". This indicates to the system that no application-specific
|
||||
* search activity is provided, and that it should launch web-based search instead.</li>
|
||||
* <li>Simply do nothing and the default implementation of
|
||||
* {@link android.app.Activity#onSearchRequested} will cause global search to be triggered.
|
||||
* (You can also always trigger search via a direct call to {@link android.app.Activity#startSearch}.
|
||||
* This is most useful if you wish to provide local searchability <i>and</i> access to global
|
||||
* search.)</li></ul>
|
||||
* search, which uses Quick Search Box to search across the device and the web.
|
||||
* Override {@link android.app.Activity#onSearchRequested} and call
|
||||
* {@link android.app.Activity#startSearch} with {@code globalSearch} set to {@code true}.
|
||||
*
|
||||
* <p><b>How to disable search from your activity.</b> Search is a system-wide feature and users
|
||||
* will expect it to be available in all contexts. If your UI design absolutely precludes
|
||||
@@ -871,12 +861,8 @@ import java.util.List;
|
||||
*
|
||||
* <p>The simplest way to specify this is to add a <i>search reference</i> element to the
|
||||
* application entry in the <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> file.
|
||||
* The value of this reference can be either of:
|
||||
* <ul><li>The name of your searchable activity.
|
||||
* It is typically prefixed by '.' to indicate that it's in the same package.</li>
|
||||
* <li>A "*" indicates that the system may select a default searchable activity, in which
|
||||
* case it will typically select web-based search.</li>
|
||||
* </ul>
|
||||
* The value of this reference should be the name of your searchable activity.
|
||||
* It is typically prefixed by '.' to indicate that it's in the same package.
|
||||
*
|
||||
* <p>Here is a snippet showing the necessary addition to the manifest entry for your
|
||||
* non-searchable activities.
|
||||
@@ -1662,32 +1648,15 @@ public class SearchManager
|
||||
/**
|
||||
* Gets the name of the global search activity.
|
||||
*
|
||||
* This is currently implemented by returning the first activity that handles
|
||||
* the GLOBAL_SEARCH intent and has the GLOBAL_SEARCH permission. If we allow
|
||||
* more than one global search acitivity to be installed, this code must be changed.
|
||||
*
|
||||
* TODO: Doing this every time we start global search is inefficient. Will fix that once
|
||||
* we have settled on the right mechanism for finding the global search activity.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public ComponentName getGlobalSearchActivity() {
|
||||
Intent intent = new Intent(INTENT_ACTION_GLOBAL_SEARCH);
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
List<ResolveInfo> activities =
|
||||
pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
int count = activities.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
ActivityInfo ai = activities.get(i).activityInfo;
|
||||
if (pm.checkPermission(Manifest.permission.GLOBAL_SEARCH,
|
||||
ai.packageName) == PackageManager.PERMISSION_GRANTED) {
|
||||
return new ComponentName(ai.packageName, ai.name);
|
||||
} else {
|
||||
Log.w(TAG, "Package " + ai.packageName + " wants to handle GLOBAL_SEARCH, "
|
||||
+ "but does not have the GLOBAL_SEARCH permission.");
|
||||
}
|
||||
try {
|
||||
return mService.getGlobalSearchActivity();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "getGlobalSearchActivity() failed: " + ex);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1700,13 +1669,12 @@ public class SearchManager
|
||||
* @hide
|
||||
*/
|
||||
public ComponentName getWebSearchActivity() {
|
||||
ComponentName globalSearch = getGlobalSearchActivity();
|
||||
if (globalSearch == null) {
|
||||
try {
|
||||
return mService.getWebSearchActivity();
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "getWebSearchActivity() failed: " + ex);
|
||||
return null;
|
||||
}
|
||||
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
|
||||
intent.setPackage(globalSearch.getPackageName());
|
||||
return intent.resolveActivity(mContext.getPackageManager());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1840,27 +1808,7 @@ public class SearchManager
|
||||
*/
|
||||
public SearchableInfo getSearchableInfo(ComponentName componentName) {
|
||||
try {
|
||||
return mService.getSearchableInfo(componentName, false);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "getSearchableInfo() failed: " + ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about a searchable activity.
|
||||
*
|
||||
* @param componentName The activity to get searchable information for.
|
||||
* @param globalSearch If <code>false</code>, return information about the given activity.
|
||||
* If <code>true</code>, return information about the global search activity.
|
||||
* @return Searchable information, or <code>null</code> if the activity is not searchable.
|
||||
*
|
||||
* @hide because SearchableInfo is not part of the API.
|
||||
*/
|
||||
public SearchableInfo getSearchableInfo(ComponentName componentName,
|
||||
boolean globalSearch) {
|
||||
try {
|
||||
return mService.getSearchableInfo(componentName, globalSearch);
|
||||
return mService.getSearchableInfo(componentName);
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "getSearchableInfo() failed: " + ex);
|
||||
return null;
|
||||
|
||||
@@ -123,24 +123,15 @@ public class SearchManagerService extends ISearchManager.Stub {
|
||||
* Returns the SearchableInfo for a given activity.
|
||||
*
|
||||
* @param launchActivity The activity from which we're launching this search.
|
||||
* @param globalSearch If false, this will only launch the search that has been specifically
|
||||
* defined by the application (which is usually defined as a local search). If no default
|
||||
* search is defined in the current application or activity, no search will be launched.
|
||||
* If true, this will always launch a platform-global (e.g. web-based) search instead.
|
||||
* @return Returns a SearchableInfo record describing the parameters of the search,
|
||||
* or null if no searchable metadata was available.
|
||||
*/
|
||||
public SearchableInfo getSearchableInfo(final ComponentName launchActivity,
|
||||
final boolean globalSearch) {
|
||||
if (globalSearch) {
|
||||
return getSearchables().getDefaultSearchable();
|
||||
} else {
|
||||
if (launchActivity == null) {
|
||||
Log.e(TAG, "getSearchableInfo(), activity == null");
|
||||
return null;
|
||||
}
|
||||
return getSearchables().getSearchableInfo(launchActivity);
|
||||
public SearchableInfo getSearchableInfo(final ComponentName launchActivity) {
|
||||
if (launchActivity == null) {
|
||||
Log.e(TAG, "getSearchableInfo(), activity == null");
|
||||
return null;
|
||||
}
|
||||
return getSearchables().getSearchableInfo(launchActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,27 +142,17 @@ public class SearchManagerService extends ISearchManager.Stub {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the searchable activities that handle web searches.
|
||||
* Can be called from any thread.
|
||||
* Gets the name of the global search activity.
|
||||
*/
|
||||
public List<SearchableInfo> getSearchablesForWebSearch() {
|
||||
return getSearchables().getSearchablesForWebSearchList();
|
||||
public ComponentName getGlobalSearchActivity() {
|
||||
return getSearchables().getGlobalSearchActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default searchable activity for web searches.
|
||||
* Can be called from any thread.
|
||||
* Gets the name of the web search activity.
|
||||
*/
|
||||
public SearchableInfo getDefaultSearchableForWebSearch() {
|
||||
return getSearchables().getDefaultSearchableForWebSearch();
|
||||
public ComponentName getWebSearchActivity() {
|
||||
return getSearchables().getWebSearchActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default searchable activity for web searches.
|
||||
* Can be called from any thread.
|
||||
*/
|
||||
public void setDefaultWebSearch(final ComponentName component) {
|
||||
getSearchables().setDefaultWebSearch(component);
|
||||
broadcastSearchablesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
package android.server.search;
|
||||
|
||||
import com.android.internal.app.ResolverActivity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.SearchManager;
|
||||
import android.app.SearchableInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
@@ -52,9 +50,8 @@ public class Searchables {
|
||||
private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null;
|
||||
private ArrayList<SearchableInfo> mSearchablesList = null;
|
||||
private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null;
|
||||
private ArrayList<SearchableInfo> mSearchablesForWebSearchList = null;
|
||||
private SearchableInfo mDefaultSearchable = null;
|
||||
private SearchableInfo mDefaultSearchableForWebSearch = null;
|
||||
private ComponentName mGlobalSearchActivity = null;
|
||||
private ComponentName mWebSearchActivity = null;
|
||||
|
||||
public static String GOOGLE_SEARCH_COMPONENT_NAME =
|
||||
"com.android.googlesearch/.GoogleSearch";
|
||||
@@ -131,10 +128,9 @@ public class Searchables {
|
||||
// Irrespective of source, if a reference was found, follow it.
|
||||
if (refActivityName != null)
|
||||
{
|
||||
// An app or activity can declare that we should simply launch
|
||||
// "system default search" if search is invoked.
|
||||
// This value is deprecated, return null
|
||||
if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
|
||||
return getDefaultSearchable();
|
||||
return null;
|
||||
}
|
||||
String pkg = activity.getPackageName();
|
||||
ComponentName referredActivity;
|
||||
@@ -163,20 +159,6 @@ public class Searchables {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the system-default search activity, which you can use
|
||||
* whenever getSearchableInfo() returns null;
|
||||
*
|
||||
* @return Returns the system-default search activity, null if never defined
|
||||
*/
|
||||
public synchronized SearchableInfo getDefaultSearchable() {
|
||||
return mDefaultSearchable;
|
||||
}
|
||||
|
||||
public synchronized boolean isDefaultSearchable(SearchableInfo searchable) {
|
||||
return searchable == mDefaultSearchable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an entire list (suitable for display) of
|
||||
* activities that are searchable, by iterating the entire set of
|
||||
@@ -205,8 +187,6 @@ public class Searchables {
|
||||
= new ArrayList<SearchableInfo>();
|
||||
ArrayList<SearchableInfo> newSearchablesInGlobalSearchList
|
||||
= new ArrayList<SearchableInfo>();
|
||||
ArrayList<SearchableInfo> newSearchablesForWebSearchList
|
||||
= new ArrayList<SearchableInfo>();
|
||||
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
|
||||
@@ -244,127 +224,71 @@ public class Searchables {
|
||||
}
|
||||
}
|
||||
|
||||
if (webSearchInfoList != null) {
|
||||
for (int i = 0; i < webSearchInfoList.size(); ++i) {
|
||||
ActivityInfo ai = webSearchInfoList.get(i).activityInfo;
|
||||
ComponentName component = new ComponentName(ai.packageName, ai.name);
|
||||
SearchableInfo searchable = newSearchablesMap.get(component);
|
||||
if (searchable == null) {
|
||||
Log.w(LOG_TAG, "did not find component in searchables: " + component);
|
||||
} else {
|
||||
newSearchablesForWebSearchList.add(searchable);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find the global search activity
|
||||
ComponentName newGlobalSearchActivity = findGlobalSearchActivity();
|
||||
|
||||
// Find the global search provider
|
||||
Intent globalSearchIntent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
|
||||
ComponentName globalSearchActivity = globalSearchIntent.resolveActivity(pm);
|
||||
SearchableInfo newDefaultSearchable = newSearchablesMap.get(globalSearchActivity);
|
||||
|
||||
if (newDefaultSearchable == null) {
|
||||
Log.w(LOG_TAG, "No searchable info found for new default searchable activity "
|
||||
+ globalSearchActivity);
|
||||
}
|
||||
|
||||
// Find the default web search provider.
|
||||
ComponentName webSearchActivity = getPreferredWebSearchActivity(mContext);
|
||||
SearchableInfo newDefaultSearchableForWebSearch = null;
|
||||
if (webSearchActivity != null) {
|
||||
newDefaultSearchableForWebSearch = newSearchablesMap.get(webSearchActivity);
|
||||
}
|
||||
if (newDefaultSearchableForWebSearch == null) {
|
||||
Log.w(LOG_TAG, "No searchable info found for new default web search activity "
|
||||
+ webSearchActivity);
|
||||
}
|
||||
// Find the web search activity
|
||||
ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
|
||||
|
||||
// Store a consistent set of new values
|
||||
synchronized (this) {
|
||||
mSearchablesMap = newSearchablesMap;
|
||||
mSearchablesList = newSearchablesList;
|
||||
mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
|
||||
mSearchablesForWebSearchList = newSearchablesForWebSearchList;
|
||||
mDefaultSearchable = newDefaultSearchable;
|
||||
mDefaultSearchableForWebSearch = newDefaultSearchableForWebSearch;
|
||||
mGlobalSearchActivity = newGlobalSearchActivity;
|
||||
mWebSearchActivity = newWebSearchActivity;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given activity component is present in the system and if so makes it the
|
||||
* preferred activity for handling ACTION_WEB_SEARCH.
|
||||
* @param component Name of the component to check and set as preferred.
|
||||
* @param action Intent action for which this activity is to be set as preferred.
|
||||
* @return true if component was detected and set as preferred activity, false if not.
|
||||
* Finds the global search activity.
|
||||
*
|
||||
* This is currently implemented by returning the first activity that handles
|
||||
* the GLOBAL_SEARCH intent and has the GLOBAL_SEARCH permission. If we allow
|
||||
* more than one global search activity to be installed, this code must be changed.
|
||||
*/
|
||||
private static boolean setPreferredActivity(Context context,
|
||||
ComponentName component, String action) {
|
||||
Log.d(LOG_TAG, "Checking component " + component);
|
||||
PackageManager pm = context.getPackageManager();
|
||||
ActivityInfo ai;
|
||||
try {
|
||||
ai = pm.getActivityInfo(component, 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return false;
|
||||
private ComponentName findGlobalSearchActivity() {
|
||||
Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
List<ResolveInfo> activities =
|
||||
pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
int count = activities == null ? 0 : activities.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
ActivityInfo ai = activities.get(i).activityInfo;
|
||||
if (pm.checkPermission(Manifest.permission.GLOBAL_SEARCH,
|
||||
ai.packageName) == PackageManager.PERMISSION_GRANTED) {
|
||||
return new ComponentName(ai.packageName, ai.name);
|
||||
} else {
|
||||
Log.w(LOG_TAG, "Package " + ai.packageName + " wants to handle GLOBAL_SEARCH, "
|
||||
+ "but does not have the GLOBAL_SEARCH permission.");
|
||||
}
|
||||
}
|
||||
|
||||
// The code here to find the value for bestMatch is heavily inspired by the code
|
||||
// in ResolverActivity where the preferred activity is set.
|
||||
Intent intent = new Intent(action);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
List<ResolveInfo> webSearchActivities = pm.queryIntentActivities(intent, 0);
|
||||
ComponentName set[] = new ComponentName[webSearchActivities.size()];
|
||||
int bestMatch = 0;
|
||||
for (int i = 0; i < webSearchActivities.size(); ++i) {
|
||||
ResolveInfo ri = webSearchActivities.get(i);
|
||||
set[i] = new ComponentName(ri.activityInfo.packageName,
|
||||
ri.activityInfo.name);
|
||||
if (ri.match > bestMatch) bestMatch = ri.match;
|
||||
}
|
||||
|
||||
Log.d(LOG_TAG, "Setting preferred web search activity to " + component);
|
||||
IntentFilter filter = new IntentFilter(action);
|
||||
filter.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
pm.replacePreferredActivity(filter, bestMatch, set, component);
|
||||
return true;
|
||||
Log.w(LOG_TAG, "No global search activity found");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ComponentName getPreferredWebSearchActivity(Context context) {
|
||||
// Check if we have a preferred web search activity.
|
||||
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
|
||||
PackageManager pm = context.getPackageManager();
|
||||
ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
|
||||
if (ri == null || ri.activityInfo.name.equals(ResolverActivity.class.getName())) {
|
||||
Log.d(LOG_TAG, "No preferred activity set for action web search.");
|
||||
|
||||
// The components in the providers array are checked in the order of declaration so the
|
||||
// first one has the highest priority. If the component exists in the system it is set
|
||||
// as the preferred activity to handle intent action web search.
|
||||
String[] preferredActivities = context.getResources().getStringArray(
|
||||
com.android.internal.R.array.default_web_search_providers);
|
||||
for (String componentName : preferredActivities) {
|
||||
ComponentName component = ComponentName.unflattenFromString(componentName);
|
||||
if (setPreferredActivity(context, component, Intent.ACTION_WEB_SEARCH)) {
|
||||
return component;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the current preferred activity is GoogleSearch, and we detect
|
||||
// EnhancedGoogleSearch installed as well, set the latter as preferred since that
|
||||
// is a superset and provides more functionality.
|
||||
ComponentName cn = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
|
||||
if (cn.flattenToShortString().equals(GOOGLE_SEARCH_COMPONENT_NAME)) {
|
||||
ComponentName enhancedGoogleSearch = ComponentName.unflattenFromString(
|
||||
ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME);
|
||||
if (setPreferredActivity(context, enhancedGoogleSearch,
|
||||
Intent.ACTION_WEB_SEARCH)) {
|
||||
return enhancedGoogleSearch;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Finds the web search activity.
|
||||
*
|
||||
* Only looks in the package of the global search activity.
|
||||
*/
|
||||
private ComponentName findWebSearchActivity(ComponentName globalSearchActivity) {
|
||||
if (globalSearchActivity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ri == null) return null;
|
||||
return new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
|
||||
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
|
||||
intent.setPackage(globalSearchActivity.getPackageName());
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
List<ResolveInfo> activities =
|
||||
pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
int count = activities == null ? 0 : activities.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
ActivityInfo ai = activities.get(i).activityInfo;
|
||||
// TODO: do some sanity checks here?
|
||||
return new ComponentName(ai.packageName, ai.name);
|
||||
}
|
||||
Log.w(LOG_TAG, "No web search activity found");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,24 +307,16 @@ public class Searchables {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the searchable activities that handle web searches.
|
||||
* Gets the name of the global search activity.
|
||||
*/
|
||||
public synchronized ArrayList<SearchableInfo> getSearchablesForWebSearchList() {
|
||||
return new ArrayList<SearchableInfo>(mSearchablesForWebSearchList);
|
||||
public synchronized ComponentName getGlobalSearchActivity() {
|
||||
return mGlobalSearchActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default searchable activity for web searches.
|
||||
* Gets the name of the web search activity.
|
||||
*/
|
||||
public synchronized SearchableInfo getDefaultSearchableForWebSearch() {
|
||||
return mDefaultSearchableForWebSearch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default searchable activity for web searches.
|
||||
*/
|
||||
public synchronized void setDefaultWebSearch(ComponentName component) {
|
||||
setPreferredActivity(mContext, component, Intent.ACTION_WEB_SEARCH);
|
||||
buildSearchableList();
|
||||
public synchronized ComponentName getWebSearchActivity() {
|
||||
return mWebSearchActivity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,15 +127,4 @@
|
||||
<item><xliff:g id="id">ime</xliff:g></item>
|
||||
</string-array>
|
||||
|
||||
<!-- Do not translate. Each string points to the component name of an ACTION_WEB_SEARCH
|
||||
handling activity. On startup if there were no preferred ACTION_WEB_SEARCH handlers,
|
||||
the first component from this list which is found to be installed is set as the
|
||||
preferred activity. -->
|
||||
<string-array name="default_web_search_providers">
|
||||
<item>com.google.android.googlequicksearchbox/.google.GoogleSearch</item>
|
||||
<item>com.android.quicksearchbox/.google.GoogleSearch</item>
|
||||
<item>com.google.android.providers.enhancedgooglesearch/.Launcher</item>
|
||||
<item>com.android.googlesearch/.GoogleSearch</item>
|
||||
<item>com.android.websearch/.Search.1</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -64,39 +64,7 @@ public class SearchablesTest extends AndroidTestCase {
|
||||
* findActionKey works
|
||||
* getIcon works
|
||||
*/
|
||||
|
||||
/**
|
||||
* The goal of this test is to confirm proper operation of the
|
||||
* SearchableInfo helper class.
|
||||
*
|
||||
* TODO: The metadata source needs to be mocked out because adding
|
||||
* searchability metadata via this test is causing it to leak into the
|
||||
* real system. So for now I'm just going to test for existence of the
|
||||
* GlobalSearch app (which is searchable).
|
||||
*/
|
||||
public void testSearchableGlobalSearch() {
|
||||
// test basic array & hashmap
|
||||
Searchables searchables = new Searchables(mContext);
|
||||
searchables.buildSearchableList();
|
||||
|
||||
// test linkage from another activity
|
||||
// TODO inject this via mocking into the package manager.
|
||||
// TODO for now, just check for searchable GlobalSearch app (this isn't really a unit test)
|
||||
ComponentName thisActivity = new ComponentName(
|
||||
"com.android.globalsearch",
|
||||
"com.android.globalsearch.GlobalSearch");
|
||||
|
||||
SearchableInfo si = searchables.getSearchableInfo(thisActivity);
|
||||
assertNotNull(si);
|
||||
assertEquals(thisActivity, si.getSearchActivity());
|
||||
|
||||
Context appContext = si.getActivityContext(mContext);
|
||||
assertNotNull(appContext);
|
||||
MoreAsserts.assertNotEqual(appContext, mContext);
|
||||
assertEquals("Quick Search Box", appContext.getString(si.getHintId()));
|
||||
assertEquals("Quick Search Box", appContext.getString(si.getLabelId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that non-searchable activities return no searchable info (this would typically
|
||||
* trigger the use of the default searchable e.g. contacts)
|
||||
@@ -113,18 +81,7 @@ public class SearchablesTest extends AndroidTestCase {
|
||||
SearchableInfo si = searchables.getSearchableInfo(nonActivity);
|
||||
assertNull(si);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that there is a default searchable (aka global search provider).
|
||||
*/
|
||||
public void testDefaultSearchable() {
|
||||
Searchables searchables = new Searchables(mContext);
|
||||
searchables.buildSearchableList();
|
||||
SearchableInfo si = searchables.getDefaultSearchable();
|
||||
checkSearchable(si);
|
||||
assertTrue(searchables.isDefaultSearchable(si));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is an attempt to run the searchable info list with a mocked context. Here are some
|
||||
* things I'd like to test.
|
||||
@@ -371,7 +328,8 @@ public class SearchablesTest extends AndroidTestCase {
|
||||
public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
|
||||
assertNotNull(intent);
|
||||
assertTrue(intent.getAction().equals(Intent.ACTION_SEARCH)
|
||||
|| intent.getAction().equals(Intent.ACTION_WEB_SEARCH));
|
||||
|| intent.getAction().equals(Intent.ACTION_WEB_SEARCH)
|
||||
|| intent.getAction().equals(SearchManager.INTENT_ACTION_GLOBAL_SEARCH));
|
||||
switch (mSearchablesMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
return mRealPackageManager.queryIntentActivities(intent, flags);
|
||||
@@ -472,6 +430,20 @@ public class SearchablesTest extends AndroidTestCase {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkPermission(String permName, String pkgName) {
|
||||
assertNotNull(permName);
|
||||
assertNotNull(pkgName);
|
||||
switch (mSearchablesMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
return mRealPackageManager.checkPermission(permName, pkgName);
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
return PackageManager.PERMISSION_DENIED;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user