Android support library - SearchView in Toolbar does not call onSearchRequested - android

During changes from Holo to Material using Google support library I found an issue that it seems like onSearchRequested callback of Activity is not called. Both Activities - the one that starts search (ProjectDetail) and the one that is search target (ResultList) - are extending android.support.v7.app.ActionBarActivity.
Search works but it never reaches onSearchRequested callback therefore I cannot set additional parameters to search bundle.
There are many similar questions but none of the solutions worked for me so far, therefore I am asking here. I am fighting this for a couple of hours and maybe I am missing something terribly obvious as desperation is obscuring my vision :) Pretty please, help!
Snippet form Manifest:
<application>
<meta-data
android:name="android.app.default_searchable"
android:value=".ResultList" />
<activity android:name="my.package.ProjectDetail">
<meta-data
android:name="android.app.default_searchable"
android:value=".ResultList"/>
</activity>
<activity android:name="my.package.ResultList" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.gms.actions.SEARCH_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="android.app.searchable" android:resource="#xml/searchable" />
</activity>
</application>
This is in onCreateOptionsMenu in Activity that starts the search:
getMenuInflater().inflate(R.menu.search, menu);
MenuItem searchItem = menu.findItem(R.id.menu_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
searchView.setSearchableInfo(info);
searchView.setIconifiedByDefault(true);
searchView.setQueryRefinementEnabled(true);
searchView.setQueryHint(getString(R.string.search_hint));
This is search.xml inflated in previous snippet, containing MenuItem and ActionView:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/menu_search"
android:title="#string/m_search"
android:icon="#android:drawable/ic_menu_search"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
And this is onSearchRequested callback in ProjectDetail Activity:
#Override
public boolean onSearchRequested() {
L.dd("SEARCH", "REQUESTED IN PROJECT");
Bundle searchData = new Bundle();
searchData.putLong(Const.EXTRA_PROJECT_ID, projectId);
searchData.putLong(Const.EXTRA_ACCOUNT_ID, accountId);
startSearch(null, false, searchData, false);
return true;
}
Finally, this is searchable.xml as referenced from Manifest:
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="#string/app_label"
android:hint="#string/search_hint"
android:searchSuggestAuthority="my.package.provider.SearchSuggestionsProvider"
android:searchSuggestSelection=" ?"
android:includeInGlobalSearch="true"
/>
Thanks in advance.

I had the same problem. Found one simple workaround here.
Generally speaking you override method startActivity in search activity and put params to intent when action is equal to Intent.ACTION_SEARCH:
#Override
public void startActivity(Intent intent) {
// check if search intent
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
intent.putExtra("KEY", "VALUE");
}
super.startActivity(intent);
}
And then in searchable activity get passed params like this:
private void handleIntent(Intent intent){
if (Intent.ACTION_SEARCH.equals(intent.getAction())){
mSearchedQuery = intent.getStringExtra(SearchManager.QUERY);
mExtraData = intent.getStringExtra("KEY");
}

Related

Android Search Widget in Actionbar and second unnecessary search on top

I want to create a search for the user in the ActionBar. I use the SearchView Widget as an Action View. But when I include the
part in the manifest, it also pops up a second search on top. Both the view on top and the ActionBar Search work. When I remove the part from the manifest, the second Search doesn't pop up and only the one in the ActionBar does, but nothing happens when I hit the search button.
This is how it looks:
I only want the second view not the white search on top. Perhaps somebody easily sees whats wrong.
This is my AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/BlueTheme">
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:label="#string/app_name"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.default_searchable"
android:value=".helper.SearchResultsActivity" />
</activity>
<activity android:name=".helper.SearchResultsActivity">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="#xml/searchable"/>
</activity>
</application>
The part of the Fragment(as part of MainActivity) which handles the search:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.persons, menu);
Log.d("ml Person", "creating Options Menu for Persons");
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_search:
getActivity().onSearchRequested();
return true;
}
return super.onOptionsItemSelected(item);
}
widget in menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_search_white_24dp"
android:orderInCategory="10"
android:title="#string/action_search"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
searchable.xml
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="#string/app_name"
android:hint="#string/search_hint_persons" />

