48

I've got a problem trying to add a SearchView widget to the ActionBar in my activity - I get a null value when calling getActionView to get my SearchView object.

I've been following the Android Developer guide and also went through a ton of SO questions as well as some other links on the Internet; all to no avail. It could be something simple but I wasn't able to figure it out - it seems to me my code is basically the same as that from google (apart from changing some names etc.) but it still won't work.

Any help would be appreciated.

Included below are relevant bits of the code. Please let me know if anything's unclear of if you have any idea as to what could possibly be wrong.

Activity code:

    private ListView workflowListView;
    private DrawerLayout drawerLayout;
    private ListView drawerList;
    private ActionBarDrawerToggle drawerToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
        setContentView(R.layout.activity_workflow_list);

        workflowListView = (ListView) findViewById(R.id.workflowListView);
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawerList = (ListView) findViewById(R.id.drawer_list);

        drawerToggle = new ActionBarDrawerToggle(
             this,                  /* host Activity */
             drawerLayout,         /* DrawerLayout object */
             R.drawable.ic_launcher,  /* nav drawer icon to replace 'Up' caret */
             R.string.app_name,  /* "open drawer" description */
             R.string.app_name  /* "close drawer" description */
             ) {

                /** Called when a drawer has settled in a completely closed state. */
                public void onDrawerClosed(View view) {
    //                getActionBar().setTitle("Closed drawer");
                }

                /** Called when a drawer has settled in a completely open state. */
                public void onDrawerOpened(View drawerView) {
    //                getActionBar().setTitle("Open drawer");
                }
       };

       drawerLayout.setDrawerListener(drawerToggle);
       ActionBar actionBar = getActionBar();
       actionBar.setDisplayShowTitleEnabled(false);

       actionBar.setDisplayHomeAsUpEnabled(true);
       actionBar.setHomeButtonEnabled(true);
       actionBar.setIcon(android.R.color.transparent);

       String[] testData = {"a", "b", "c", "d"};
       ArrayList<String> workflowList = new ArrayList<String>();
           for (String s : testData) {

                workflowList.add(s);
           }

       ArrayAdapter<String> workflowAdapter = new ArrayAdapter<String>(this.getApplicationContext(), R.layout.workflow_list_item, workflowList);

            workflowListView.setAdapter(workflowAdapter);
   }


   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
   // Inflate the menu; this adds items to the action bar if it is present.
        MenuInflater inflater = getMenuInflater();

        inflater.inflate(R.menu.workflow_list, menu);
        inflater.inflate(R.menu.options_menu, menu);

        // Associate searchable configuration with the SearchView
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);

        // The below line returned null even though it was used in Google sample code
        SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();

        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

        return super.onCreateOptionsMenu(menu);
    }

xml/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:includeInGlobalSearch="false" />

menu/options_menu.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" >

    <item android:id="@+id/search"
          android:title="@string/search_title"
          android:icon="@drawable/ic_action_search"
          android:showAsAction="always|collapseActionView"
          android:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
JakeP
  • 1,736
  • 4
  • 23
  • 31
  • In your `options_menu.xml`, do you really need to use the support library? Can you try to set `android:actionViewClass="android.widget.SearchView"`? – jbihan Sep 16 '13 at 19:21
  • @jbihan - Well, it's required by the application spec so even if I delete it now, I'll have to include it in the future. – JakeP Sep 23 '13 at 09:20

8 Answers8

107

Try to replace the failing line with:

mSearchMenuItem = menu.findItem(R.id.action_search);
mSearchView = (EnglishVerbSearchView) MenuItemCompat.getActionView(mSearchMenuItem);

Where R.id.action_search is the id of your search item in the menu.

EDIT

Your manifest should look like that:

<activity
       android:name="com.bronzelabs.twc.activities.WorkflowListActivity"
       android:label="@string/app_name"
       android:theme="@style/Theme.AppCompat.Light" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>
<activity 
        android:name=".activities.SearchResultActivity"
        android:theme="@style/Theme.AppCompat.Light"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"
            android:value=".activities.SearchResultActivity" />
    </activity>

The way you call setSearchableInfo is:

mSearchView.setSearchableInfo(searchManager.getSearchableInfo(
            new ComponentName(getApplicationContext(), SearchResultActivity.class)));

