הקשה כדי לקרוא עם העוזר הקולי

ב-Android Automotive, הקול נחשב למרכיב חיוני לאינטראקציות בטוחות בזמן הנהיגה, ואחת הדרכים הבטוחות ביותר שבהן משתמשים יכולים לקיים אינטראקציה עם מערכת Android Automotive OS בזמן הנהיגה. כתוצאה מכך, הרחבנו את ממשקי ה-API של עוזרות הקול של Android (כולל VoiceInteractionSession) כדי לאפשר לעוזרות הקול לבצע עבור המשתמשים משימות שקשה לבצע בזמן הנהיגה.

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

ב-Automotive, התראות שפורסמו במרכז ההתראות ומסומנות בתווית INBOX או INBOX_IN_GROUP (למשל, הודעות SMS) כוללות לחצן הפעלה. המשתמש יכול ללחוץ על הפעלה כדי שהעוזרת הקולית שנבחרה תקריא את ההתראה, וגם להשיב לה באמצעות הקול.

התראה עם אפשרות הקשה לקריאה

איור 1. התראה עם לחצן הפעלה להקשה כדי לקרוא.

שילוב עם CarVoiceInteractionSession

בקטעים הבאים מוסבר איך לשלב עוזרת קול עם CarVoiceInteractionSession.

תמיכה באינטראקציות קוליות

אפליקציות שמספקות שירותי אינטראקציה קולית ברכב חייבות לשלב את עצמן עם האינטראקציות הקוליות הקיימות ב-Android. למידע נוסף, ראו Google Assistant ל-Android (למעט VoiceInteractionSession). כל הרכיבים של Voice Interaction API נשארים זהים לאלה שמופעלים במכשירים ניידים, אבל CarVoiceInteractionSession (המתואר בקטע הטמעת CarVoiceInteractionSession) מחליף את VoiceInteractionSession. מידע נוסף זמין בדפים הבאים:

הטמעת CarVoiceInteractionSession

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

ההבדל העיקרי בין הכיתות CarVoiceInteractionSession ו-VoiceInteractionSession הוא ש-CarVoiceInteractionSession מעביר את הפעולה ב-onShow כדי שעוזר הקול יוכל לזהות את ההקשר של הבקשה של המשתמש ברגע ש-CarVoiceInteractionSession מתחיל סשן. הפרמטרים של onShow לכל כיתה מפורטים בטבלה הבאה:

CarVoiceInteractionSession VoiceInteractionSession
onShow מקבל את שלושת הפרמטרים הבאים:
  • args
  • showFlags
  • actions
onShow מקבל את שני הפרמטרים הבאים:
  • args
  • showFlags

שינויים ב-Android 10

החל מ-Android 10, הפלטפורמה קוראת ל-VoiceInteractionService.onGetSupportedVoiceActions כדי לזהות אילו פעולות נתמכות. העוזרת הקולית מבטלת את VoiceInteractionService.onGetSupportedVoiceActions ומטמיעה אותה, כפי שמוצג בדוגמה הבאה:

public class MyInteractionService extends VoiceInteractionService {
    private static final List SUPPORTED_VOICE_ACTIONS = Arrays.asList(
        CarVoiceInteractionSession.VOICE_ACTION_READ_NOTIFICATION);

    @Override
    public Set onGetSupportedVoiceActions(@NonNull Set voiceActions) {
       Set result = new HashSet<>(voiceActions);
       result.retainAll(SUPPORTED_VOICE_ACTIONS);
       return result;
   }
}

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

פעולה עומס נתונים צפוי הפעולה הצפויה של האינטראקציה הקולית
VOICE_ACTION_READ_NOTIFICATION קוראים את ההודעות למשתמש, ואז מפעילים את הכוונה 'סימון כהודעה שנקראה' חזרה כשההודעות נקראו בהצלחה. אפשר גם לבקש מהמשתמש להשיב.
VOICE_ACTION_REPLY_NOTIFICATION ניתן לחלק למקטעים עם מפתח.
KEY_NOTIFICATION שממופה אל StatusBarNotification.
נדרשת android.permission.BIND_NOTIFICATION_LISTENER_SERVICE.
מבקשים מהמשתמש לומר את הודעת התשובה, מזינים את הודעת התשובה בשדה RemoteInputReply של ה-intent בהמתנה ואז מפעילים את ה-intent בהמתנה.
VOICE_ACTION_HANDLE_EXCEPTION מחרוזת עם מפתח.
KEY_EXCEPTION שממופה לערך ExceptionValue (מתואר בקטע ערכים חריגים).
KEY_FALLBACK_ASSISTANT_ENABLED שממופה לערך בוליאני. אם הערך הוא true, אסיסטנט החלופות שיכול לטפל בבקשה של המשתמש הושבת.
הפעולה הצפויה שצריך לבצע לגבי החריגה מוגדרת במסמכי התיעוד של החריגה.

ערכים חריגים

EXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING מציין לעוזרת הקולית שחסרה לה ההרשאה Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE, ומבקש לקבל את ההרשאה הזו מהמשתמש.

שליחת בקשה להרשאת מאזין להתראות

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

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

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

עבודה עם StatusBarNotification

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

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

עמידה בתנאי הקבלה של 'הקשה כדי לקרוא'

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

דיאגרמות רצף

בתרשים הבא מוצגים תהליכי הלוגיקה של CarVoiceInteractionSession actions:

VOICE_ACTION_READ_NOTIFICATION

איור 2. תרשים רצף של VOICE_ACTION_READ_NOTIFICATION.

במקרה של איור 3, מומלץ להשתמש באפליקציה עם הגבלת קצב של בקשות הרשאה:

VOICE_ACTION_REPLY_NOTIFICATION

איור 3. תרשים רצף של VOICE_ACTION_REPLY_NOTIFICATION.

VOICE_ACTION_HANDLE_EXCEPTION

איור 4. תרשים רצף של VOICE_ACTION_HANDLE_EXCEPTION.

קריאת שם האפליקציה

אם אתם רוצים שהעוזרת הקולית תקריא את שם אפליקציית ההודעות בקול רם במהלך הקריאה של ההודעה (לדוגמה, "דני מ-Hangouts אמר…"), תוכלו ליצור פונקציה כמו זו שמוצגת בדוגמת הקוד הבאה כדי לוודא שהעוזרת קורא את השם הנכון:

@Nullable
String getMessageApplicationName(Context context, StatusBarNotification statusBarNotification) {
    ApplicationInfo info = getApplicationInfo(context, statusBarNotification.getPackageName());
    if (info == null) return null;

    Notification notification = statusBarNotification.getNotification();

    // Sometimes system packages will post on behalf of other apps, so check this
    // field for a system app notification.
    if (isSystemApp(info)
            && notification.extras.containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)) {
        return notification.extras.getString(Notification.EXTRA_SUBSTITUTE_APP_NAME);
    } else {
        PackageManager pm = context.getPackageManager();
        return String.valueOf(pm.getApplicationLabel(info));
    }
}

@Nullable
ApplicationInfo getApplicationInfo(Context context, String packageName) {
    final PackageManager pm = context.getPackageManager();
    ApplicationInfo info;
    try {
        info = pm.getApplicationInfo(packageName, 0);
    } catch (PackageManager.NameNotFoundException e) {
        return null;
    }
    return info;
}

boolean isSystemApp(ApplicationInfo info) {
    return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}