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

כדאי לנסות את הדרך של כתיבת אימייל
‫Jetpack Compose היא ערכת הכלים המומלצת לבניית ממשק משתמש ל-Android. כך מוסיפים פונקציית חיפוש בכלי הכתיבה.

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

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

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

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

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

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

כדי לספק הצעות בהתאמה אישית, פועלים לפי השלבים הבאים:

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

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

כשהמערכת מזהה שהפעילות שלכם ניתנת לחיפוש ומציעה הצעות לחיפוש, התהליך הבא מתרחש כשהמשתמש מזין שאילתה:

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

אחרי שההצעות המותאמות אישית מוצגות, יכול לקרות אחד מהדברים הבאים:

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

שינוי ההגדרה של מה שאפשר לחפש

כדי להוסיף תמיכה בהצעות מותאמות אישית, מוסיפים את המאפיין android:searchSuggestAuthority לרכיב <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.MyCustomSuggestionProvider">
</searchable>

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

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

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

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

בקטעים הבאים מוסבר איך ליצור ספק תוכן להצעות מותאמות אישית:

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

טיפול בשאילתת ההצעה

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

סיכום הפרמטרים שהמערכת מעבירה לשיטה query(), לפי הסדר:

  1. uri

    תמיד תוכן Uri, בפורמט הבא:

    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY
    

    התנהגות ברירת המחדל היא שהמערכת מעבירה את ה-URI הזה ומצרפת אליו את טקסט השאילתה:

    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY/puppies
    

    טקסט השאילתה בסוף מקודד באמצעות כללי קידוד URI, ולכן יכול להיות שתצטרכו לפענח אותו לפני שתבצעו חיפוש.

    החלק optional.suggest.path נכלל ב-URI רק אם הגדרתם נתיב כזה בקובץ התצורה שניתן לחיפוש באמצעות המאפיין android:searchSuggestPath. המאפיין הזה נדרש רק אם אתם משתמשים באותו ספק תוכן לכמה פעילויות שאפשר לחפש. אם זה המצב, צריך להסיר את הדו-משמעות ממקור שאילתת ההצעה.

  2. projection
    תמיד null.
  3. selection
    הערך שצוין במאפיין android:searchSuggestSelection של קובץ התצורה שאפשר לחפש בו, או null אם לא הצהרתם על המאפיין android:searchSuggestSelection. הנושא הזה מוסבר בהרחבה בקטע הבא.
  4. selectionArgs
    מכיל את שאילתת החיפוש כרכיב הראשון והיחיד במערך אם מצהירים על מאפיין android:searchSuggestSelection בהגדרה של החיפוש. אם לא מצהירים על android:searchSuggestSelection, הפרמטר הזה יהיה null. בקטע הבא נרחיב על כך.
  5. sortOrder
    תמיד null.

המערכת יכולה לשלוח לכם את הטקסט של שאילתת החיפוש בשתי דרכים. דרך ברירת המחדל היא לכלול את טקסט השאילתה כנתיב האחרון של ה-URI של התוכן שמועבר בפרמטר uri. עם זאת, אם כוללים ערך בחירה במאפיין android:searchSuggestSelection של ההגדרה שאפשר לחפש בה, טקסט השאילתה מועבר כרכיב הראשון של מערך המחרוזות selectionArgs. שתי האפשרויות האלה מתוארות בהמשך.

קבלת השאילתה ב-Uri

כברירת מחדל, השאילתה מצורפת כפלח האחרון של הפרמטר uri – אובייקט Uri. כדי לאחזר את טקסט השאילתה במקרה הזה, משתמשים ב-getLastPathSegment(), כמו בדוגמה הבאה:

Kotlin

val query: String = uri.lastPathSegment.toLowerCase()

Java

String query = uri.getLastPathSegment().toLowerCase();

הפונקציה מחזירה את הפלח האחרון של Uri, שהוא טקסט השאילתה שהמשתמש מזין.

קבלת השאילתה בארגומנטים של הבחירה

במקום להשתמש ב-URI, יכול להיות שיהיה הגיוני יותר שהשיטה query() תקבל את כל מה שהיא צריכה כדי לבצע את החיפוש, ושהפרמטרים selection ו-selectionArgs יכילו את הערכים המתאימים. במקרה כזה, מוסיפים את המאפיין android:searchSuggestSelection להגדרות שניתן לחפש בהן באמצעות מחרוזת הבחירה של SQLite. במחרוזת הבחירה, כוללים סימן שאלה (?) כ-placeholder לשאילתת החיפוש בפועל. המערכת קוראת ל-query() עם מחרוזת הבחירה כפרמטר selection ועם שאילתת החיפוש כרכיב הראשון במערך selectionArgs.