EDIT 2

Make sure your menu xml file is like that (pay attention to those 2 attributes with yourapp namespace - this is needed when you use the compat library):

<menu xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <item android:id="@+id/action_search"
      android:title="@string/action_search"
      android:icon="@drawable/action_search"
      yourapp:showAsAction="always|collapseActionView"
      yourapp:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
Szymon
  • 42,577
  • 16
  • 96
  • 114
  • I think this helped... Could you actually explain to me exactly the difference between your code and mine? Also, it seems this change caused me to get an NPE on the next line: searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); Any idea on how to fix it now? – JakeP Sep 23 '13 at 09:19
  • Your code failed because `SearchView` is not a `MenuItem` so cannot be obtained by `menu.findItem`. You have to get the menu item for search first and then get your `SearchView`. – Szymon Sep 23 '13 at 09:49
  • Sorry, my previous edit was incorrect. Still looking at it... Can you post your AndroidManifest.xml for your activity? – Szymon Sep 23 '13 at 09:55
  • http://pastebin.com/6TeHfMr5 This link contains my AndroidManifest.xml file's content. It'll expire in 1 week. – JakeP Sep 23 '13 at 12:13
  • So your SearchView is in WorkflowlistActivity and you want to display results in SearchResultActivity? – Szymon Sep 23 '13 at 12:37
  • Eventually I want the results to be shown in WorkflowlistActivity - the idea behind it is for this activity to contain a searchbox with dynamic suggestions. However, I wanted to do it gradually - i.e. start by moving to another activity with the results displayed there :) Sorry if it's confusing. – JakeP Sep 23 '13 at 13:06
  • I introduced the changes you'd suggested but the NPE still persists, and on the exact same line. Do you have any other ideas? It looks to me like it has to be something so simple neither of us didn't even think of... – JakeP Sep 26 '13 at 15:25
  • I'll take a look at my code. I remember it was quite tricky to set up correctly. – Szymon Sep 27 '13 at 06:17
  • Hmm, not sure. It cannot find the searchable info for the correct activity. Can you post your manifest and the line that's failing again? – Szymon Sep 29 '13 at 11:00
  • Sure. This is the manifest file: http://pastebin.com/GFm7gjue And this is the failing line: `searchView.setSearchableInfo(searchManager.getSearchableInfo( new ComponentName(getApplicationContext(), SearchResultActivity.class)));` (in the onCreateOptionsMenu of the WorkflowListActivity class). – JakeP Sep 30 '13 at 08:32
  • This one is driving me crazy! Which one is null: `searchView` or what `searchManager.getSearchableInfo` returns? – Szymon Sep 30 '13 at 09:51
  • It's the searchView that's null - I just confirmed that. Sorry for the late reply, there's been some other projects that need my attention; I'm trying to go back to this whenever I've got time though. Thanks for your help. – JakeP Oct 03 '13 at 16:05
  • And what about `mSearchMenuItem`? Is that null too? – Szymon Oct 03 '13 at 21:43
  • Nope, looks like that's not null. It's just that searchView object. – JakeP Oct 04 '13 at 08:07
  • This is what my options_menu.xml file looks like: http://pastebin.com/5E6xP4vA I know the names might be a bit different but don't they depend on me to set them to whatever I want? Anyway, they correspond to the actual code and don't seem to be causing any problems... Thanks for your time @Szymon - it's nice to see a person with such a familiar name help me :) – JakeP Oct 04 '13 at 16:13
  • 3
    You need to change 2 of the namespaces, they should be `app` in your case: for `showAsAction` and `actionViewClass` - see my example above. Familiar name? – Szymon Oct 04 '13 at 20:19
  • Sorry for such late reply but I had another project which needed to be taken care of. As for this issue - I changed these 2 namespaces as you suggested and it started working! :) I'll mark your answer as the solution in a sec but could you also explain to me exactly why they need to be `app` and not whatever they were before? These little details of XML files in Android development still elude me... As for your name, it sounds a bit Polish to me :) – JakeP Nov 13 '13 at 10:20
  • This is because those attributes come from a library (action bar compat) that is included in your project. Check more in this link: http://developer.android.com/tools/sdk/tools-notes.html (notes for revision 17). And yes, I'm Polish :) (though I live in Australia). Out of curiosity, why is that familiar? – Szymon Nov 13 '13 at 11:02
  • I've checked the link you've posted but tbh I couldn't find anything related to that bit in particular; could you elaborate on this issue a bit more? I'm just wondering if that `app` namespace simply always has to be `app` or if it depends on some other value I'd set up in another XML file... (I'm Polish though I live in the UK :) – JakeP Nov 13 '13 at 12:16
  • 5
    `app` can be anything, in my example it is `yourapp`. It has to point to `http://schemas.android.com/apk/res-auto` schema though. – Szymon Nov 13 '13 at 12:22
  • 1
    Well then, it looks like I need to do more reading on Android schemas then. Thanks again for your help, @Szymon :) – JakeP Nov 13 '13 at 12:35
  • 2
    Thank you so much, I searched a lot for hours and I had problems, but this one specially Edit to resolved my problem. – daniel Feb 21 '14 at 17:41
  • My issue was Proguard. If you have Proguard enabled, make sure you have a rule that keeps the `android.support.v7.widget.SearchView`. For example, to keep everything in all the different versions of the support library, add `-keep class android.support.** { *; }` and `-keep interface android.support.** { *; }`. – ashughes May 24 '14 at 00:18
  • In my case these two lines are very important: xmlns:yourapp="http://schemas.android.com/apk/res-auto" "yourapp:actionViewClass="android.support.v7.widget.SearchView" – cwhsu May 28 '14 at 04:32
  • Thank you sir EDIT 2 really help – Ngo Phuong Le Sep 04 '14 at 14:51
  • Thank you for this solution. Would have never figured it out. – leafartist Sep 25 '14 at 19:38
  • [IMPORTANT] The hint and label in the searchable.xml must be references, and not hardcoded strings. – Whales Sep 25 '14 at 20:13
  • 1
    The `MenuItemCompat.getActionView()` has been deprecate. – zeleven Jan 04 '18 at 06:43
