Search code examples
androidbundleandroid-searchmanager

Problem passing a Bundle with onSearchRequested


I'm actually trying to use the built-in search interface of Android, but I have some issues when I try to pass data with the search query.

Here is a brief explanation : I have an object in a first Activity (FirstActivity) called "Category" which implements Serializable (I already pass it successfuly between Activities) and I want to perform a search related to that category, and display the results in a second Activity (SecondActivity).

So, in FirstActivity I override the onSearchRequest method :

@Override
public boolean onSearchRequested() {
    Bundle appData = new Bundle();
    appData.putSerializable("category", _currentCategory);
    Log.d(Utils.LOG_TAG, "Bundle : "+appData.keySet());
    startSearch(null, false, appData, false);
    return true;
}

And in SecondActivity, I try to get this Bundle :

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    handleIntent(getIntent());
}

private void handleIntent(Intent intent){
    Bundle appData = intent.getBundleExtra(SearchManager.APP_DATA);
    if(appData == null) Log.d(Utils.LOG_TAG, "appData == null");
    Log.d(Utils.LOG_TAG, "Extras : "+intent.getExtras().keySet());
}

Problem is that appData seems to be equals to null everytime. Here is the logcat output :

Bundle : [category]
appData == null
Extras : [query, user_query]

I tried to add some other objects into the Bundle (Booleans, etc...) but it doesn't change anything at all and I keep having a null appData.


Solution

  • If you're using SearchView, it will not send your appData. Instead, consider using OnQueryTextListener. For example:

    ...
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.your-menu-id, menu);
    
        /*
         * Get the SearchView and set the searchable configuration.
         */
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.your-search-menuitem-id)
                .getActionView();
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        /*
         * Set query text listener here.
         */
        searchView.setOnQueryTextListener(mSearchViewOnQueryTextListener);
    
        return true;
    }// onCreateOptionsMenu()
    
    ...
    private final SearchView.OnQueryTextListener mSearchViewOnQueryTextListener = new SearchView.OnQueryTextListener() {
    
        @Override
        public boolean onQueryTextSubmit(String query) {
            /*
             * You don't need to deal with "appData", because you already
             * have the search query here.
             */
    
            // Tell the SearchView that we handled the query.
            return true;
        }// onQueryTextSubmit()
    
        @Override
        public boolean onQueryTextChange(String newText) {
            // TODO Auto-generated method stub
            return false;
        }// onQueryTextChange()
    };// mSearchViewOnQueryTextListener
    

    Note: You still need to keep the old way (using appData inside onSearchRequested()). In your onCreate(), if the extra for SearchManager.APP_DATA is null, that means you already handled the search query in the listener.

    Conclusion:

    • If the SearchView is inactive, and you invoke it via onSearchRequested(), this will happen: onSearchRequested() >> onCreate() (ACTION_SEARCH contains SearchManager.APP_DATA).
    • If the SearchView is active, the user types and submits search, this will happen: SearchView.OnQueryTextListener.onQueryTextSubmit() >> onCreate() (ACTION_SEARCH without SearchManager.APP_DATA).