לדוגמה, כך אפשר ליצור את המאפיין android: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.MyCustomSuggestionProvider"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:searchSuggestSelection="word MATCH ?">
</searchable>

בהגדרה הזו, השיטה query() מעבירה את הפרמטר selection כ-"word MATCH ?" ואת הפרמטר selectionArgs כשאילתת החיפוש. כשמעבירים אותם לשיטה של SQLite‏ query() כארגומנטים המתאימים, הם עוברים סינתזה יחד – כלומר, סימן השאלה מוחלף בטקסט של השאילתה. אם אתם מקבלים שאילתות להצעות בדרך הזו ואתם צריכים להוסיף תווים כלליים לטקסט של השאילתה, אתם יכולים להוסיף אותם כקידומת או כסיומת לפרמטר selectionArgs, כי הערך הזה מוקף במירכאות ומוכנס במקום סימן השאלה.

מאפיין נוסף בדוגמה שלמעלה הוא android:searchSuggestIntentAction, שמגדיר את פעולת הכוונה שנשלחת עם כל כוונה כשהמשתמש בוחר הצעה. הנושא הזה מוסבר בהרחבה בקטע הצהרה על כוונת הצעות.

יצירת טבלת הצעות

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

המערכת מבינה כמה עמודות, אבל רק שתיים מהן הן חובה:

_ID
מזהה שורה ייחודי של מספר שלם לכל הצעה. המערכת דורשת את זה כדי להציג הצעות בListView.
SUGGEST_COLUMN_TEXT_1
המחרוזת שמוצגת כהצעה.

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

