Turn AutoCompleteTextView into a SearchView in ActionBar instead
Solution 1
To get Places Autocomplete API results in a SearchView, you'll first need a ContentProvider for the API.
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.util.Log;
public class PlacesSuggestionProvider extends ContentProvider {
private static final String LOG_TAG = "ExampleApp";
public static final String AUTHORITY = "com.example.google.places.search_suggestion_provider";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/search");
// UriMatcher constant for search suggestions
private static final int SEARCH_SUGGEST = 1;
private static final UriMatcher uriMatcher;
private static final String[] SEARCH_SUGGEST_COLUMNS = {
BaseColumns._ID,
SearchManager.SUGGEST_COLUMN_TEXT_1,
SearchManager.SUGGEST_COLUMN_TEXT_2,
SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID
};
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
uriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
}
@Override
public int delete(Uri uri, String arg1, String[] arg2) {
throw new UnsupportedOperationException();
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case SEARCH_SUGGEST:
return SearchManager.SUGGEST_MIME_TYPE;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues arg1) {
throw new UnsupportedOperationException();
}
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
Log.d(LOG_TAG, "query = " + uri);
// Use the UriMatcher to see what kind of query we have
switch (uriMatcher.match(uri)) {
case SEARCH_SUGGEST:
Log.d(LOG_TAG, "Search suggestions requested.");
MatrixCursor cursor = new MatrixCursor(SEARCH_SUGGEST_COLUMNS, 1);
cursor.addRow(new String[] {
"1", "Search Result", "Search Result Description", "content_id"
});
return cursor;
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
@Override
public int update(Uri uri, ContentValues arg1, String arg2, String[] arg3) {
throw new UnsupportedOperationException();
}
}
Then add your Places Autocomplete API client code into the query method on the content provider. You extract the user input as follows:
String query = uri.getLastPathSegment().toLowerCase();
Add the PlacesSuggestionProvider to your AndroidManifest, and make sure your activity has a searchable configuration.
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity android:name=".PlacesSearchViewActivity" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
<provider
android:name="com.example.google.places.PlacesSuggestionProvider"
android:authorities="com.example.google.places.search_suggestion_provider"
android:syncable="false" />
</application>
</manifest>
And make sure your searchable configuration (res/xml/searchable.xml) has a search suggest authority.
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint"
android:searchSuggestAuthority="com.example.google.places.search_suggestion_provider">
</searchable>
The authority should be the same in AndroidManifest.xml, searchable.xml, and your content provider.
Create a options menu for your ActionBar that includes a SearchView (/res/menu/options_menu.xml).
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_search"
android:title="@string/menu_search"
android:icon="@drawable/ic_menu_search"
android:showAsAction="collapseActionView|ifRoom"
android:actionViewClass="android.widget.SearchView" />
</menu>
Configure your Activity with a SearchView that's associated with your searchable configuration/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the options menu from XML
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
// Tells your app's SearchView to use this activity's searchable configuration
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default
return true;
}
A few key docs are:
Adding Custom Suggestions: http://developer.android.com/guide/topics/search/adding-custom-suggestions.html
Creating a Content Provider: http://developer.android.com/guide/topics/providers/content-provider-creating.html
Using a Search Widget: http://developer.android.com/guide/topics/search/search-dialog.html#UsingSearchWidget
Solution 2
AutoCompleteTextView with google search Api
your xml
<AutoCompleteTextView
android:id="@+id/main_omnibox_input"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@null"
android:hint="Search"
android:focusable="true"
android:focusableInTouchMode="true"
android:selectAllOnFocus="true"
android:singleLine="true"
android:textSize="@dimen/_14sdp" />
your java code
this.inputBox = (AutoCompleteTextView) findViewById(R.id.main_omnibox_input);
inputBox.setAdapter(new SearchAutocompleteAdapter(SearchActivity.this, new SearchAutocompleteAdapter.OnSearchCommitListener() {
@Override
public void onSearchCommit(String text) {
inputBox.setText(text);
inputBox.setSelection(text.length());
}
}));
this.inputBox.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> adapterView, View view, int i, long j) {
String charSequence = ((TextView) view.findViewById(android.R.id.text1)).getText().toString();
inputBox.setText(Html.fromHtml(BrowserUnit.urlWrapper(charSequence)), BufferType.SPANNABLE);
inputBox.setSelection(charSequence.length());
// your code
// updateAlbum(charSequence);
// hideSoftInput(SearchActivity.this.inputBox);
}
});
SearchAutocompleteAdapter
public class SearchAutocompleteAdapter extends BaseAdapter implements Filterable {
interface OnSearchCommitListener {
void onSearchCommit(String text);
}
private final Context mContext;
private final OnSearchCommitListener commitListener;
private List<String> completions = new ArrayList<>();
static final String searchCompleteUrl = "https://www.google.com/complete/search?client=firefox&q=%s";
SearchAutocompleteAdapter(Context context, OnSearchCommitListener commitListener) {
mContext = context;
this.commitListener = commitListener;
}
@Override
public int getCount() {
return completions.size();
}
@Override
public Object getItem(int position) {
return completions.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@SuppressLint("ClickableViewAccessibility")
@Override
@SuppressWarnings("ConstantConditions")
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(android.R.layout.simple_dropdown_item_1line, parent, false);
}
TextView textview = convertView.findViewById(android.R.id.text1);
textview.setText(completions.get(position));
Drawable d = ContextCompat.getDrawable(mContext, R.drawable.icon_goarrowsmall);
final int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, mContext.getResources().getDisplayMetrics());
d.setBounds(0, 0, size, size);
textview.setCompoundDrawables(null, null, d, null);
textview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
TextView t = (TextView) view;
if (event.getX() > t.getWidth() - t.getCompoundPaddingRight()) {
commitListener.onSearchCommit(getItem(position).toString());
return true;
}
return false;
}
});
parent.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (event.getX() > view.getWidth() - size * 2) {
return true;
}
return false;
}
});
return convertView;
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// Invoked on a worker thread
FilterResults filterResults = new FilterResults();
if (constraint != null) {
List<String> results = getCompletions(constraint.toString());
filterResults.values = results;
filterResults.count = results.size();
}
return filterResults;
}
@Override
@SuppressWarnings("unchecked")
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
completions = (List<String>) results.values;
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
}
private List<String> getCompletions(String text) {
int total = 0;
byte[] data = new byte[16384];
try {
URL url = new URL(URLUtil.composeSearchUrl(text, searchCompleteUrl, "%s"));
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
while (total <= data.length) {
int count = in.read(data, total, data.length - total);
if (count == -1) {
break;
}
total += count;
}
if (total == data.length) {
// overflow
return new ArrayList<>();
}
} finally {
urlConnection.disconnect();
}
} catch (IOException e) {
return new ArrayList<>();
}
JSONArray jsonArray;
try {
jsonArray = new JSONArray(new String(data, StandardCharsets.UTF_8));
} catch (JSONException e) {
return new ArrayList<>();
}
jsonArray = jsonArray.optJSONArray(1);
if (jsonArray == null) {
return new ArrayList<>();
}
final int MAX_RESULTS = 10;
List<String> result = new ArrayList<>(Math.min(jsonArray.length(), MAX_RESULTS));
for (int i = 0; i < jsonArray.length() && result.size() < MAX_RESULTS; i++) {
String s = jsonArray.optString(i);
if (s != null && !s.isEmpty()) {
result.add(s);
}
}
return result;
}
}
Related videos on Youtube
Comments
-
theAlse almost 4 years
I have a AutoCompleteTextView which gives user auto-completion search result from Google Places API. Once I was done I discovered SearchView and how it can be placed in the ActionBar. I checked out the SearchView example provided by google and added it to my application as a starting point (it lists the installed applications) but I don´t know how to proceed from here. I want to have the same functionality as AutoCompleteTextView but use the SearchView instead. Any suggestion? The whole class is provided below.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.SearchManager; import android.app.SearchableInfo; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.ImageView; import android.widget.ListView; import android.widget.SearchView; import android.widget.TextView; import android.widget.Toast; /** * * @author * */ public class PlacesListSearchActivity extends Activity implements SearchView.OnQueryTextListener{ private static final String TAG = "PlacesListActivity"; private ResultReceiver mReceiver; private OnSharedPreferenceChangeListener sharedPreferencesListener; private SharedPreferences sharedPreferences; /** Called when the activity is first created. */ public ArrayAdapter<String> adapter; public AutoCompleteTextView textView; private SearchView mSearchView; private TextView mStatusView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_ACTION_BAR); setContentView(R.layout.places_search); mStatusView = (TextView) findViewById(R.id.status_text); final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.item_list); textView = (AutoCompleteTextView)findViewById(R.id.autoCompleteTextView1); adapter.setNotifyOnChange(true); textView.setHint("type store name"); textView.setAdapter(adapter); textView.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, int count) { if (count%3 == 1) { adapter.clear(); GetPlaces task = new GetPlaces(); //now pass the argument in the textview to the task task.execute(textView.getText().toString()); } } public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } public void afterTextChanged(Editable s) { } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.searchview_in_menu, menu); MenuItem searchItem = menu.findItem(R.id.action_search); mSearchView = (SearchView) searchItem.getActionView(); setupSearchView(searchItem); return true; } private void setupSearchView(MenuItem searchItem) { if (isAlwaysExpanded()) { mSearchView.setIconifiedByDefault(false); } else { searchItem.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); } SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); if (searchManager != null) { List<SearchableInfo> searchables = searchManager.getSearchablesInGlobalSearch(); // Try to use the "applications" global search provider SearchableInfo info = searchManager.getSearchableInfo(getComponentName()); for (SearchableInfo inf : searchables) { if (inf.getSuggestAuthority() != null && inf.getSuggestAuthority().startsWith("applications")) { info = inf; } } mSearchView.setSearchableInfo(info); } mSearchView.setOnQueryTextListener(this); } public boolean onQueryTextChange(String newText) { mStatusView.setText("Query = " + newText); return false; } public boolean onQueryTextSubmit(String query) { mStatusView.setText("Query = " + query + " : submitted"); return false; } public boolean onClose() { mStatusView.setText("Closed!"); return false; } protected boolean isAlwaysExpanded() { return false; } class GetPlaces extends AsyncTask<String, Void, ArrayList<String>> { @Override // three dots is java for an array of strings protected ArrayList<String> doInBackground(String... args) { Log.d("PlacesListActivity", "doInBackground"); ArrayList<String> predictionsArr = new ArrayList<String>(); try { URL googlePlaces = new URL( "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=" + URLEncoder.encode(args[0], "UTF-8") + // "&types=geocode&language=en&sensor=true&key=" + SEARCHES FOR GEO CODES "&types=establishment&language=en&sensor=true&key=" + getResources().getString(R.string.googleAPIKey)); Log.d("PlacesListActivity", googlePlaces.toString()); URLConnection tc = googlePlaces.openConnection(); BufferedReader in = new BufferedReader(new InputStreamReader( tc.getInputStream())); String line; StringBuffer sb = new StringBuffer(); //take Google's legible JSON and turn it into one big string. while ((line = in.readLine()) != null) { sb.append(line); } //turn that string into a JSON object JSONObject predictions = new JSONObject(sb.toString()); //now get the JSON array that's inside that object JSONArray ja = new JSONArray(predictions.getString("predictions")); for (int i = 0; i < ja.length(); i++) { JSONObject jo = (JSONObject) ja.get(i); //add each entry to our array predictionsArr.add(jo.getString("description")); } } catch (IOException e) { Log.e("PlacesListActivity", "GetPlaces : doInBackground", e); } catch (JSONException e) { Log.e("PlacesListActivity", "GetPlaces : doInBackground", e); } return predictionsArr; } @Override protected void onPostExecute(ArrayList<String> result){ Log.d("PlacesListActivity", "onPostExecute : " + result.size()); //update the adapter adapter = new ArrayAdapter<String>(getBaseContext(), R.layout.item_list); adapter.setNotifyOnChange(true); //attach the adapter to textview textView.setAdapter(adapter); for (String string : result) { Log.d("PlacesListActivity", "onPostExecute : result = " + string); adapter.add(string); adapter.notifyDataSetChanged(); } Log.d("PlacesListActivity", "onPostExecute : autoCompleteAdapter" + adapter.getCount()); } } }
After updating the code suggested by saxman, I can see that the query method in the provider is never called:
My manifest file looks like this:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.rathinavelu.rea" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".PlacesListActivity" > </activity> <activity android:name=".PlacesListSearchActivity" > <action android:name="android.intent.action.SEARCH" /> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> </activity> <activity android:name=".TestMapActivity" > </activity> <activity android:name=".SettingsPreferencesActivity" > </activity> <activity android:name="com.rathinavelu.util.ConnectionChecker" > </activity> <uses-library android:name="com.google.android.maps" /> <service android:name=".places.PlacesRESTService" android:enabled="true" android:exported="false" > <intent-filter> <action android:name="android.intent.action.ACTION_SYNC" /> </intent-filter> </service> <provider android:name=".places.PlacesSuggestionProvider" android:authorities="com.rathinavelu.rea.places.search_suggestion_provider" android:syncable="false" /> </application> </manifest>
I use the same authority in the manifest, content provider and manifest file. I see the searchView in the menu and I have not modified the query method so It should just return the one line cursor. but the query method is never called. please help. Another issue I just spotted is that the searchView does not show the specified search_hint!
Providing more code *PlacesListSearchActivity.java*
public class PlacesListSearchActivity extends Activity { private static final String TAG = "PlacesListSearchActivity"; private ResultReceiver mReceiver; private OnSharedPreferenceChangeListener sharedPreferencesListener; private SharedPreferences sharedPreferences; /** Called when the activity is first created. */ public ArrayAdapter<String> adapter; public AutoCompleteTextView textView; private SearchView mSearchView; private TextView mStatusView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_ACTION_BAR); setContentView(R.layout.places_search); mStatusView = (TextView) findViewById(R.id.status_text); final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.item_list); textView = (AutoCompleteTextView)findViewById(R.id.autoCompleteTextView1); adapter.setNotifyOnChange(true); textView.setHint("type store name"); textView.setAdapter(adapter); textView.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, int count) { if (count%3 == 1) { adapter.clear(); GetPlaces task = new GetPlaces(); //now pass the argument in the textview to the task task.execute(textView.getText().toString()); } } public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } public void afterTextChanged(Editable s) { } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // super.onCreateOptionsMenu(menu); // Inflate the options menu from XML MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.places_list_search_options_menu, menu); SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView(); // Tells your app's SearchView to use this activity's searchable configuration searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default // setupSearchView(searchItem); return true; }
places_search.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#dddddd"> <AutoCompleteTextView android:id="@+id/autoCompleteTextView1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" > <requestFocus></requestFocus> </AutoCompleteTextView> <TextView android:id="@+id/status_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal"/> </RelativeLayout>
places_list_search_options_menu.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/menu_search" android:title="@string/menu_search" android:icon="@android:drawable/ic_menu_search" android:showAsAction="collapseActionView|ifRoom" android:actionViewClass="android.widget.SearchView" /> </menu>
searchable.xml
<?xml version="1.0" encoding="utf-8"?> <searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/app_name" android:hint="@string/search_hint" android:searchSuggestAuthority="com.rathinavelu.rea.places.search_suggestion_provider"> </searchable>
PlacesSuggestionProvider.java
public class PlacesSuggestionProvider extends ContentProvider { private static final String LOG_TAG = "PlacesSuggestionProvider"; public static final String AUTHORITY = "com.rathinavelu.rea.places.search_suggestion_provider"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/search"); // UriMatcher constant for search suggestions private static final int SEARCH_SUGGEST = 1; private static final UriMatcher uriMatcher; private static final String[] SEARCH_SUGGEST_COLUMNS = { BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1, SearchManager.SUGGEST_COLUMN_TEXT_2, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID }; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST); uriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST); } @Override public int delete(Uri uri, String arg1, String[] arg2) { throw new UnsupportedOperationException(); } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case SEARCH_SUGGEST: return SearchManager.SUGGEST_MIME_TYPE; default: throw new IllegalArgumentException("Unknown URL " + uri); } } @Override public Uri insert(Uri uri, ContentValues arg1) { throw new UnsupportedOperationException(); } @Override public boolean onCreate() { return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Log.d(LOG_TAG, "query = " + uri); // Use the UriMatcher to see what kind of query we have switch (uriMatcher.match(uri)) { case SEARCH_SUGGEST: Log.d(LOG_TAG, "Search suggestions requested."); MatrixCursor cursor = new MatrixCursor(SEARCH_SUGGEST_COLUMNS, 1); cursor.addRow(new String[] { "1", "Search Result", "Search Result Description", "content_id" }); return cursor; default: throw new IllegalArgumentException("Unknown Uri: " + uri); } } @Override public int update(Uri uri, ContentValues arg1, String arg2, String[] arg3) { throw new UnsupportedOperationException(); } }
-
Lumii about 11 yearsHi, just wondering, is there any advantage for using SearchView over AutoCompleteTextView for search functionality in action bar?
-
Fatima over 8 yearsTerrific link for future vsitors; drzon.net/…
-
-
theAlse almost 12 yearsthanks for the reply. So the content provider will do the looking up at Google Places and return a cursor! But I still don´t know how the searchView is connected to it?
-
saxman almost 12 yearsAdded that code as well (last 2 code blocks). In onCreateOptionsMenu, you configure the SearchView to use the searchable configuration you defined for your activity.
-
saxman almost 12 yearsIt sounds like you might be missing the last part: associating your searchable config with the SearchView. Please post your other files as well (searchable.xml, PlacesListSearchActivity, PlaceSuggestionProvider, and whatever you're using for the options menu).
-
theAlse almost 12 yearsI have added pretty much all the classes. searchable.xml & PlacesSuggestionProvider.java is pretty much your original code.
-
saxman almost 12 yearsYou need an <intent-filter> around the <action android:name="android.intent.action.SEARCH" /> in your manifest.
-
theAlse almost 12 yearsI will try this as soon as I get home ;) I can not believe I missed that and also I don´t understand why it did not complain!
-
theAlse almost 12 yearsA follow up question, how do I use the previously used onPostExecute into the query-method of the content provider?
-
saxman almost 12 yearsNot sure I follow... But you don't need to use an AsyncTask in your ContentProvider query method; calls to query(...) are off the UI thread. For my implementation, I have a PlacesService class that has "autocomplete", "getDetails", and "search" methods. I call autocomplete from the search suggest ContentProvider, but can also call it from other widgets, such as the AutoCompleteTextView.
-
Elyes Jlassi over 9 yearsIs it possible to add two search widget in the same action bar of an activity ?
-
Aman Jham almost 9 yearsHow to find
searchView
onItemClickListner? -
kellogs over 8 yearsThanks for the solution! A few comments: query method does run on the UI thread on API 19 at least. I am getting
android.os.NetworkOnMainThreadException
if ran just like that. Another issue I have spent 2 hours on: Replace the linepublic static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/search");
withpublic static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + SearchManager.SUGGEST_URI_PATH_QUERY);
and all should be well -
kellogs over 8 yearsIf going the way described above then the search query will not be available in
String query = uri.getLastPathSegment().toLowerCase();
but instea you may take it irectly from the query method arguments