return data to calling activity from searchable

I have this app where the user reads articles through a webview. He can read related articles and press the back or up button to go back through his history. Is there a way to override the search widget in the action bar so that it calls SearchResultsActivity through startActivityForResult() or something? I'd like for the user to click an article and have the link to that article passed back to the webview to keep the history intact.
from ArticleActivity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_article, menu);
/* Search results in new activity, clicked article passed back to articleActivity
Associate searchable configuration with the SearchView */
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
ComponentName componentName = new ComponentName(this, SearchResultsActivity.class);
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName));
return true;
}
from manifest
<activity
android:name=".ArticleActivity"
android:label="#string/article"
android:parentActivityName=".CategoryActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="app.morningsignout.com.morningsignoff.CategoryActivity" />
</activity>
<activity
android:name=".SearchResultsActivity"
android:launchMode="singleTop"
android:label="#string/title_activity_search">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
menu_article.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="app.morningsignout.com.morningsignoff.ArticleActivity">
<item android:id="#+id/action_search"
android:title="#string/action_search"
android:icon="#android:drawable/ic_menu_search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

SearchView: getSearchableInfo returns null

I'm trying to implement searching in my android app. There are two activities, the MainActivity where search is launched (via searchview in action bar) and ResultsActivity, where search is handled and a list is inflated with results. The problem is that the getSearchableInfo method that i invoke in onCreateOptionsMenu in the main activity returns a null, like no searchable.xml were attached to the activity. I'v tried many combinations of meta data arrangement in the manifest, also every solution found on the internet and other stackoverflow questions, but nothing seems to work.
These are the sources:
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Light" >
<activity
android:name="com.example.webparser.MainActivity"
android:label="#string/app_name">
<intent-filter>
<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>
<activity android:name="com.example.ResultsActivity" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
</activity>
<meta-data
android:name="android.app.default_searchable"
android:value=".ResultsActivity" />
</application>
** MainActivity.java **
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
SearchManager searchManager = (SearchManager) getSystemService(getApplicationContext().SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
Log.d("Search:", searchManager.getSearchableInfo(getComponentName())
.toString());
return true;
}
** ResultsActivity.java **
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
elementi = new ArrayList<String>();
for(Ricetta ricetta:ricette){
if( ricetta.getNome().toLowerCase().matches(query) ){
elementi.add(ricetta.getNome());
}
}
adapter=new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
elementi);
lista.setAdapter(adapter);
Log.i("LOG:", "searching");
}
}
** searchable.xml **
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="#string/app_name"
/>
Please notice that I inserted a Log.d where the searchview is supposed to be initialized, and where is called getSearchableInfo, so at runtime a nullpointerexception is raised and the app doesn't launch, but if that Log.d is removed then everything but the search works (on pressing enter in the search box nothing happens). I think there is a problem with the manifest, but I can't figure out what it is. Does anyone have any clue?
I also tried to launch the main activity in singleTop pointing the searchable meta data tags to the main activity, but the same exception is raised.
I notice that you are using Menu to try an obtain your search view instead of the findViewById function
SearchView searchView = (SearchView) menu.findItem(R.id.search)
.getActionView()
Should be more like this
SearchView searchView = (SearchView) findViewById(R.id.search);
This would give you the SearchView you are looking for.
Faced the same problem. Following helped me:
This is my MainActivity
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_list_view_test, menu);
SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
MenuItem searchItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setSearchableInfo( searchManager.getSearchableInfo(getComponentName()) );
return true;
Note: Make sure that you have imported SearchView from Support.v7.widget
(import android.support.v7.widget.SearchView;)
This is my Menu.xml for MainActivity
< item android:id="#+id/search"
android:title="Search"
android:icon="#drawable/ic_action_search"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView" />
In my case I have similar set up just a little bit different. I have:
<meta-data android:name="android.app.default_searchable"
android:value=".ResultsActivity" />
in my Main Activity. And
<meta-data android:name="android.app.searchable"
android:resource="#xml/searchable" />
and
searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName));
should work.
in my ResultActivity.
And I create a component name in my MainActivity with:
ComponentName componentName = new ComponentName(context, ResultActivity.class);
Note: be careful with your item layout:
Use: app:actionViewClass="android.support.v7.widget.SearchView" if you have problem with android:actionViewClass="android.support.v7.widget.SearchView"