SUGGEST_COLUMN_TEXT_2
מחרוזת. אם הגיליון האלקטרוני Cursor כולל את העמודה הזו, כל ההצעות מוצגות בפורמט של שתי שורות. המחרוזת בעמודה הזו מוצגת כשורה שנייה קטנה יותר של טקסט מתחת לטקסט של ההצעה הראשית. אפשר להשאיר את הערך null או ריק כדי לציין שאין טקסט משני.
SUGGEST_COLUMN_ICON_1
מחרוזת URI של משאב, תוכן או קובץ שאפשר לצייר. אם הגיליון האלקטרוני שלכם, Cursor, כולל את העמודה הזו, כל ההצעות מוצגות בפורמט של סמל וטקסט, כשהסמל ניתן לציור בצד ימין. הערך בשדה הזה יכול להיות null או אפס כדי לציין שאין סמל בשורה הזו.
SUGGEST_COLUMN_ICON_2
מחרוזת URI של משאב, תוכן או קובץ שאפשר לצייר. אם הגיליון האלקטרוני שלכם Cursor כולל את העמודה הזו, כל ההצעות מוצגות בפורמט של סמל וטקסט, כשהסמל מופיע בצד שמאל. הערך בשדה הזה יכול להיות null או אפס אם לא רוצים להציג סמל בשורה הזו.
SUGGEST_COLUMN_INTENT_ACTION
מחרוזת של פעולת Intent. אם העמודה הזו קיימת ומכילה ערך בשורה הנתונה, הפעולה שמוגדרת כאן משמשת ליצירת הכוונה של ההצעה. אם לא מציינים את הרכיב, הפעולה מתבצעת מהשדה android:searchSuggestIntentAction בהגדרות החיפוש. אם הפעולה זהה לכל ההצעות, עדיף לציין את הפעולה באמצעות android:searchSuggestIntentAction ולהשמיט את העמודה הזו.
SUGGEST_COLUMN_INTENT_DATA
מחרוזת של URI של נתונים. אם העמודה הזו קיימת ומכילה ערך בשורה הנתונה, הנתונים האלה משמשים ליצירת כוונת ההצעה. אם לא מציינים את הרכיב, הנתונים נלקחים מהשדה android:searchSuggestIntentData בהגדרה שלכם לחיפוש. אם לא מסופק אף אחד מהמקורות, שדה הנתונים של הכוונה הוא null. אם הנתונים זהים לכל ההצעות, או שאפשר לתאר אותם באמצעות חלק קבוע ומזהה ספציפי, עדיף לציין אותם באמצעות android:searchSuggestIntentData ולהשמיט את העמודה הזו.
SUGGEST_COLUMN_INTENT_DATA_ID
מחרוזת של נתיב URI. אם העמודה הזו קיימת ומכילה ערך בשורה הנתונה, המערכת מוסיפה את הערך הזה לשדה הנתונים בכוונת המשתמש, אחרי התו '/'. משתמשים בזה רק אם שדה הנתונים שצוין במאפיין android:searchSuggestIntentData בהגדרה של החיפוש כבר מוגדר למחרוזת בסיס מתאימה.
SUGGEST_COLUMN_INTENT_EXTRA_DATA
נתונים שרירותיים. אם העמודה הזו קיימת ומכילה ערך בשורה מסוימת, אלה הנתונים הנוספים שמשמשים ליצירת כוונת ההצעה. אם לא מספקים נתונים, שדה הנתונים הנוספים של הכוונה הוא null. בעמודה הזו אפשר לראות הצעות עם נתונים נוספים שכלולים כתוספת במפתח EXTRA_DATA_KEY של הכוונה.
SUGGEST_COLUMN_QUERY
אם העמודה הזו קיימת והרכיב הזה קיים בשורה הנתונה, אלה הנתונים שמשמשים ליצירת השאילתה של ההצעה, והם נכללים כתוספת במפתח QUERY של הכוונה. הוא נדרש אם הפעולה של ההצעה היא ACTION_SEARCH, אבל אופציונלי בכל מקרה אחר.
SUGGEST_COLUMN_SHORTCUT_ID
בשימוש רק כשמספקים הצעות לתיבת החיפוש המהיר. העמודה הזו מציינת אם צריך לאחסן הצעה לחיפוש כקיצור דרך ואם צריך לאמת אותה. קיצורי דרך נוצרים בדרך כלל כשהמשתמש מקיש על הצעה מתיבת החיפוש המהיר. אם הוא חסר, התוצאה נשמרת כקיצור דרך ולא מתרעננת אף פעם. אם המדיניות מוגדרת לערך SUGGEST_NEVER_MAKE_SHORTCUT, התוצאה לא נשמרת כקיצור דרך. אחרת, מזהה קיצור הדרך משמש כדי לבדוק אם יש הצעה עדכנית באמצעות SUGGEST_URI_PATH_SHORTCUT.
SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING
בשימוש רק כשמספקים הצעות לתיבת החיפוש המהיר. העמודה הזו מציינת שצריך להציג סימן גרפי שמתבצעת פעולה במקום סמל מ-SUGGEST_COLUMN_ICON_2 בזמן שהקיצור של ההצעה הזו מתעדכן בתיבת החיפוש המהיר.

בקטעים הבאים מוסבר על רוב העמודות האלה.

הצהרה על כוונה להצעות

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

הצהרה על פעולת ה-Intent

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

בהתאם לשאלה אם רוצים שכל ההצעות ישתמשו באותה פעולת כוונה, אפשר להגדיר את הפעולה בשתי דרכים:

  • משתמשים במאפיין android:searchSuggestIntentAction של קובץ ההגדרות שניתן לחיפוש כדי להגדיר את הפעולה לכל ההצעות, כמו בדוגמה הבאה:
    <?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.MyCustomSuggestionProvider"
        android:searchSuggestIntentAction="android.intent.action.VIEW" >
    </searchable>
  • בעמודה SUGGEST_COLUMN_INTENT_ACTION מגדירים את הפעולה עבור כל הצעה. כדי לעשות את זה, מוסיפים את העמודה SUGGEST_COLUMN_INTENT_ACTION לטבלת ההצעות, ובכל הצעה מציינים את הפעולה שרוצים להשתמש בה, כמו "android.intent.action.VIEW".

אפשר גם לשלב בין שתי הטכניקות האלה. לדוגמה, אפשר לכלול את המאפיין android:searchSuggestIntentAction עם פעולה שתשמש כברירת מחדל לכל ההצעות, ואז לבטל את הפעולה הזו עבור חלק מההצעות על ידי הצהרה על פעולה אחרת בעמודה SUGGEST_COLUMN_INTENT_ACTION. אם לא מציינים ערך בעמודה SUGGEST_COLUMN_INTENT_ACTION, המערכת משתמשת בכוונת הרכישה שצוינה במאפיין android:searchSuggestIntentAction.

