新增自訂搜尋建議

您可以根據 Android 搜尋對話方塊或搜尋小工具中的近期搜尋查詢,提供搜尋建議。舉例來說,如果使用者查詢「puppies」,查詢會在使用者再次輸入相同查詢時顯示為建議。圖 1 是顯示近期查詢建議的搜尋對話方塊範例。

在開始之前,請先在應用程式中實作要進行基本搜尋的搜尋對話方塊或搜尋小工具。如要瞭解操作方式,請參閱「建立搜尋介面」。

基本概念

圖 1 顯示近期查詢建議的搜尋對話方塊螢幕截圖。

近期查詢建議即儲存搜尋。當使用者選取建議時,可搜尋活動會收到 ACTION_SEARCH 意圖,並將建議視為可搜尋活動已處理的搜尋查詢做為建議。

如要提供近期查詢建議,您必須:

  • 實作可搜尋的活動。
  • 建立可擴充 SearchRecentSuggestionsProvider 的內容供應器,並在應用程式資訊清單中宣告該供應器。
  • 根據提供搜尋建議的內容供應器相關資訊,修改可供搜尋的設定。
  • 每次執行搜尋時,將查詢儲存到內容供應器。

就像 Android 系統會顯示搜尋對話方塊,也會在對話方塊或搜尋小工具下方顯示搜尋建議。您需要提供系統擷取建議的來源,

當系統識別為活動可供搜尋並提供搜尋建議時,當使用者輸入查詢時,就會發生下列情況:

  1. 無論使用者開始輸入什麼內容,系統都會接收搜尋查詢文字,並對提供建議的內容供應器執行查詢。
  2. 內容供應器會傳回 Cursor,指向符合搜尋查詢文字的所有建議。
  3. 系統會顯示 Cursor 提供的建議清單。

顯示近期查詢建議後,可能會發生下列情形:

  • 如果使用者輸入其他鍵或變更查詢,上述步驟會重複執行,建議清單也會更新。
  • 如果使用者執行搜尋,系統會忽略建議,並使用一般 ACTION_SEARCH 意圖將搜尋傳送至可供搜尋的活動。
  • 如果使用者選取建議,系統會使用建議的文字做為查詢,將 ACTION_SEARCH 意圖傳送至您的可搜尋活動。

您為內容供應器擴充的 SearchRecentSuggestionsProvider 類別會自動執行上述步驟中的工作,因此幾乎無須編寫程式碼。

建立內容供應器

近期查詢建議所需的內容供應器是 SearchRecentSuggestionsProvider 的實作。這個類別會為您完成所有工作。您只需編寫用於執行一行程式碼的類別建構函式即可。

舉例來說,以下是最近查詢建議的內容供應器完整實作方式:

Kotlin

class MySuggestionProvider : SearchRecentSuggestionsProvider() {
    init {
        setupSuggestions(AUTHORITY, MODE)
    }

    companion object {
        const val AUTHORITY = "com.example.MySuggestionProvider"
        const val MODE: Int = SearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES
    }
}

Java

public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
    public final static String AUTHORITY = "com.example.MySuggestionProvider";
    public final static int MODE = DATABASE_MODE_QUERIES;

    public MySuggestionProvider() {
        setupSuggestions(AUTHORITY, MODE);
    }
}

呼叫 setupSuggestions() 會傳遞搜尋授權單位名稱和資料庫模式。搜尋授權可以是任何不重複的字串,但最佳做法是使用內容供應器的完整名稱,例如套件名稱,後面加上供應器的類別名稱。例如 "com.example.MySuggestionProvider"

資料庫模式必須包含 DATABASE_MODE_QUERIES,並視需要加入 DATABASE_MODE_2LINES,以便在建議表格中新增資料欄,讓您可以針對每個建議提供第二行文字。如果您想要在每項建議中提供兩行資訊,請參閱以下範例:

Kotlin

const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES

Java

public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;

透過在 SearchRecentSuggestionsProvider 類別和可搜尋設定中使用的授權字串,宣告應用程式資訊清單中的內容供應器。例如:

<application>
    <provider android:name=".MySuggestionProvider"
              android:authorities="com.example.MySuggestionProvider" />
    ...
</application>

修改可供搜尋的設定

如要設定系統使用建議供應程式,請在可搜尋的設定檔的 <searchable> 元素中,加入 android:searchSuggestAuthorityandroid:searchSuggestSelection 屬性。例如:

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

android:searchSuggestAuthority 的值必須是內容供應器的完整名稱,且必須與內容供應器中使用的授權完全相符,例如上述範例中的 "com.example.MySuggestionProvider"

android:searchSuggestSelection 的值必須是在後方加上空格的單一問號:" ?"。這是 SQLite 選取引數的預留位置,且會自動替換為使用者輸入的查詢文字。

儲存查詢

如要填入近期查詢的集合,請將可搜尋活動收到的每個查詢新增至 SearchRecentSuggestionsProvider。如要這麼做,請建立 SearchRecentSuggestions 的執行個體,並在每次可搜尋的活動收到查詢時呼叫 saveRecentQuery()。舉例來說,以下是如何在活動的 onCreate() 方法期間儲存查詢:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

    if (Intent.ACTION_SEARCH == intent.action) {
        intent.getStringExtra(SearchManager.QUERY)?.also { query ->
            SearchRecentSuggestions(this, MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE)
                    .saveRecentQuery(query, null)
        }
    }
}

Java

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

    Intent intent  = getIntent();

    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
                MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
        suggestions.saveRecentQuery(query, null);
    }
}

SearchRecentSuggestionsProvider 建構函式需要與內容供應器宣告的授權和資料庫模式相同。

saveRecentQuery() 方法接受搜尋查詢字串做為第一個參數,並視需要加入第二個字串 (可選擇加入為建議第二行或空值)。只有在您透過 DATABASE_MODE_2LINES 啟用搜尋建議雙行模式時,才能使用第二個參數。如果啟用雙行模式,系統就會在尋找相符的建議時,將查詢文字與第二行進行比對。

清除建議資料

為保護使用者隱私,請務必提供使用者清除近期查詢建議的方式。如要清除查詢記錄,請呼叫 clearHistory()。例如:

Kotlin

SearchRecentSuggestions(this, HelloSuggestionsProvider.AUTHORITY, HelloSuggestionsProvider.MODE)
        .clearHistory()

Java

SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
        HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);
suggestions.clearHistory();

選擇「清除搜尋記錄」選單項目、偏好設定項目或按鈕執行這個動作。提供確認對話方塊,確認使用者要刪除自己的搜尋記錄。