Cannot get searchview in actionbar to work
AndroidAndroid ActionbarSearchviewAndroid Problem Overview
I am pretty new to java and android development; and I have been working on an app in which I want an action bar with a SearchView
. I have looked at the google examples but I can not get it to work. I must be doing something wrong and I'm about to give up on app-development :D I have searched but I have not found anything helpful. Maybe you guys can help me :)
The problem: I get the search view to open as it should, but after that nothing happens at all, I've noticed that my searchManager.getSearchableInfo(getComponentName()) returns null. Also my hint that I've given is not displayed in my search box which leads me to believing that maybe the app can't find my searchable.xml? Enough talk :)
MainActivity.java
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Get the SearchView and set the searchable configuration
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView =
(SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
return true;
}
}
searchable.xml
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/search_hint"
android:label="@string/app_label">
</searchable>
Androidmanifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.searchapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name=".SearchableActivity" >
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
</application>
</manifest>
SearchableActivity.java
package com.example.searchapp;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class SearchableActivity extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
// Get the intent, verify the action and get the query
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
doMySearch(query);
}
}
private void doMySearch(String query) {
Log.d("Event",query);
}
}
And here is a link to the referred project, I would be eternally grateful if someone was to help me with this!
Android Solutions
Solution 1 - Android
Your problem is in your AndroidManifest. I had it almost exactly as you do, because that is what I get following the documentation. But it is unclear or mistaken.
Watching at the API Demos source I found that the "android.app.searchable" metadata must go in your "results" activity, and in the main activity (or the activity where you place the SearchView) you point to the other one with "android.app.default_searchable".
You can see it in the following file, which is the Manifest from my test project:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<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=".SearchActivity" />
</activity>
<activity
android:name=".SearchActivity"
android:label="@string/app_name" >
<!-- This intent-filter identifies this activity as "searchable" -->
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!-- This metadata entry provides further configuration details for searches -->
<!-- that are handled by this activity. -->
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
</application>
It is also important that the hint and label in the searchable.xml are references, and not hardcoded strings.
I hope it solves your problem. It took me all day to figure it out :(
Solution 2 - Android
Android guides explicitly says:
// Assumes current activity is the searchable activity
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
Which is in your case NOT TRUE. Because you don't want to search in MainActivity but in SearchableActivity. That means you should use this ComponentName instead of getComponentName() method:
ComponentName cn = new ComponentName(this, SearchableActivity.class);
searchView.setSearchableInfo(searchManager.getSearchableInfo(cn));
Solution 3 - Android
Also it seems that both the android:hint and android:label attributes MUST be references to strings in strings.xml. Being lazy and hardcoding the string values doesn't seem to work at all :)
i.e. Don't do:
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="Search for something..."
android:label="My App">
</searchable>
But definitely do (as the OP correctly did):
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/search_hint"
android:label="@string/app_label">
</searchable>
Solution 4 - Android
If you are using Android Studio,
<meta-data
android:name="android.app.default_searchable"
android:value=".SearchActivity" />
part may not work.
write full package name like
<meta-data
android:name="android.app.default_searchable"
android:value="com.example.test.SearchActivity" />
Solution 5 - Android
be careful with "xml/searchable.xml".
If you made HARD CODE with android:hint
and android:label
.It will not work. Haha
Should be :
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/app_name"
android:label="@string/search_lb"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"/>
Solution 6 - Android
There's actually no need use the "missing part" as described in the answers above. This method(using a SearchView
) works exactly as the official docs say till Using the Search widget. Here a slight modification needs to made as follows:
Properties in a SearchableInfo
are used to display labels, hints, suggestions, create intents for launching search results screens and controlling other affordances such as a voice button(docs).
Thus, the SearchableInfo
object we pass to the SearchView.setSearchableInfo(SearchableInfo s)
must contain proper references to the target activity which should be displayed to show the search results. This is done by manually passing the ComponentName
of our target activity. One constructor for creating a ComponentName
is
public ComponentName (String pkg, String cls)
pkg
and cls
are package names and class names of the target activity to be launched for displaying search results. Note that:
pkg
must point to the root package name of your project and,
cls
must be a fully qualified name of the class(i.e. the entire thing)
e.g.:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Get the SearchView and set the searchable configuration
String pkg = "com.example.musicapp"
String cls = "com.example.musicapp.search.SearchActivity"
ComponentName mycomponent = new ComponentName(pkg,cls);
SearchManager searchManager =(SearchManager)getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(mycomponent));
searchView.setIconifiedByDefault(false); //if using on actionbar
return true;
}
Depending on your requirements take a look at the other ComponentName
constructors.
Solution 7 - Android
Make sure your searchables.xml
file is in the correct location (i.e, in your res/xml/
folder) and that the same file does not contain any errors - otherwise you will find that (SearchManager)getSystemService(Context.SEARCH_SERVICE).getSearchableInfo(componentName)
will return null, breaking your search functionality.
(Also, ensure you set componentName
in the appropriate manner, because the example shown in the Android guide is for only when you are making searches and displaying searches in the same Activity.)
Solution 8 - Android
i was facing same issue adding search intent filter like this to searchable activity:
<activity
android:launchMode="singleTop"
android:name=".ui.activities.MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<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>
Solution 9 - Android
Double check if the corresponding entry(ie search_hint and app_label) is present in values/strings.xml
eg
<string name="app_label">FunApp</string>
<string name="search_hint">Caps Off</string>