搜索信息总是为空。

21

我在设置操作栏中的搜索视图方面遇到了困难。

我遵循了开发者网站上的步骤,但仍然无法正常工作。我感觉可能漏掉了什么。

运行我的代码时,它总是输出“无法获取可搜索信息”(MainActivity.setupSearchView())。

MainActivity.java

// package...
// imports...
public class MainActivity extends Activity {
    private static String tag = "Main Activity";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater mi = getMenuInflater();
        mi.inflate(R.menu.search_view, menu);
        setupSearchView(menu);
        return true;
    }
    private void setupSearchView(Menu menu) {
        SearchManager sm = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchableInfo si = sm.getSearchableInfo(getComponentName());
        if (si == null) {
            Log.wtf(tag, "failed to get searchable info");
            return;
        }
        SearchView sv = (SearchView) menu.findItem(R.id.menu_search).getActionView();
        sv.setSearchableInfo(si);
        // Do not iconify the widget; expand it by default
        sv.setIconifiedByDefault(false);
    }
}

搜索结果活动(SearchResultsActivity.java)

// package...
// imports...
public class SearchResultsActivity extends ListActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Intent queryIntent = getIntent();
        doSearchQuery(queryIntent);
    }
    @Override
    public void onNewIntent(final Intent newIntent) {
        super.onNewIntent(newIntent);
        final Intent queryIntent = getIntent();
        doSearchQuery(queryIntent);
    }
}

searchable.xml

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/search_label" >
</searchable>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kpaek.examples"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="15" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".search.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=".SearchResultsActivity">
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />
        </activity>
    </application>
</manifest>
7个回答

43

我发现的关键问题是 searchable.xml 不能包含文字字符串,只能使用资源引用。因为这会导致 getSearchableInfo 静默失败,所以我在这个问题上浪费了大约半天时间。


谢谢!你为我节省了半天的时间 :) - HighFlyer
哇!这是一个非常恶劣的 bug。我已在此处报告了它:https://code.google.com/p/android/issues/detail?id=37517 - Rodja
2
实际上,文档中指出了哪些参数必须是字符串资源,哪些可以是字符串。http://developer.android.com/guide/topics/search/searchable-config.html - Yaroslav Mytkalyk
因为这个问题,我刚刚浪费了4个小时,如果我没有看到这个答案,可能会更长时间。非常感谢。 - Reuben Scratton
我们应该让你成为骑士,以表彰你的回答。 - eMich
显示剩余3条评论

19

我发现intent-filter和meta-data元素必须包含在清单活动元素中,该元素是搜索启动的源头(MainActivity具有SearchView),才能使方法getSearchableInfo(getComponentName())返回正确的配置而不是null。

<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>

    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>

    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
</activity>

我想知道是否可以(而且现在我采取的解决方案是)保留结果活动声明中的意图和元数据,并将 getSearchableInfo() 的参数更改如下:

我好奇的是,是否可以改为(并且这是我现在采用的解决方法),保留结果活动声明中的意图和元数据,并将参数更改为以下内容:

<activity android:name=".SearchResultsActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>

    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
</activity>

对MainActivity的更改(请注意,可搜索信息的赋值语句):

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_search, menu);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView mySearchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
    SearchableInfo searchableInfo = searchManager.getSearchableInfo(new ComponentName(getApplicationContext(), SearchResultsActivity.class));
    mySearchView.setSearchableInfo(searchableInfo);

    return true;
}

1
谢谢,唯一对我有用的解决方案是新的组件名称......我不知道为什么其他的都没用。 - Gaurav
哇!唯一有效的解决方案!值得更多的赞! - camelCaseCoder

19

在我的情况下,在res/menu/mymenu.xml中使用自定义标签对我有用:

app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"

不要使用:

android:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.support.v7.widget.SearchView"

11

这个问题折磨了我一整天 - 我以为它和ActionBarSherlock有关,但实际上即使与其一起使用也能正常工作。

问题在于我试图绕过示例进行搜索。至少你的一个活动 - 从中进行搜索的那个活动 - 必须在清单文件中具有此意图过滤器:

<intent-filter>
  <action android:name="android.intent.action.SEARCH" />
</intent-filter>
如果不是这样,那么searchManager.getSearchableInfo(getComponentName())始终返回null,并且您的配置将被忽略。

3
我遇到了这个问题,但上面的建议并没有解决它。相反,问题出在SearchResultActivity中设置默认类别。例如,以下代码会导致错误:
<activity android:name=".SearchResultActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
    <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
            <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchable" />
</activity>

移除android.intent.category.DEFAULT可以解决这个问题。

<activity android:name=".SearchResultActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
    <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchable" />
</activity>

此前的回答有误。MainActivity 应该定义为 android.app.default_searchable,而 android.app.searchable 只适用于 SearchResultsActivity。
<activity
    android:name=".MainActivity"
    android:label="@string/app_name">
    <!-- other stuff-->
    <meta-data android:name="android.app.default_searchable"
            android:value=".SearchResultsActivity" />
</activity>

总的来说,SearchManager 是一个脆弱的组件,可能会在 AndroidManifest.xml 不完美的情况下发生悄无声息的故障。

3

开发者网站指出:

可搜索配置定义了SearchView的行为,并在res/xml/searchable.xml文件中定义。最少,可搜索配置必须包含一个android:label属性,该属性的值与您Android清单文件中的 或 元素的android:label属性相同。

例如,他们展示了以下内容:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_name"
        android:hint="@string/search_hint" />

app_name,就像在清单文件中一样,是活动的标签。然而,在您的可搜索内容中,标签指的是search_label。如果app_name和search_label相等,那么可能会起作用,但这似乎对我来说很脆弱。


1
我浪费了8个小时,因为我检查了所有上面的解决方案,但对我来说还有一件事情是缺失的。
在我的Android清单文件中:
<meta-data
                android:name="android.app.searchable"
                android:value="@xml/searchable" />

Should has been:

<meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />

对我来说,它是默默地失败了。首先最好的做法就是复制并粘贴示例代码。只需确保所有属性完全相同即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接