Purify SettingsActivity from old search code.

Bug:35763944, 32590887
Test: make RunSettingsRoboTests
Change-Id: Id8140b68a676e595bff095546fa119cd3ced2c4a
This commit is contained in:
Matthew Fritze
2017-03-16 13:19:20 -07:00
parent 8973e2786d
commit 0b431fc003
11 changed files with 8 additions and 1048 deletions

View File

@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/search_panel"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical">
<LinearLayout android:id="@+id/layout_suggestions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<!-- Padding is included in the background -->
<ListView android:id="@+id/list_suggestions"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="@dimen/dashboard_padding_start"
android:paddingEnd="@dimen/dashboard_padding_end"
android:paddingTop="@dimen/dashboard_padding_top"
android:paddingBottom="@dimen/dashboard_padding_bottom"
android:scrollbarStyle="outsideOverlay"
android:headerDividersEnabled="false"
android:background="@drawable/search_panel_list_background"
android:elevation="@dimen/search_panel_elevation"
/>
</LinearLayout>
<LinearLayout android:id="@+id/layout_results"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical"
android:layout_weight="1">
<!-- Padding is included in the background -->
<ListView android:id="@+id/list_results"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="@dimen/dashboard_padding_start"
android:paddingEnd="@dimen/dashboard_padding_end"
android:paddingTop="@dimen/dashboard_padding_top"
android:paddingBottom="@dimen/dashboard_padding_bottom"
android:scrollbarStyle="outsideOverlay"
android:headerDividersEnabled="false"
android:background="@drawable/search_panel_list_background"
android:elevation="@dimen/search_panel_elevation"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/dashboard_category_height"
android:paddingStart="@dimen/search_title_padding_start"
android:singleLine="true"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:textAppearance="@style/TextAppearance.ResultTitle"
android:textAlignment="viewStart"
android:text="@string/search_results_label"
/>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/dashboard_category_height"
android:paddingStart="@dimen/search_title_padding_start"
android:singleLine="true"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:textAppearance="@style/TextAppearance.RecentsTitle"
android:textAlignment="viewStart"
android:text="@string/search_recents_queries_label"
/>

View File

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingEnd="?android:attr/scrollbarSize">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:minWidth="@*android:dimen/preference_icon_minWidth"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon"
android:layout_width="@dimen/search_result_item_image_size"
android:layout_height="@dimen/search_result_item_image_size"
android:scaleType="centerInside"
android:layout_marginStart="@dimen/search_result_item_image_margin_start"
android:layout_marginEnd="@dimen/search_result_item_image_margin_end"
/>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
</RelativeLayout>
</LinearLayout>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/search"
android:title="@string/search_menu"
android:icon="@*android:drawable/ic_search_api_material"
android:showAsAction="collapseActionView|ifRoom"
android:actionViewClass="android.widget.SearchView" />
</menu>

View File

@@ -6060,11 +6060,6 @@
<xliff:g name="first_item">%1$s</xliff:g> > <xliff:g name="second_item">%2$s</xliff:g> <xliff:g name="first_item">%1$s</xliff:g> > <xliff:g name="second_item">%2$s</xliff:g>
</string> </string>
<!-- Text used to identify the search query suggestions / recent searches -->
<string name="search_recents_queries_label">Recent searches</string>
<!-- Text used to identify the search results -->
<string name="search_results_label">Results</string>
<!--Search Keywords [CHAR LIMIT=NONE]--> <!--Search Keywords [CHAR LIMIT=NONE]-->
<string name="keywords_wifi">wifi, wi-fi, network connection</string> <string name="keywords_wifi">wifi, wi-fi, network connection</string>
<string name="keywords_more_default_sms_app">text message, texting, messages, messaging</string> <string name="keywords_more_default_sms_app">text message, texting, messages, messaging</string>

View File

