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

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

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

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

התראה על הקש כדי לקרוא

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

השתלב עם CarVoiceInteractionSession

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

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

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

יישום CarVoiceInteractionSession

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

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

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

שינויים באנדרואיד 10

החל מאנדרואיד 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 של הכוונה הממתינה, ולאחר מכן הפעל את הכוונה הממתינה.
VOICE_ACTION_HANDLE_EXCEPTION מחרוזת עם מפתח.
KEY_EXCEPTION שממפה ל- ExceptionValue (מתואר ב- Exception values ).
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 , המספק שיטות לחלץ הודעות מההתראה ולכתוב את הודעות התשובה לכוונה הממתינה המתאימה של ההתראה. לאחר שהעוזר הקולי קורא את ההודעה, על העוזרת הקולית לירות את הכוונה סמן כקריאה.

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

רק 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.

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

אם אתה רוצה שהעוזר הקולי שלך יקרא בקול את השם של אפליקציית ההודעות במהלך קריאת ההודעות (לדוגמה, "Sam מ-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;
}