开发者

Android: Return search query to current activity

I followed the steps described on http://developer.android.com/guide/topics/search/search-dialog.html to implement a search feature in my notepad application.

My problem is, that when I finish the search a new activity opens capturing my search query. But what I really want, is the query returned to the current activity instead of starting a new one.

Is this possible?

UPDATE:

AndroidManifest.xml


<activity android:name="MyNotepad"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <action android:name="android.intent.action.SEARCH"></action>
            </intent-filter>
            <meta-data android:resource="@xml/searchable" android:name="android.app.searchable"></meta-data>
        </activity><activity android:name="Preferences" android:label="Preferences" >
</activity>

searchable.xml


<?xml version="1.0" encoding="utf-8"?>
<searchable
  xmlns:android=&q开发者_运维知识库uot;http://schemas.android.com/apk/res/android"
  android:label="@string/app_name"
  android:hint="@string/search_hint">
</searchable>

JAVA-code


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_pad);
    Intent intent = getIntent();
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        Toast.makeText(getApplicationContext(), query, Toast.LENGTH_LONG).show();
    }
}


@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    switch(item.getItemId())
    {
        case R.id.menuItemSearch:
            startSearch("", false, null, false);
    break;
    }
    return true;
}

Even if I use the search-button on the phone it doesn't work. I therefor believe that the problem is in the AndroidManifest.xml


In your Application Manifest you need to define the current activity as a searchable activity.

<activity android:name="BrowseItems" android:label="@string/browseitems"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <meta-data android:name="android.app.searchable"
                android:resource="@xml/itemsearchable" />
</activity>

You then use the following code, which is from http://developer.android.com/guide/topics/search/search-dialog.html#LifeCycle

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

@Override
protected void onNewIntent(Intent intent) {
    setIntent(intent);
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
      String query = intent.getStringExtra(SearchManager.QUERY);
      // Do work using string
    }
}

You can then use the string to reload your activity, if its a list activity you can call your code that you use to load data and use the string in that.


Add to AndroidManifest.xml in your Searchable Activity:

android:launchMode="singleTop" 

so, your AndroidManifest.xml looks like:

<activity android:name="MyNotepad"
              android:label="@string/app_name"
              android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
            <action android:name="android.intent.action.SEARCH"></action>
        </intent-filter>
        <meta-data android:resource="@xml/searchable" android:name="android.app.searchable"></meta-data>
    </activity><activity android:name="Preferences" android:label="Preferences" >

The reason:

From this post:

The activity launch mode has four valid values:

"standard" "singleTop" "singleTask" "singleInstance"

The 'standard' is the default value. The four values fall into two groups:

'standard' and 'singleTop' can instantiate multiple activity instances and the instance will stay in the same task. For 'singleTask' or 'singleInstance', the activity class uses the singleton pattern, and that instance will be the root activity of a new task. Let's examine each value: "standard":

Multiple instances of the activity class can be instantiated and multiple instances can be added to the same task or different tasks. This is the common mode for most of the activities.

"singleTop":

The difference from 'standard' is, if an instance of activity already exists at the top of the current task and system routes intent to this activity, no new instance will be created because it will fire off an onNewIntent() method instead of creating a new object.


I simply use this:-

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String s) {
            //on submit
            return false;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            //get all text changes
            return false;
        }
});

This is best used when you have to search across a listview and have to filter out items. I never go by implementing the search function using the manifest file. The 2 methods do all the job.


I was also facing the same problem, then I wrote this code and it solved my problem.

Implement this in your Activity

**implements SearchView.OnQueryTextListener, SearchView.OnCloseListener**

Add this function in the class:

private void setupSearchView()
        {

            searchView.setIconifiedByDefault(true);

            SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
            if (searchManager != null)
                {
                    List<SearchableInfo> searchables = searchManager.getSearchablesInGlobalSearch();

                    // Try to use the "applications" global search provider
                    SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
                    for (SearchableInfo inf : searchables)
                        {
                            if (inf.getSuggestAuthority() != null && inf.getSuggestAuthority().startsWith("applications"))
                                {
                                    info = inf;
                                }
                        }
                    searchView.setSearchableInfo(info);
                }

            searchView.setOnQueryTextListener(this);
            searchView.setOnCloseListener(this);
        }

Call the function in the onCreateOptionsMenu(Menu menu)

@Override
    public boolean onCreateOptionsMenu(Menu menu)
        {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.menu, menu);
            //restoreActionBar();
            // Associate searchable configuration with the SearchView
            //SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
            searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
            //searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
            setupSearchView();
            return super.onCreateOptionsMenu(menu);
        }

This will totally solve your problem..

Happy Coding!!


Briefly:

  1. Add android:launchMode="singleTop" to the searchable activity definition in the AndroidManifest.xml
  2. Implement onNewIntent in the searchable activity and handle the search there.


I followed Lachlan's clue of "You can then use the string to reload your activity", and finally worked this out. So please read Lachlan's post first, and then take the following 3 steps "to reload your activity":

  1. Save query string in ApplicationContext.
  2. Finish the new opened search Activity.
  3. Override OnResume, get query string you just saved, and then refresh the list.

Codes in List Activity:

private void handleIntent(Intent intent) {
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String searchText = intent.getStringExtra(SearchManager.QUERY);
        ((MyApp)this.getApplicationContext()).setSearchText(searchText);
        this.finish();
    }
}

protected void onResume() {
    super.onResume();

    String searchText = ((MyApp)this.getApplicationContext()).getSearchText();
    //refresh your list here...
}

MyApp class: (This original idea is from here: Android: How to declare global variables?)

public class MyApp extends Application {

    private String mSearchText;

    public String getSearchText() {
        return mSearchText;
    }

    public void setSearchText(String searchText) {
        this.mSearchText = searchText;
    }
}

Don't forget to add property android:name=".MyApp" to your application in the Manifest file. Good luck!


in the manifest file, add:

android:launchMode="singleTop"

To your search activity. Then, let your search activity implement SearchView.OnSuggestionListener finally:

mSearchView.setOnSuggestListener(this)

this way you can handle the suggestion click event with out creating a new instance of your search activity.


It doesn't bring up a new activity if the SearchView.OnSuggestionListener on the searchView is set, and the overridden methods return true (overriding the default behavior). You can do that in the onCreateOptionsMenu() implementation, like this:

    searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
        @Override
        public boolean onSuggestionSelect(int position) {
            return true;
        }

        @Override
        public boolean onSuggestionClick(int position) {
            CursorAdapter selectedView = searchView.getSuggestionsAdapter();
            Cursor cursor = (Cursor) selectedView.getItem(position);
            int index = cursor.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1);
            searchView.setQuery(cursor.getString(index), true);
            return true;
        }
    });

No need to force the activity to singleTop or other hacks.


Just add

<application>

  <meta-data 
     android:name="android.app.default_searchable"
     android:value="#Activity_Name" />

   <!-- All your activities, service, etc. -->

</application>

in your android_manifest.xml file where #Activity_Name is the name of the activity that handles the search.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