הצהרה על נתוני כוונות

כשהמשתמש בוחר הצעה, הפעילות שניתן לחפש בה מקבלת את הכוונה עם הפעולה שהגדרתם – כפי שמוסבר בקטע הקודם – אבל הכוונה צריכה גם לשאת נתונים כדי שהפעילות תוכל לזהות איזו הצעה נבחרה. הנתונים צריכים להיות ייחודיים לכל הצעה, כמו מזהה השורה של ההצעה בטבלת SQLite. כשמתקבלת הכוונה, אפשר לאחזר את הנתונים המצורפים באמצעות getData() או getDataString().

אפשר להגדיר את הנתונים שייכללו עם הכוונה בשתי דרכים:

  • מגדירים את הנתונים של כל הצעה בעמודה SUGGEST_COLUMN_INTENT_DATA בטבלת ההצעות.

    בטבלת ההצעות, מספקים את כל פרטי הנתונים הנדרשים לכל כוונת חיפוש. לשם כך, כוללים את העמודה SUGGEST_COLUMN_INTENT_DATA וממלאים אותה בנתונים ייחודיים לכל שורה. הנתונים מהעמודה הזו מצורפים לכוונת המשתמש בדיוק כמו שהיא מוגדרת בעמודה הזו. אחר כך תוכלו לאחזר אותו באמצעות getData() או getDataString().

  • מפצלים את URI של הנתונים לשני חלקים: החלק שמשותף לכל ההצעות והחלק שייחודי לכל הצעה. מציבים את החלקים האלה במאפיין android:searchSuggestintentData של ההגדרה שאפשר לחפש בה ובטור SUGGEST_COLUMN_INTENT_DATA_ID של טבלת ההצעות, בהתאמה.

    בדוגמה הבאה מוצג אופן ההצהרה על החלק ב-URI שמשותף לכל ההצעות במאפיין android:searchSuggestIntentData של ההגדרה שניתן לחפש בה:

      <?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.MyCustomSuggestionProvider"
          android:searchSuggestIntentAction="android.intent.action.VIEW"
          android:searchSuggestIntentData="content://com.example/datatable" >
      </searchable>
      

    בכל הצעה, צריך לכלול את הנתיב הסופי – החלק הייחודי – בעמודה SUGGEST_COLUMN_INTENT_DATA_ID בטבלת ההצעות. כשהמשתמש בוחר הצעה, המערכת לוקחת את המחרוזת מתוך android:searchSuggestIntentData, מוסיפה לוכסן (/), ואז מוסיפה את הערך המתאים מהעמודה SUGGEST_COLUMN_INTENT_DATA_ID כדי ליצור URI מלא של תוכן. אחר כך אפשר לאחזר את Uri באמצעות getData().

הוספת נתונים

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

טיפול בכוונה

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

Kotlin

when(intent.action) {
    Intent.ACTION_SEARCH -> {
        // Handle the normal search query case.
        intent.getStringExtra(SearchManager.QUERY)?.also { query ->
            doSearch(query)
        }
    }
    Intent.ACTION_VIEW -> {
        // Handle a suggestions click, because the suggestions all use ACTION_VIEW.
        showResult(intent.data)
    }
}

Java

Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
    // Handle the normal search query case.
    String query = intent.getStringExtra(SearchManager.QUERY);
    doSearch(query);
} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
    // Handle a suggestions click, because the suggestions all use ACTION_VIEW.
    Uri data = intent.getData();
    showResult(data);
}

בדוגמה הזו, פעולת הכוונה היא ACTION_VIEW והנתונים כוללים URI מלא שמפנה לפריט המוצע, כפי שסונתז על ידי המחרוזת android:searchSuggestIntentData והעמודה SUGGEST_COLUMN_INTENT_DATA_ID. מזהה ה-URI מועבר לשיטה showResult() המקומית שמבצעת שאילתה לספק התוכן לגבי הפריט שצוין על ידי מזהה ה-URI.

לשכתב את הטקסט של השאילתה

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