25

I had a similar probably that appeared on my release builds but not my debug builds when switching over to the v21 support library. Turned out to be an obfuscation problem, and adding this line to my proguard-rules.txt file fixed it:

-keep class android.support.v7.widget.SearchView { *; }
waynesford
  • 1,688
  • 19
  • 17
25

First check you are using app namespace for actionViewClass.

android:actionViewClass="android.support.v7.widget.SearchView"-this throws NPE

app:actionViewClass="android.support.v7.widget.SearchView"-use this

and second

Check if you are using same searchView in menu.xml and in your Activity

ketankk
  • 2,578
  • 1
  • 29
  • 27
1

I had a very similar issue where the following line was returning null

SearchView searchView = (android.support.v7.widget.SearchView)MenuItemCompat.getActionView(searchMenuItem);

The fix was in my styles.xml file, i changed my AppTheme's parent to Theme.AppCompat.Light

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light">
Parampal Pooni
  • 2,958
  • 8
  • 34
  • 40
0

For anyone still searching, I followed everything above and could not seem to get things going. I wrapped my searchView.setSearchableInfo... in a null check and voila! It ran just like it ought to.

if (searchView != null) {
    searchView.setSearchableInfo(searchManager.getSearchableInfo(
                    new ComponentName(getApplicationContext(), SearchActivity.class)));
}
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Jacob
  • 588
  • 1
  • 4
  • 14
0

for me, This is the right answer: In menu/options_menu.xml, use this:

app:actionViewClass="android.support.v7.widget.SearchView"
liang
  • 1
  • 2
-1

I think you're occupying FragmentActivity, you need to extend of ActionBarActivity

steving21
  • 1
  • 3
  • I'm not sure your answer actually makes any sense. The class was extending ActionBarActivity if that's what you mean. – JakeP Feb 12 '14 at 10:39
-2

I had the same problem. My solution is: replace android:actionViewClass="android.support.v7.widget.SearchView" with

android:actionViewClass="android.widget.SearchView"
Hans
  • 523
  • 1
  • 5
  • 16
  • 1
    Sorry mate but, as I've mentioned above, I am required to use the support library by the project's specs. – JakeP Jan 08 '14 at 14:41