הוספת הצעות לחיפוש בהתאמה אישית

אפשר להציג הצעות חיפוש על סמך שאילתות חיפוש אחרונות בתיבת הדו-שיח של חיפוש ב-Android או ווידג'ט החיפוש. לדוגמה, אם משתמש שולח שאילתה ל"גורים", השאילתה מופיעה כהצעה מקלידים את אותה השאילתה שוב. באיור 1 מוצגת דוגמה לתיבת דו-שיח של חיפוש עם השאילתה האחרונה הצעות.

לפני שמתחילים, צריך להטמיע את תיבת הדו-שיח לחיפוש או ווידג'ט חיפוש לחיפושים בסיסיים באפליקציה שלכם. כדי ללמוד איך עושים זאת, אפשר לעיין יוצרים ממשק חיפוש.

העקרונות הבסיסיים

איור 1. צילום מסך של תיבת דו-שיח של חיפוש עם השאילתה האחרונה הצעות.

הצעות אחרונות לשאילתות הן חיפושים שמורים. כשהמשתמש יבחר הצעה, הפרמטר יוכל לחיפוש הפעילות מקבלת Intent של ACTION_SEARCH בהצעה בתור שאילתת החיפוש שבה כבר מטפלת הפעילות שלך בחיפוש.

כדי לספק הצעות לשאילתות אחרונות:

  • להטמיע פעילות שניתנת לחיפוש.
  • יצירת ספק תוכן עם נפח אחסון מורחב SearchRecentSuggestionsProvider ולהצהיר עליו במניפסט של האפליקציה.
  • משנים את התצורה שניתנת לחיפוש באמצעות מידע על ספק התוכן שמספק הצעות לחיפוש.
  • לשמור שאילתות בספק התוכן בכל פעם שמתבצע חיפוש.

בדיוק כמו שמערכת Android מציגה את תיבת הדו-שיח של החיפוש, כך מוצגות גם ההצעות לחיפוש למטה לווידג'ט של תיבת הדו-שיח או החיפוש. מציינים את המקור שממנו המערכת מאחזרת את ההצעות.

כשהמערכת מזהה שהפעילות שלכם ניתנת לחיפוש ומספקת הצעות לחיפוש, קורה כאשר המשתמש מקליד שאילתה:

  1. המערכת לוקחת את הטקסט של שאילתת החיפוש — כל מה שהמשתמש מתחיל להקליד — וגם שולח שאילתה לספק התוכן שמכיל את ההצעות שלכם.
  2. ספק התוכן שלך מחזיר Cursor שמצביע לכולם הצעות שתואמות לטקסט של שאילתת החיפוש.
  3. המערכת מציגה את רשימת ההצעות שסופקו על ידי Cursor.

יכול להיות שזה יקרה אחרי שההצעות האחרונות לשאילתות יוצגו:

  • אם המשתמש מקליד מפתח אחר או משנה את השאילתה בדרך כלשהי, השלבים הקודמים הם חוזר על עצמו ורשימת ההצעות מתעדכנת.
  • אם המשתמש מבצע את החיפוש, המערכת מתעלמת מההצעות והחיפוש מועבר אל את הפעילות שלך הניתנת לחיפוש באמצעות הכוונה הרגילה של ACTION_SEARCH.
  • אם המשתמש בוחר הצעה, Intent מסוג ACTION_SEARCH מועבר אל פעילות שניתן לחפש באמצעות הטקסט המוצע כשאילתה.

הכיתה SearchRecentSuggestionsProvider שהורחבה לספק התוכן עושה את העבודה באופן אוטומטי בשלבים הקודמים, כך שלא צריך לכתוב קוד בכלל.

יצירת ספק תוכן

ספק התוכן הדרוש לך כדי לקבל הצעות אחרונות לשאילתות הוא יישום של SearchRecentSuggestionsProvider הכיתה הזו עושה את כל מה שצריך. צריך רק לכתוב constructor של מחלקות שמריץ שורת קוד אחת.

לדוגמה, הנה הטמעה מלאה של ספק תוכן לשאילתה האחרונה הצעות:

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>

שינוי התצורה שניתנת לחיפוש

כדי להגדיר את המערכת לשימוש בספק ההצעות, מוסיפים את android:searchSuggestAuthority ו-android:searchSuggestSelection לרכיב <searchable> בקובץ התצורה שניתן לחפש. עבור דוגמה:

<?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 חייב להיות סימן שאלה אחד לפניו במרחב משותף: " ?". זהו placeholder לארגומנט הבחירה של SQLite, מוחלף אוטומטית בטקסט השאילתה שהמשתמש הזין.

שמירת השאילתות

כדי לאכלס את אוסף השאילתות האחרונות, צריך להוסיף כל שאילתה שהתקבלה בחיפוש פעילות ל-SearchRecentSuggestionsProvider שלך. כדי לעשות את זה, יוצרים מופע של SearchRecentSuggestions ולהתקשר saveRecentQuery() בכל פעם שפעילות החיפוש שלך מקבלת שאילתה. לדוגמה, כך אפשר לשמור את השאילתה במהלך הפעילות onCreate() method:

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);
    }
}

ה-constructor של SearchRecentSuggestionsProvider דורש אותו סמכות ומצב מסד נתונים שהוצהר על ידי ספק התוכן.

השיטה saveRecentQuery() מתייחסת למחרוזת של שאילתת החיפוש כפרמטר הראשון ובאופן אופציונלי, מחרוזת שנייה שצריך לכלול כשורה השנייה של ההצעה, או ערך null. השנייה משתמשים בפרמטר הזה רק אם מפעילים את מצב שתי שורות עבור הצעות החיפוש עם DATABASE_MODE_2LINES אם מפעילים את מצב שתי השורות, הטקסט של השאילתה תואם כאשר המערכת מחפשת הצעות תואמות.

ניקוי נתוני ההצעות

כדי להגן על פרטיות המשתמש, תמיד צריך לספק לו דרך לנקות את השאילתה האחרונה הצעות. כדי לנקות את היסטוריית השאילתות, התקשר clearHistory() לדוגמה:

Kotlin

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

Java

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

יש לבצע זאת מתוך האפשרות 'ניקוי היסטוריית החיפושים' אפשרות בתפריט, אפשרות מועדפת או לחצן. לספק תיבת דו-שיח לאישור כדי לוודא שהמשתמש רוצה למחוק את היסטוריית החיפושים שלו.