אפשר לנסח מחדש את טקסט השאילתה בדרכים הבאות:

  • מוסיפים את מאפיין android:searchMode להגדרה של החיפוש עם הערך "queryRewriteFromText". במקרה הזה, התוכן מהעמודה SUGGEST_COLUMN_TEXT_1 של ההצעה משמש לשכתוב הטקסט של השאילתה.
  • מוסיפים את המאפיין android:searchMode להגדרה של החיפוש עם הערך "queryRewriteFromData". במקרה הזה, התוכן מהעמודה SUGGEST_COLUMN_INTENT_DATA בהצעה משמש לשכתוב הטקסט של השאילתה. השתמשו בשיטה הזו רק עם מזהי URI או פורמטים אחרים של נתונים שנועדו להיות גלויים למשתמשים, כמו כתובות URL של HTTP. אל תשתמשו בסכימות פנימיות של מזהי URI כדי לשכתב את השאילתה בדרך הזו.
  • צריך לספק מחרוזת טקסט ייחודית של שאילתה בעמודה SUGGEST_COLUMN_QUERY של טבלת ההצעות. אם העמודה הזו קיימת ומכילה ערך להצעה הנוכחית, הערך הזה משמש לכתיבה מחדש של טקסט השאילתה ומבטל את אחת מההטמעות הקודמות.

הצגת הצעות לחיפוש בתיבת החיפוש המהיר

אחרי שמגדירים את האפליקציה כך שתספק הצעות חיפוש מותאמות אישית, אפשר להוסיף אותן לתיבת החיפוש המהיר שנגישה לכולם בקלות רבה. כל מה שצריך לעשות הוא לשנות את ההגדרה של החיפוש כך שתכלול את android:includeInGlobalSearch עם הערך "true".

התרחיש היחיד שבו נדרשת עבודה נוספת הוא כשספק התוכן דורש הרשאת קריאה. במקרה כזה, צריך להוסיף רכיב <path-permission> כדי שהספק ייתן לתיבת החיפוש המהיר הרשאת קריאה לספק התוכן, כמו בדוגמה הבאה:

<provider android:name="MySuggestionProvider"
          android:authorities="com.example.MyCustomSuggestionProvider"
          android:readPermission="com.example.provider.READ_MY_DATA"
          android:writePermission="com.example.provider.WRITE_MY_DATA">
  <path-permission android:pathPrefix="/search_suggest_query"
                   android:readPermission="android.permission.GLOBAL_SEARCH" />
</provider>

בדוגמה הזו, הספק מגביל את הגישה לקריאה ולכתיבה של התוכן. הרכיב <path-permission> משנה את ההגבלה בכך שהוא מעניק גישת קריאה לתוכן בתוך קידומת הנתיב "/search_suggest_query" אם קיימת ההרשאה "android.permission.GLOBAL_SEARCH". הפעולה הזו מעניקה גישה לתיבת החיפוש המהיר, כדי שהיא תוכל לשלוח שאילתות לספק התוכן שלכם ולקבל ממנו הצעות.

אם ספק התוכן לא אוכף הרשאות קריאה, תיבת החיפוש המהיר קוראת אותו כברירת מחדל.

הפעלת ההצעות במכשיר

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

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

<?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.MyCustomSuggestionProvider"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:includeInGlobalSearch="true"
    android:searchSettingsDescription="@string/search_description" >
</searchable>

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

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

ניהול קיצורי דרך להצעות בתיבת החיפוש המהיר

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

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

  • הגדרת תיבת החיפוש המהיר כך שתבצע שאילתה מחדש לספק התוכן כדי לקבל גרסה חדשה של קיצור הדרך להצעה.

    מזינים ערך בעמודה SUGGEST_COLUMN_SHORTCUT_ID כדי שההצעה תישאל מחדש לגבי גרסה עדכנית בכל פעם שמוצג קיצור הדרך. קיצור הדרך מוצג במהירות עם הנתונים העדכניים ביותר שזמינים עד שהשאילתה לרענון חוזרת, ואז ההצעה מתעדכנת עם המידע החדש. שאילתת הרענון נשלחת לספק התוכן עם נתיב URI של SUGGEST_URI_PATH_SHORTCUT במקום SUGGEST_URI_PATH_QUERY.

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

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

  • למנוע את ההעתקה של ההצעה לקיצור דרך.

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

  • החלת התנהגות ברירת המחדל של קיצור הדרך.

    משאירים את SUGGEST_COLUMN_SHORTCUT_ID ריק לכל הצעה שלא משתנה ואפשר לשמור אותה כקיצור דרך.

אם אף אחת מההצעות שלכם לא משתנה, אתם לא צריכים את העמודה SUGGEST_COLUMN_SHORTCUT_ID.

מידע על דירוג ההצעות בתיבת החיפוש המהיר

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