Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Search widget - difference between onQueryTextSubmit and sending Intent to SearchableActivity?

I have an activity that contains a SearchView widget. I am handling the results of the text search using an onQueryTextSubmit listener, and this works fine. (The activity itself is designated as a Searchable Activity).

I recently decided to add voice recognition, by adding the "voiceSearchMode" attribute in the searchable.xml file:

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:voiceSearchMode="showVoiceSearchButton|launchRecognizer">
</searchable>

When I added the voice recognition, the onQueryTextSubmit listener does not get called after providing the voice input (however, it still gets called after providing the text input using the editText box). The voice recognizer sends an ACTION_SEARCH Intent back to the same Activity (which can be handled in the onCreate method). Is there a way to activate the onQueryTextSubmit method with the voice recognizer (or something similar which doesn't require re-creating the activity?) The reason I am asking is because if the recognizer has to send an intent, I have to create and send an additional bundle with APP_DATA and that doesn't seem to be working.

So my question is:

(1) How do you use (or can you use) an onQueryTextSubmit listener with voice recognition search enabled? (the same way you would use it with regular text based search)

(2) If (1) is not possible, then how can I pass additional data with the voice recognition search query via an intent? I tried adding it through onSearchRequested() like this:

@Override
public boolean onSearchRequested() {
    Bundle appData = new Bundle();
    appData.putInt("testKey", 44);
    this.startSearch(null, true, appData, false);
    return true;
}

but when I try to access this in onCreate, appData is null:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.overview_list);

    Bundle extras = getIntent().getExtras();
    Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);

    // Receive search intents (from voice recognizer)
    Intent intent = getIntent();
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
      String query = intent.getStringExtra(SearchManager.QUERY);
      //doMySearch(query);
    }
}

(Also, when I add the onSearchRequested handler, pressing the magnifying glass icon has the effect of expanding the search widget twice on top of each other - I imagine this is because I am starting the search manually in addition to having set up a searchable xml configuration).

On a related note, what is the advantage of sending an intent over using a listener within the same activity? I understand that if your SearchableActivity is another activity then you would want to send an intent to it; but in the case where the SearchableActivity is the same activity that contains the search widget, what is the point of using an intent?

Any comments and suggestions would be greatly appreciated. Let me know if I need to provide any additional details.

like image 883
abeliangrape Avatar asked Mar 14 '13 16:03

abeliangrape


1 Answers

(1) As far as I can tell through extensive debugging onQueryTextSubmit never gets called when I input search queries through my voice recognizer button. However, there's an easy workaround - see below.

(2) I solved my issue by setting the activity launch mode to "singleTop" - this means that instead of re-creating the activity after voice search, the new ACTION_SEARCH intent is handled within the existing instance of the activity in the onNewIntent() handler. As a result, you have access to all of the private members of the existing activity, and you don't need to pass any data through bundles by modifying the search intent.

AndroidManifest.xml: add launchmode=singleTop attribute to your searchable activity:

<activity
    android:name=".SearchableActivity"
    android:label="@string/app_name"
    android:uiOptions="splitActionBarWhenNarrow"
    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" />
</activity>

In SearchableActivity, add onNewIntent() method:

@Override
public void onNewIntent(Intent intent) {
    super.onNewIntent(intent);      
    setIntent(intent);
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        // Gets the search query from the voice recognizer intent
        String query = intent.getStringExtra(SearchManager.QUERY);

        // Set the search box text to the received query and submit the search
        mSearchView.setQuery(query, true);
    }
}

This essentially receives the voice recognizer query and puts it in the text box, and submits the text box search which is handled by onQueryTextSubmit as usual.

like image 85
abeliangrape Avatar answered Sep 20 '22 01:09

abeliangrape