SearchView in ActionBarSherlock

I'm using the SearchView widget in ActionbarSherlock as a follows:
File.java
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.MenuSearch).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(true);
searchView.setSubmitButtonEnabled(true);
return true;
}
File.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/MenuSearch" android:title="#string/Bs"
android:icon="#drawable/ic_action_search"
android:showAsAction="always|withText"
android:actionViewClass="com.actionbarsherlock.widget.SearchView" >
</item>
</menu>
In my application I get to show the search icon and select it unfolds the search box for the widget, but when I write any search I do not know how to interact with the widget SearchView to launch a new activity and show a series of results.
With the command searchView.setSubmitButtonEnabled(true); appears a icon similar to 'play' and I suppose it is for just that, but I do not know how to interact with it.
Can anyone help?
Official android documentation here describes how start new activity to handle search query and display results.
First you need to create (if you havent already) searchable configuration in res/xml/searchable.xml, like this:
<?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" />
Set this configuration for your activity, that contains SearchView in actionbar, like this (in manifest):
<activity ... >
...
<meta-data android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
So basically, you need your searchable activity (new activity that will start after submitting search query) to handle the android.intent.action.SEARCH action. Declare it in manifest like this:
<activity android:name=".SearchResultsActivity" ... >
...
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
...
</activity>
And your searchable activity should look like this:
public class SearchResultsActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
...
handleIntent(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
...
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
//use the query to search your data somehow
}
}
...
}

onSuggestionClick recreates my activity

In my application i made my content provider searchable, defining my main activity as the default search activity on my manifest.
<activity
android:name="com.pt.application.MainActivity"
android:label="#string/title_activity_map"
android:launchMode="singleTop"
android:theme="#style/AppTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
Then i implemented the onSuggestionClick option to update a map, based on the suggestion clicked by the user. The searchview is on the action bar.
The problem is that when the user clicks on a suggestion, somehow the activity is recreated (i think OnPause and OnResume are called?). Is there any way to prevent this from happening? I don't want that my activity is "recreated" every time the user clicks on a suggestion.
If more code is needed, please ask. Thanks.
EDIT: Code added
<?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:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
android:voiceLanguageModel="web_search"
android:searchSuggestAuthority="com.pt.provider"
android:searchSuggestIntentData="content://com.pt.provider/busstop">
</searchable>
On my main activity:
// Bind the Activity’s SearchableInfo to the Search View
searchView = (SearchView)menu.findItem(R.id.menu_search).getActionView();
this.setupSearchView();
private void setupSearchView()
{
// Use the Search Manager to find the SearchableInfo related
// to this Activity.
SearchManager searchManager =
(SearchManager)getSystemService(Context.SEARCH_SERVICE);
SearchableInfo searchableInfo =
searchManager.getSearchableInfo(getComponentName());
searchView.setSearchableInfo(searchableInfo);
searchView.setSubmitButtonEnabled(false);
searchView.setOnSuggestionListener(new OnSuggestionListener() {
#Override
public boolean onSuggestionSelect(int position) {
return false;
}
#Override
public boolean onSuggestionClick(int position) {
// Do things
return false;
}
});
}
Solved my question. Changed on the manifest:
From:
android:launchMode="singleTop"
To:
android:launchMode="singleTask"

Categories

Resources