Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android assisted Search: The search button does not invoke the searchable Activity (Other Solutions did not help)

I wrote this small test application to demonstrate the problem, that is the searchable activity is not started when the user presses the search button on the keyboard.

I have been following the developer guides, but from my web search, it turns out that the official developer guide misses some points. From my SO search (which did not help):

  • Reference 1: Solved by Adding tag in the element in the manifest. I also looked into the manifest of the sample "User Dictionary" (I don't know where can I find the samples online, or I would link to it). This tag is there in the application element.

  • Reference 2: The "android:label" and "android:hint" in res/xml/searchable.xml must be references to string resources and not hard coded strings. Mine are.

  • Reference 3: Add a tag with "android:name="android.app.default_searchable" " (and " android:value="<. searchable-activity-name>" ") in the manifest in the Activity from where the search is going to be initiated. Tried this, did not seem to work.

  • Reference 4: "Your Searchable activity has to do something - and actually display results." Mine does, it receives the intent with the ACTION_SEARCH action, and passes the search query string retrieved from the intent to a method named "performSearch(string)" which displays the string in a textview.

So what am I doing wrong, and what can I do to solve this?

Code: MainActivity.java - Has a single SearchView - the user enters the query and presses the Search button on the keyboard.

public class MainActivity extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

TestTwoActivity.java

    public class TestTwoActivity extends Activity {
        TextView tv;
        private static final String TAG = TestTwoActivity.class.getSimpleName();

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

            /**
             * The following code enables assisted search on the SearchView by calling setSearchableInfo() and passing it our SearchableInfo object.
             */
            SearchView searchView = (SearchView) findViewById(R.id.searchActivity_searchView);
            // SearchManager => provides access to the system search services.

            // Context.getSystemService() => Return the handle to a system-level
            // service by name. The class of the returned object varies by the
            // requested name.

            // Context.SEARCH_SERVICE => Returns a SearchManager for handling search

            // Context = Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android
            // system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching
            // activities, broadcasting and receiving intents, etc.

            // Activity.getComponentName = Returns a complete component name for this Activity 

            SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
            searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

            /**
             * If the search is executed from another activity, the query is sent to this (searchable) activity in an Intent with ACTION_SEARCH action.
             */
            // getIntent() Returns the intent that started this Activity
            Intent intent = getIntent();
            if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
                Log.i(TAG, "Search Query Delivered");//check
                String searchQuery = intent.getStringExtra(SearchManager.QUERY);
                performSearch(searchQuery);
            }

        }

        private void performSearch(String searchQuery) {
            //Just for testing purposes, I am simply printing the search query delivered to this searchable activity in a textview.
            tv = (TextView) findViewById(R.id.testTwoActivity_textView);
            tv.setText(searchQuery);
        }
}

res/xml/searchable.xml - The Searchable Configuration

<?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/searchViewHint" >
</searchable>

Manifest File

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tests"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".TestTwoActivity"
            android:label="@string/title_activity_test_two" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH"/> <!-- Declares the activity to accept ACTION_SEARCH intent -->
            </intent-filter> 
                <meta-data 
                    android:name="android.app.searchable"
                    android:resource="@xml/searchable" /> <!-- Specifies the searchable configuration to use --> 
        </activity>

        <!-- Points to searchable activity so the whole app can invoke search. -->
        <meta-data android:name="android.app.default_searchable"
                   android:value=".TestTwoActivity" />

    </application>

</manifest>

Layouts:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"

    android:orientation="vertical"

    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context="com.tests.MainActivity" >

    <android.support.v7.widget.SearchView
        android:id="@+id/searchActivity_searchView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
         /> 

</LinearLayout>

activity_test_two.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"

    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context="${relativePackage}.${activityClass}" >

    <android.support.v7.widget.SearchView
        android:id="@+id/searchActivity_searchView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
         /> 

    <TextView
        android:id="@+id/testTwoActivity_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

EDIT 1: it's crazy that I wrote a similar app with the search dilogue instead of the search widget, that works perfectly.

I tried to debug it in Eclipse but debugging stops because the TestTwoActivity (the searchable activity) simply won't start.

like image 663
Solace Avatar asked Dec 19 '14 14:12

Solace


1 Answers

I'm not sure if you've forgotten to add it but your MainActivity misses setting the searchable info on the SearchView:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    SearchView searchView = (SearchView) findViewById(R.id.searchActivity_searchView);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
}

As a side note:

I've had problems with the default_searchable meta-tag, when using flavors. It seemed to only work when using the full path (skipping the flavor) to the search activity e.g.:

<meta-data 
    android:name="android.app.default_searchable"
    android:value="com.example.SearchActivity"/>
like image 133
Simas Avatar answered Oct 28 '22 01:10

Simas