@@ -47,13 +47,10 @@ import android.text.TextUtils;
import android.transition.TransitionManager; import android.transition.TransitionManager;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.SearchView;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import com.android.settings.Settings.WifiSettingsActivity; import com.android.settings.Settings.WifiSettingsActivity;
@@ -63,7 +60,6 @@ import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.core.instrumentation.SharedPreferencesLogger; import com.android.settings.core.instrumentation.SharedPreferencesLogger;
import com.android.settings.dashboard.DashboardFeatureProvider; import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.DashboardSummary; import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.dashboard.SearchResultsSummary;
import com.android.settings.enterprise.EnterprisePrivacySettings; import com.android.settings.enterprise.EnterprisePrivacySettings;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.DynamicIndexableContentMonitor; import com.android.settings.search.DynamicIndexableContentMonitor;
@@ -81,9 +77,7 @@ import java.util.Set;
public class SettingsActivity extends SettingsDrawerActivity public class SettingsActivity extends SettingsDrawerActivity
implements PreferenceManager.OnPreferenceTreeClickListener, implements PreferenceManager.OnPreferenceTreeClickListener,
PreferenceFragment.OnPreferenceStartFragmentCallback, PreferenceFragment.OnPreferenceStartFragmentCallback,
ButtonBarHandler, FragmentManager.OnBackStackChangedListener, ButtonBarHandler, FragmentManager.OnBackStackChangedListener {
SearchView.OnQueryTextListener, SearchView.OnCloseListener,
MenuItem.OnActionExpandListener {
private static final String LOG_TAG = "Settings"; private static final String LOG_TAG = "Settings";
@@ -91,8 +85,6 @@ public class SettingsActivity extends SettingsDrawerActivity
// Constants for state save/restore // Constants for state save/restore
private static final String SAVE_KEY_CATEGORIES = ":settings:categories"; private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
private static final String SAVE_KEY_SEARCH_MENU_EXPANDED = ":settings:search_menu_expanded";
private static final String SAVE_KEY_SEARCH_QUERY = ":settings:search_query";
private static final String SAVE_KEY_SHOW_HOME_AS_UP = ":settings:show_home_as_up"; private static final String SAVE_KEY_SHOW_HOME_AS_UP = ":settings:show_home_as_up";
private static final String SAVE_KEY_SHOW_SEARCH = ":settings:show_search"; private static final String SAVE_KEY_SHOW_SEARCH = ":settings:show_search";
@@ -166,8 +158,6 @@ public class SettingsActivity extends SettingsDrawerActivity
private static final String EXTRA_UI_OPTIONS = "settings:ui_options"; private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
private static final String EMPTY_QUERY = "";
private static final int REQUEST_SUGGESTION = 42; private static final int REQUEST_SUGGESTION = 42;
private String mFragmentClass; private String mFragmentClass;
@@ -226,25 +216,15 @@ public class SettingsActivity extends SettingsDrawerActivity
private ViewGroup mContent; private ViewGroup mContent;
private SearchView mSearchView;
private MenuItem mSearchMenuItem;
private boolean mSearchMenuItemExpanded = false;
private SearchResultsSummary mSearchResultsFragment;
private SearchFeatureProvider mSearchFeatureProvider; private SearchFeatureProvider mSearchFeatureProvider;
private MetricsFeatureProvider mMetricsFeatureProvider; private MetricsFeatureProvider mMetricsFeatureProvider;
// Categories // Categories
private ArrayList<DashboardCategory> mCategories = new ArrayList<>(); private ArrayList<DashboardCategory> mCategories = new ArrayList<>();
private boolean mNeedToRevertToInitialFragment = false;
private DashboardFeatureProvider mDashboardFeatureProvider; private DashboardFeatureProvider mDashboardFeatureProvider;
private Intent mResultIntentData;
private ComponentName mCurrentSuggestion; private ComponentName mCurrentSuggestion;
@VisibleForTesting
String mSearchQuery;
public SwitchBar getSwitchBar() { public SwitchBar getSwitchBar() {
return mSwitchBar; return mSwitchBar;
} }
@@ -269,54 +249,15 @@ public class SettingsActivity extends SettingsDrawerActivity
} }
} }
@Override
protected void onStart() {
super.onStart();
if (mNeedToRevertToInitialFragment) {
revertToInitialFragment();
}
}
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
if (!mDisplaySearch) { if (!mDisplaySearch) {
return false; return false;
} }
MenuInflater inflater = getMenuInflater();
if (mSearchFeatureProvider.isEnabled(this)) {
mSearchFeatureProvider.setUpSearchMenu(menu, this); mSearchFeatureProvider.setUpSearchMenu(menu, this);
return true; return true;
} }
inflater.inflate(R.menu.options_menu, menu);
// Cache the search query (can be overridden by the OnQueryTextListener)
final String query = mSearchQuery;
mSearchMenuItem = menu.findItem(R.id.search);
mSearchView = (SearchView) mSearchMenuItem.getActionView();
if (mSearchMenuItem == null || mSearchView == null) {
return false;
}
if (mSearchResultsFragment != null) {
mSearchResultsFragment.setSearchView(mSearchView);
}
mSearchMenuItem.setOnActionExpandListener(this);
mSearchView.setMaxWidth(Integer.MAX_VALUE);
mSearchView.setOnQueryTextListener(this);
mSearchView.setOnCloseListener(this);
if (mSearchMenuItemExpanded) {
mSearchMenuItem.expandActionView();
}
mSearchView.setQuery(query, true /* submit */);
return true;
}
@Override @Override
public SharedPreferences getSharedPreferences(String name, int mode) { public SharedPreferences getSharedPreferences(String name, int mode) {
@@ -417,8 +358,6 @@ public class SettingsActivity extends SettingsDrawerActivity
if (savedState != null) { if (savedState != null) {
// We are restarting from a previous saved state; used that to initialize, instead // We are restarting from a previous saved state; used that to initialize, instead
// of starting fresh. // of starting fresh.
mSearchMenuItemExpanded = savedState.getBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED);
mSearchQuery = savedState.getString(SAVE_KEY_SEARCH_QUERY);
setTitleFromIntent(intent); setTitleFromIntent(intent);
ArrayList<DashboardCategory> categories = ArrayList<DashboardCategory> categories =
@@ -430,7 +369,6 @@ public class SettingsActivity extends SettingsDrawerActivity
} }
mDisplayHomeAsUpEnabled = savedState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP); mDisplayHomeAsUpEnabled = savedState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);
} else { } else {
launchSettingFragment(initialFragmentName, isSubSettings, intent); launchSettingFragment(initialFragmentName, isSubSettings, intent);
@@ -456,21 +394,21 @@ public class SettingsActivity extends SettingsDrawerActivity
Button backButton = (Button)findViewById(R.id.back_button); Button backButton = (Button)findViewById(R.id.back_button);
backButton.setOnClickListener(new OnClickListener() { backButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
setResult(RESULT_CANCELED, getResultIntentData()); setResult(RESULT_CANCELED, null);
finish(); finish();
} }
}); });
Button skipButton = (Button)findViewById(R.id.skip_button); Button skipButton = (Button)findViewById(R.id.skip_button);
skipButton.setOnClickListener(new OnClickListener() { skipButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
setResult(RESULT_OK, getResultIntentData()); setResult(RESULT_OK, null);
finish(); finish();
} }
}); });
mNextButton = (Button)findViewById(R.id.next_button); mNextButton = (Button)findViewById(R.id.next_button);
mNextButton.setOnClickListener(new OnClickListener() { mNextButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
setResult(RESULT_OK, getResultIntentData()); setResult(RESULT_OK, null);
finish(); finish();
} }
}); });
@@ -614,20 +552,6 @@ public class SettingsActivity extends SettingsDrawerActivity
} }
outState.putBoolean(SAVE_KEY_SHOW_HOME_AS_UP, mDisplayHomeAsUpEnabled); outState.putBoolean(SAVE_KEY_SHOW_HOME_AS_UP, mDisplayHomeAsUpEnabled);
outState.putBoolean(SAVE_KEY_SHOW_SEARCH, mDisplaySearch);
if (mDisplaySearch) {
// The option menus are created if the ActionBar is visible and they are also created
// asynchronously. If you launch Settings with an Intent action like
// android.intent.action.POWER_USAGE_SUMMARY and at the same time your device is locked
// thru a LockScreen, onCreateOptionsMenu() is not yet called and references to the search
// menu item and search view are null.
boolean isExpanded = (mSearchMenuItem != null) && mSearchMenuItem.isActionViewExpanded();
outState.putBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED, isExpanded);
String query = (mSearchView != null) ? mSearchView.getQuery().toString() : EMPTY_QUERY;
outState.putString(SAVE_KEY_SEARCH_QUERY, query);
}
} }
@Override @Override
@@ -653,9 +577,6 @@ public class SettingsActivity extends SettingsDrawerActivity
} }
mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR); mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
if(mDisplaySearch && !TextUtils.isEmpty(mSearchQuery)) {
onQueryTextSubmit(mSearchQuery);
}
updateTilesList(); updateTilesList();
} }
@@ -1011,96 +932,6 @@ public class SettingsActivity extends SettingsDrawerActivity
return super.shouldUpRecreateTask(new Intent(this, SettingsActivity.class)); return super.shouldUpRecreateTask(new Intent(this, SettingsActivity.class));
} }
@Deprecated
@Override
public boolean onQueryTextSubmit(String query) {
if (mSearchFeatureProvider.isEnabled(this)) {
return false;
}
mSearchQuery = query;
switchToSearchResultsFragmentIfNeeded();
return mSearchResultsFragment.onQueryTextSubmit(query);
}
@Deprecated
@Override
public boolean onQueryTextChange(String newText) {
mSearchQuery = newText;
if (mSearchFeatureProvider.isEnabled(this) || mSearchResultsFragment == null) {
return false;
}
return mSearchResultsFragment.onQueryTextChange(newText);
}
@Override
public boolean onClose() {
return false;
}
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
if (item.getItemId() == mSearchMenuItem.getItemId()) {
switchToSearchResultsFragmentIfNeeded();
}
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
if (item.getItemId() == mSearchMenuItem.getItemId()) {
if (mSearchMenuItemExpanded) {
revertToInitialFragment();
}
}
return true;
}
@Override
public void onProfileTileOpen() {
if (!mIsShowingDashboard) {
finish();
}
}
@Deprecated
private void switchToSearchResultsFragmentIfNeeded() {
if (mSearchResultsFragment != null) {
return;
}
Fragment current = getFragmentManager().findFragmentById(R.id.main_content);
if (current != null && current instanceof SearchResultsSummary) {
mSearchResultsFragment = (SearchResultsSummary) current;
} else {
setContentHeaderView(null);
mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
SearchResultsSummary.class.getName(), null, false, true,
R.string.search_results_title, null, true);
}
mSearchResultsFragment.setSearchView(mSearchView);
mSearchMenuItemExpanded = true;
}
@Deprecated
public void needToRevertToInitialFragment() {
mNeedToRevertToInitialFragment = true;
}
@Deprecated
private void revertToInitialFragment() {
mNeedToRevertToInitialFragment = false;
mSearchResultsFragment = null;
mSearchMenuItemExpanded = false;
getFragmentManager().popBackStackImmediate(SettingsActivity.BACK_STACK_PREFS,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
if (mSearchMenuItem != null) {
mSearchMenuItem.collapseActionView();
}
}
public Intent getResultIntentData() {
return mResultIntentData;
}
public void startSuggestion(Intent intent) { public void startSuggestion(Intent intent) {
if (intent == null || ActivityManager.isUserAMonkey()) { if (intent == null || ActivityManager.isUserAMonkey()) {
return; return;

View File

@@ -1,642 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.dashboard;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.search.Index;
import java.util.HashMap;
public class SearchResultsSummary extends InstrumentedPreferenceFragment {
private static final String LOG_TAG = "SearchResultsSummary";
private static final String EMPTY_QUERY = "";
private static char ELLIPSIS = '\u2026';
private static final String SAVE_KEY_SHOW_RESULTS = ":settings:show_results";
private SearchView mSearchView;
private ListView mResultsListView;
private SearchResultsAdapter mResultsAdapter;
private UpdateSearchResultsTask mUpdateSearchResultsTask;
private ListView mSuggestionsListView;
private SuggestionsAdapter mSuggestionsAdapter;
private UpdateSuggestionsTask mUpdateSuggestionsTask;
private ViewGroup mLayoutSuggestions;
private ViewGroup mLayoutResults;
private String mQuery;
private boolean mShowResults;
/**
* A basic AsyncTask for updating the query results cursor
*/
private class UpdateSearchResultsTask extends AsyncTask<String, Void, Cursor> {
@Override
protected Cursor doInBackground(String... params) {
return Index.getInstance(getActivity()).search(params[0]);
}
@Override
protected void onPostExecute(Cursor cursor) {
if (!isCancelled()) {
mMetricsFeatureProvider.action(getContext(),
MetricsEvent.ACTION_SEARCH_RESULTS, cursor.getCount());
setResultsCursor(cursor);
setResultsVisibility(cursor.getCount() > 0);
} else if (cursor != null) {
cursor.close();
}
}
}
/**
* A basic AsyncTask for updating the suggestions cursor
*/
private class UpdateSuggestionsTask extends AsyncTask<String, Void, Cursor> {
@Override
protected Cursor doInBackground(String... params) {
return Index.getInstance(getActivity()).getSuggestions(params[0]);
}
@Override
protected void onPostExecute(Cursor cursor) {
if (!isCancelled()) {
setSuggestionsCursor(cursor);
setSuggestionsVisibility(cursor.getCount() > 0);
} else if (cursor != null) {
cursor.close();
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mResultsAdapter = new SearchResultsAdapter(getActivity());
mSuggestionsAdapter = new SuggestionsAdapter(getActivity());
if (savedInstanceState != null) {
mShowResults = savedInstanceState.getBoolean(SAVE_KEY_SHOW_RESULTS);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVE_KEY_SHOW_RESULTS, mShowResults);
}
@Override
public void onStop() {
super.onStop();
clearSuggestions();
clearResults();
}
@Override
public void onDestroy() {
mResultsListView = null;
mResultsAdapter = null;
mUpdateSearchResultsTask = null;
mSuggestionsListView = null;
mSuggestionsAdapter = null;
mUpdateSuggestionsTask = null;
mSearchView = null;
super.onDestroy();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.search_panel, container, false);
mLayoutSuggestions = (ViewGroup) view.findViewById(R.id.layout_suggestions);
mLayoutResults = (ViewGroup) view.findViewById(R.id.layout_results);
mResultsListView = (ListView) view.findViewById(R.id.list_results);
mResultsListView.setAdapter(mResultsAdapter);
mResultsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// We have a header, so we need to decrement the position by one
position--;
// Some Monkeys could create a case where they were probably clicking on the
// List Header and thus the position passed was "0" and then by decrement was "-1"
if (position < 0) {
return;
}
final Cursor cursor = mResultsAdapter.mCursor;
cursor.moveToPosition(position);
final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME);
final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE);
final String action = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION);
final String key = cursor.getString(Index.COLUMN_INDEX_KEY);
final SettingsActivity sa = (SettingsActivity) getActivity();
sa.needToRevertToInitialFragment();
if (TextUtils.isEmpty(action)) {
Bundle args = new Bundle();
args.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key);
Utils.startWithFragment(sa, className, args, null, 0, -1, screenTitle,
getMetricsCategory());
} else {
final Intent intent = new Intent(action);
final String targetPackage = cursor.getString(
Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
final String targetClass = cursor.getString(
Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS);
if (!TextUtils.isEmpty(targetPackage) && !TextUtils.isEmpty(targetClass)) {
final ComponentName component =
new ComponentName(targetPackage, targetClass);
intent.setComponent(component);
}
intent.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key);
sa.startActivity(intent);
}
saveQueryToDatabase();
}
});
mResultsListView.addHeaderView(
LayoutInflater.from(getActivity()).inflate(
R.layout.search_panel_results_header, mResultsListView, false),
null, false);
mSuggestionsListView = (ListView) view.findViewById(R.id.list_suggestions);
mSuggestionsListView.setAdapter(mSuggestionsAdapter);
mSuggestionsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// We have a header, so we need to decrement the position by one
position--;
// Some Monkeys could create a case where they were probably clicking on the
// List Header and thus the position passed was "0" and then by decrement was "-1"
if (position < 0) {
return;
}
final Cursor cursor = mSuggestionsAdapter.mCursor;
cursor.moveToPosition(position);
mShowResults = true;
mQuery = cursor.getString(0);
mSearchView.setQuery(mQuery, false);
}
});
mSuggestionsListView.addHeaderView(
LayoutInflater.from(getActivity()).inflate(
R.layout.search_panel_suggestions_header, mSuggestionsListView, false),
null, false);
return view;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.DASHBOARD_SEARCH_RESULTS;
}
@Override
public void onResume() {
super.onResume();
if (!mShowResults) {
showSomeSuggestions();
}
}
public void setSearchView(SearchView searchView) {
mSearchView = searchView;
}
private void setSuggestionsVisibility(boolean visible) {
if (mLayoutSuggestions != null) {
mLayoutSuggestions.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
private void setResultsVisibility(boolean visible) {
if (mLayoutResults != null) {
mLayoutResults.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
private void saveQueryToDatabase() {
Index.getInstance(getActivity()).addSavedQuery(mQuery);
}
public boolean onQueryTextSubmit(String query) {
mQuery = getFilteredQueryString(query);
mShowResults = true;
setSuggestionsVisibility(false);
updateSearchResults();
saveQueryToDatabase();
return false;
}
public boolean onQueryTextChange(String query) {
final String newQuery = getFilteredQueryString(query);
mQuery = newQuery;
if (TextUtils.isEmpty(mQuery)) {
mShowResults = false;
setResultsVisibility(false);
updateSuggestions();
} else {
mShowResults = true;
setSuggestionsVisibility(false);
updateSearchResults();
}
return true;
}
public void showSomeSuggestions() {
setResultsVisibility(false);
mQuery = EMPTY_QUERY;
updateSuggestions();
}
private void clearSuggestions() {
if (mUpdateSuggestionsTask != null) {
mUpdateSuggestionsTask.cancel(false);
mUpdateSuggestionsTask = null;
}
setSuggestionsCursor(null);
setSuggestionsVisibility(false);
}
private void setSuggestionsCursor(Cursor cursor) {
if (mSuggestionsAdapter == null) {
return;
}
Cursor oldCursor = mSuggestionsAdapter.swapCursor(cursor);
if (oldCursor != null) {
oldCursor.close();
}
}
private void clearResults() {
if (mUpdateSearchResultsTask != null) {
mUpdateSearchResultsTask.cancel(false);
mUpdateSearchResultsTask = null;
}
setResultsCursor(null);
setResultsVisibility(false);
}
private void setResultsCursor(Cursor cursor) {
if (mResultsAdapter == null) {
return;
}
Cursor oldCursor = mResultsAdapter.swapCursor(cursor);
if (oldCursor != null) {
oldCursor.close();
}
}
private String getFilteredQueryString(CharSequence query) {
if (query == null) {
return null;
}
final StringBuilder filtered = new StringBuilder();
for (int n = 0; n < query.length(); n++) {
char c = query.charAt(n);
if (!Character.isLetterOrDigit(c) && !Character.isSpaceChar(c)) {
continue;
}
filtered.append(c);
}
return filtered.toString();
}
private void clearAllTasks() {
if (mUpdateSearchResultsTask != null) {
mUpdateSearchResultsTask.cancel(false);
mUpdateSearchResultsTask = null;
}
if (mUpdateSuggestionsTask != null) {
mUpdateSuggestionsTask.cancel(false);
mUpdateSuggestionsTask = null;
}
}
private void updateSuggestions() {
clearAllTasks();
if (mQuery == null) {
setSuggestionsCursor(null);
} else {
mUpdateSuggestionsTask = new UpdateSuggestionsTask();
mUpdateSuggestionsTask.execute(mQuery);
}
}
private void updateSearchResults() {
clearAllTasks();
if (TextUtils.isEmpty(mQuery)) {
setResultsVisibility(false);
setResultsCursor(null);
} else {
mUpdateSearchResultsTask = new UpdateSearchResultsTask();
mUpdateSearchResultsTask.execute(mQuery);
}
}
private static class SuggestionItem {
public String query;
public SuggestionItem(String query) {
this.query = query;
}
}
private static class SuggestionsAdapter extends BaseAdapter {
private static final int COLUMN_SUGGESTION_QUERY = 0;
private static final int COLUMN_SUGGESTION_TIMESTAMP = 1;
private Context mContext;
private Cursor mCursor;
private LayoutInflater mInflater;
private boolean mDataValid = false;
public SuggestionsAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDataValid = false;
}
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
Cursor oldCursor = mCursor;
mCursor = newCursor;
if (newCursor != null) {
mDataValid = true;
notifyDataSetChanged();
} else {
mDataValid = false;
notifyDataSetInvalidated();
}
return oldCursor;
}
@Override
public int getCount() {
if (!mDataValid || mCursor == null || mCursor.isClosed()) return 0;
return mCursor.getCount();
}
@Override
public Object getItem(int position) {
if (mDataValid && mCursor.moveToPosition(position)) {
final String query = mCursor.getString(COLUMN_SUGGESTION_QUERY);
return new SuggestionItem(query);
}
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (!mDataValid && convertView == null) {
throw new IllegalStateException(
"this should only be called when the cursor is valid");
}
if (!mCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
View view;
if (convertView == null) {
view = mInflater.inflate(R.layout.search_suggestion_item, parent, false);
} else {
view = convertView;
}
TextView query = (TextView) view.findViewById(R.id.title);
SuggestionItem item = (SuggestionItem) getItem(position);
query.setText(item.query);
return view;
}
}
private static class SearchResult {
public Context context;
public String title;
public String summaryOn;
public String summaryOff;
public String entries;
public int iconResId;
public String key;
public SearchResult(Context context, String title, String summaryOn, String summaryOff,
String entries, int iconResId, String key) {
this.context = context;
this.title = title;
this.summaryOn = summaryOn;
this.summaryOff = summaryOff;
this.entries = entries;
this.iconResId = iconResId;
this.key = key;
}
}
private static class SearchResultsAdapter extends BaseAdapter {
private Context mContext;
private Cursor mCursor;
private LayoutInflater mInflater;
private boolean mDataValid;
private HashMap<String, Context> mContextMap = new HashMap<String, Context>();
private static final String PERCENT_RECLACE = "%s";
private static final String DOLLAR_REPLACE = "$s";
public SearchResultsAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDataValid = false;
}
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
Cursor oldCursor = mCursor;
mCursor = newCursor;
if (newCursor != null) {
mDataValid = true;
notifyDataSetChanged();
} else {
mDataValid = false;
notifyDataSetInvalidated();
}
return oldCursor;
}
@Override
public int getCount() {
if (!mDataValid || mCursor == null || mCursor.isClosed()) return 0;
return mCursor.getCount();
}
@Override
public Object getItem(int position) {
if (mDataValid && mCursor.moveToPosition(position)) {
final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE);
final String summaryOn = mCursor.getString(Index.COLUMN_INDEX_SUMMARY_ON);
final String summaryOff = mCursor.getString(Index.COLUMN_INDEX_SUMMARY_OFF);
final String entries = mCursor.getString(Index.COLUMN_INDEX_ENTRIES);
final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON);
final String className = mCursor.getString(
Index.COLUMN_INDEX_CLASS_NAME);
final String packageName = mCursor.getString(
Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
final String key = mCursor.getString(
Index.COLUMN_INDEX_KEY);
Context packageContext;
if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(packageName)) {
packageContext = mContextMap.get(packageName);
if (packageContext == null) {
try {
packageContext = mContext.createPackageContext(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, "Cannot create Context for package: " + packageName);
return null;
}
mContextMap.put(packageName, packageContext);
}
} else {
packageContext = mContext;
}
final int iconResId = TextUtils.isEmpty(iconResStr) ?
R.drawable.empty_icon : Integer.parseInt(iconResStr);
return new SearchResult(packageContext, title, summaryOn, summaryOff,
entries, iconResId, key);
}
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (!mDataValid && convertView == null) {
throw new IllegalStateException(
"this should only be called when the cursor is valid");
}
if (!mCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
View view;
TextView textTitle;
ImageView imageView;
if (convertView == null) {
view = mInflater.inflate(R.layout.search_result_item, parent, false);
} else {
view = convertView;
}
textTitle = (TextView) view.findViewById(R.id.title);
imageView = (ImageView) view.findViewById(R.id.icon);
final SearchResult result = (SearchResult) getItem(position);
textTitle.setText(result.title);
if (result.iconResId != R.drawable.empty_icon) {
final Context packageContext = result.context;
final Drawable drawable;
try {
drawable = packageContext.getDrawable(result.iconResId);
imageView.setImageDrawable(drawable);
} catch (Resources.NotFoundException nfe) {
// Not much we can do except logging
Log.e(LOG_TAG, "Cannot load Drawable for " + result.title);
}
} else {
imageView.setImageDrawable(null);
imageView.setBackgroundResource(R.drawable.empty_icon);
}
return view;
}
}
}

