Android onSearchRequested() callback to the callin

2019-04-13 17:48发布

I have a MapActivity that will display the Android Search box when a search button is pressed. The SearchManager manages the dialog, and passes the user's query to a searchable activity, which searches an SQLite DB and displays the results using a custom adapter.

This works fine - and I'm getting the correct results from the DB displayed.

However, what I want to do is display the result in the MapActivity on a map when the user clicks on a search result. Currently, this means starting a new MapActivity, passing the search result in using a Bundle.

I'd have thought the cleaner way was to pass the search result back to the original activity, rather than start a new one. At the moment, my activity stack goes MapAct -> SearchManager -> Search Result -> New MapAct. Which means pressing "back" from the new MapAct will go back to the query results, then to the original MapAct.

It seems that in the Search Result, calling finish() does not cause onActivityResult to be called in the calling MapActivity.

Any ideas how to get this callback and maintain a sensible activity stack?

2条回答
smile是对你的礼貌
2楼-- · 2019-04-13 18:15

I've been digging around for an answer to this exact question and finally found something that works. I had to make the original calling activity also the searchable activity, so my entry in the manifest looks like this:

<activity android:name=".BaseActivity"
          android:launchMode="singleTop">
   <!-- BaseActivity is also the searchable activity -->
   <intent-filter>
      <action android:name="android.intent.action.SEARCH" />
   </intent-filter>
   <meta-data android:name="android.app.searchable"
              android:resource="@xml/searchable"/>
   <!-- enable the base activity to send searches to itself -->
   <meta-data android:name="android.app.default_searchable"
              android:value=".BaseActivity" />
</activity>

And then instead of searching in this activity, manually startActivityForResult with the real search activity, which will then allow you to setResult and finish back to the original calling activity.

I went into a bit more detail in a blog post here.

查看更多
爷的心禁止访问
3楼-- · 2019-04-13 18:35

I finally discovered a solution to this that does not involve singleTop.

First, in your Activity that originates the search, override startActivityForResult:

@Override
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        int flags = intent.getFlags();
        // We have to clear this bit (which search automatically sets) otherwise startActivityForResult will never work
        flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK;
        intent.setFlags(flags);
        // We override the requestCode (which will be -1 initially)
        // with a constant of ours.
        requestCode = AppConstants.ACTION_SEARCH_REQUEST_CODE;
    }
    super.startActivityForResult(intent, requestCode, options);
}

Android will always (for some reason) start the ACTION_SEARCH intent with the Intent.FLAG_ACTIVITY_NEW_TASK flag, for some reason, but if that flag is set, onActivityResult will never be (correctly) called in your originating task.

Next, in your searchable Activity, you just call setResult(Intent.RESULT_OK, resultBundle) as normal when the user selects an item.

Finally, you implement onActivityResult(int requestCode, int resultCode, Intent data) in your originating Activity and respond appropriately when the resultCode is Intent.RESULT_OK and the requestCode is your request code constant (AppConstants.ACTION_SEARCH_REQUEST_CODE in this case).

查看更多
登录 后发表回答