View File

@@ -130,7 +130,7 @@ public class RedactionInterstitial extends SettingsActivity {
if (v.getId() == R.id.redaction_done_button) { if (v.getId() == R.id.redaction_done_button) {
final RedactionInterstitial activity = (RedactionInterstitial) getActivity(); final RedactionInterstitial activity = (RedactionInterstitial) getActivity();
if (activity != null) { if (activity != null) {
activity.setResult(RESULT_OK, activity.getResultIntentData()); activity.setResult(RESULT_OK, null);
finish(); finish();
} }
} }

View File

@@ -30,7 +30,6 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
@@ -59,20 +58,6 @@ public class SettingsActivityTest {
doReturn(mBitmap).when(mActivity).getBitmapFromXmlResource(anyInt()); doReturn(mBitmap).when(mActivity).getBitmapFromXmlResource(anyInt());
} }
@Test
public void testQueryTextChange_shouldUpdate() {
final String testQuery = "abc";
assertThat(mActivity.mSearchQuery).isNull();
try {
mActivity.onQueryTextChange(testQuery);
} catch (NullPointerException e) {
// Expected, because searchFeatureProvider is not wired up.
}
assertThat(mActivity.mSearchQuery).isEqualTo(testQuery);
}
@Test @Test
public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash() public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash()
throws ClassNotFoundException { throws ClassNotFoundException {