פיתוח אפליקציות

כדי להטמיע אפליקציית אינטראקציה קולית (VIA), מבצעים את השלבים הבאים:

  1. יוצרים שלד של VIA.
  2. (אופציונלי) מטמיעים תהליך הגדרה או כניסה.
  3. (אופציונלי) הטמעה של מסך הגדרות.
  4. צריך להצהיר על ההרשאות הנדרשות בקובץ המניפסט.
  5. הטמעת ממשק משתמש של לוחית הקול.
  6. להטמיע זיהוי קולי (חייב לכלול הטמעת API של RecognitionService).
  7. מטמיעים את ההקראה (אופציונלי, אפשר להטמיע את TextToSpeech API).
  8. להטמיע מילוי הזמנות של פקודות. הצגת התוכן הזה ב מילוי פקודות.

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

יצירת שלד של VIA

מניפסטים

האפליקציה מזוהה כאפליקציה עם 'אינטראקציה קולית' במקרים הבאים: נכללות במניפסט:

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myvoicecontrol">
    ...

  <application ... >
    <service android:name=".MyInteractionService"
        android:label="@string/app_name"
        android:permission="android.permission.BIND_VOICE_INTERACTION"
        android:process=":interactor">
      <meta-data
          android:name="android.voice_interaction"
          android:resource="@xml/interaction_service" />
      <intent-filter>
        <action android:name=
          "android.service.voice.VoiceInteractionService" />
      </intent-filter>
    </service>
  </application>
</manifest>

בדוגמה הזו:

  • סרטונים ב-VIA חייבים לחשוף שירות שאורכו VoiceInteractionService, עם מסנן Intent לפעולה VoiceInteractionService.SERVICE_INTERFACE ("android.service.voice.VoiceInteractionService").
  • השירות הזה חייב להחזיק בהרשאת חתימת המערכת BIND_VOICE_INTERACTION.
  • השירות הזה צריך לכלול קובץ מטא-נתונים מסוג android.voice_interaction כדי לכלול את הפרטים הבאים:

    res/xml/interaction_service.xml

    <voice-interaction-service
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:sessionService=
          "com.example.MyInteractionSessionService"
        android:recognitionService=
          "com.example.MyRecognitionService"
        android:settingsActivity=
          "com.example.MySettingsActivity"
        android:supportsAssist="true"
        android:supportsLaunchVoiceAssistFromKeyguard="true"
        android:supportsLocalInteraction="true" />
    

לפרטים על כל שדה: R.styleable#VoiceInteractionService. מאחר שכל סרטוני ה-VIA הם גם שירותי זיהוי קול, עליך גם יש לכלול את הפרטים הבאים במניפסט:

AndroidManifest.xml

<manifest ...>
  <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  <application ...>
    ...
    <service android:name=".RecognitionService" ...>
      <intent-filter>
        <action android:name="android.speech.RecognitionService" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
      <meta-data
        android:name="android.speech"
        android:resource="@xml/recognition_service" />
    </service>
  </application>
</manifest>

לשירותי זיהוי קולי נדרשים גם את המטא-נתונים הבאים:

res/xml/recognition_service.xml

<recognition-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:settingsActivity="com.example.MyRecognizerSettingsActivity" />

VoiceInteractionService, VoiceInteractionSessionService ו-VoiceInteractionSession

בתרשים הבא מוצג מחזור החיים של כל אחת מהישויות האלה:

מחזורי חיים

איור 1. מחזורי חיים

כמו שצוין קודם, נקודת הכניסה היא VoiceInteractionService ל-VIA. תחומי האחריות העיקריים של שירות זה הם:

  • אתחול תהליכים שאמורים להמשיך לפעול כל עוד ה-VIA הזה הוא ה-VIA הפעיל. לדוגמה, זיהוי מילות הפעלה.
  • דוחות לגבי פעולות קוליות נתמכות (מידע נוסף זמין במאמר בנושא הקשה לקריאה של Assistant באמצעות הקול).
  • הפעלת סשנים של אינטראקציה קולית ממסך הנעילה (KeyGuard).

בצורה הפשוטה ביותר, הטמעה של VoiceInteractionService תיראה כך:

public class MyVoiceInteractionService extends VoiceInteractionService {
    private static final List<String> SUPPORTED_VOICE_ACTIONS =
        Arrays.asList(
            CarVoiceInteractionSession.VOICE_ACTION_READ_NOTIFICATION,
            CarVoiceInteractionSession.VOICE_ACTION_REPLY_NOTIFICATION,
            CarVoiceInteractionSession.VOICE_ACTION_HANDLE_EXCEPTION
    );

    @Override
    public void onReady() {
        super.onReady();
        // TODO: Setup hotword detector
    }

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

ההטמעה של VoiceInteractionService#onGetSupportedVoiceActions() היא נדרש כדי לטפל הקשה לקריאה של Assistant באמצעות הקול. המערכת משתמשת ב-VoiceInteractionSessionService כדי ליצור מקיים אינטראקציה עם VoiceInteractionSession. יש לו רק אחריות אחת, כדי להתחיל סשנים חדשים כשיתבקשו לעשות זאת.

public class MyVoiceInteractionSessionService extends VoiceInteractionSessionService {
    @Override
    public VoiceInteractionSession onNewSession(Bundle args) {
        return new MyVoiceInteractionSession(this);
    }
}

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

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {

    public InteractionSession(Context context) {
        super(context);
    }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        closeSystemDialogs();
        // TODO: Unhide UI and update UI state
        // TODO: Start processing audio input
    }
    ...
}

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

הטמעת תהליך הגדרה או כניסה

תהליך ההגדרה וכניסה לחשבון עשוי להתרחש:

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

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

הגדרה במהלך החלפת שירות קולי

המשתמש תמיד יוכל לבחור VIA שלא פעל כראוי מוגדר. הסיבה לכך יכולה להיות:

  • המשתמש דילג לגמרי על אשף ההגדרה או שהמשתמש דילג על הקול שלב הגדרת האינטראקציה.
  • המשתמש בחר VIA שונה מזה שהוגדר במכשיר בתהליך ההצטרפות.

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

  • תזכורת התראה.
  • מענה קולי אוטומטי כשהמשתמש מנסה להשתמש בו.

הערה: מומלץ מאוד לא להציג תהליך הגדרה של VIA. ללא בקשה מפורשת ממשתמש. כלומר, עליכם להימנע מהצגת VIA באופן אוטומטי הצגת תוכן ב-HU במהלך הפעלת המכשיר או כתוצאה מהחלפת משתמש או לביטול הנעילה.

תזכורת על התראה

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

תזכורת על התראה

איור 2. תזכורת על התראה

כך התהליך יעבוד:

תהליך תזכורת להתראות

איור 3. תהליך תזכורת להתראות

תשובה קולית

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

הגדרה לפי השימוש הראשון

המשתמש תמיד יכול להפעיל VIA שלא פעל כראוי מוגדר. במקרים כאלה:

  1. יידע את המשתמש על כך בעל פה (לדוגמה, "כדי לעבוד כראוי, אבקש ממך לבצע כמה שלבים... ").
  2. אם המנוע להגבלות על חוויית המשתמש מאפשר זאת (ראו UX_LIMITIONS_NO_Setup), צריך לשאול את המשתמש אם הוא רוצה להפעיל תהליך ההגדרה ופתיחת מסך ההגדרות של VIA.
  3. אחרת (לדוגמה, אם המשתמש נוהג), יש להשאיר התראה למשתמש ללחוץ על האפשרות כשניתן לעשות זאת בצורה בטוחה.

יצירת מסכי הגדרה של אינטראקציה קולית

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

הנחיות כלליות:

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

מסך של הטמעת הגדרות

שילוב ההגדרות

איור 4. שילוב ההגדרות

מסכי ההגדרות הם פעילויות רגילות ב-Android. אם היא מוטמעת, נקודת הכניסה שלהם חייבת להצהיר ב-res/xml/interaction_service.xml כחלק מ-VIA מניפסטים (ראו מניפסטים). הקטע 'הגדרות' הוא מקום טוב להמשיך בהגדרה ובכניסה לחשבון (אם המשתמש לא השלים את התהליך ) או מציעים אפשרות של יציאה או החלפת משתמש במקרה הצורך. דומה לתהליך ההגדרה במסכים שתוארו למעלה, המסכים הבאים צריכים:

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

להצהיר על ההרשאות הנדרשות בקובץ המניפסט

ניתן לחלק את ההרשאות הנדרשות ל-VIA לשלוש קטגוריות:

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

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

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

מבקשים הרשאות כחלק ממסך ההגדרה

נדרשות הרשאות מסוכנות באמצעות השיטה ActivityCompat#requestPermission() הרגילה (או מקבילה). למידע נוסף על בקשת הרשאות, אפשר לעיין במאמר מבקשים הרשאות לאפליקציה.

בקשת הרשאות

איור 5. בקשת הרשאות

הרשאת האזנה להתראות

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

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

private void requestNotificationListenerAccess() {
    Intent intent = new Intent(Settings
        .ACTION_NOTIFICATION_LISTENER_SETTINGS);
    intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
    startActivity(intent);
}

הטמעת ממשק משתמש של לוחית הקול

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

הצגה של לוחית הקול

איור 6. הצגה של לוחית הקול

יש שתי דרכים להטמיע את ממשק המשתמש הזה:

  • שינוי VoiceInteractionSession#onCreateContentView()
  • התחלת פעילות באמצעות VoiceInteractionSession#startAssistantActivity()

שימוש ב-onCreateContentView()

זוהי הדרך המוגדרת כברירת מחדל להצגת לוחית קול. VoiceInteractionSession מחלקה בסיסית יוצרת חלון ומנהלת את מחזור החיים שלו כל עוד קול לא מזמן. אפליקציות חייבות לשנות את VoiceInteractionSession#onCreateContentView() ולהחזיר תצוגה שמצורפת לחלון הזה ברגע שהסשן נוצר. בשלב הראשון התצוגה צריכה להיות מוסתרת. כשמתחילה אינטראקציה קולית, התצוגה הזו צריכה להיות גלויה ב-VoiceInteractionSession#onShow() ואז בלתי נראה בחזרה בתאריך VoiceInteractionSession#onHide().

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {
    private View mVoicePlate;
    …

    @Override
    public View onCreateContentView() {
        mVoicePlate = inflater.inflate(R.layout.voice_plate, null);
        …
   }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        // TODO: Update UI state to "listening"
        mVoicePlate.setVisibility(View.VISIBLE);
    }

    @Override
    public void onHide() {
        mVoicePlate.setVisibility(View.GONE);
    }
    …
}

אם משתמשים בשיטה הזו, כדאי לשנות את הערך של VoiceInteractionSession#onComputeInsets() כדי להביא בחשבון אזורים מוסתרים בממשק המשתמש.

שימוש ב-startAssistantActivity()

במקרה הזה, VoiceInteractionSession יאציל/ה הרשאה לנהל את הקול ועל ממשק המשתמש של הלוחית לפעילות רגילה. כשמשתמשים באפשרות הזו, VoiceInteractionSession חייבת להשבית את היצירה של חלון התוכן שמוגדר כברירת המחדל (מידע נוסף זמין בקטע שימוש ב-onCreateContentView()) בonPrepareShow() קריאה חוזרת. בשעה VoiceInteractionSession#onShow(), הקול יופעל בסשן פעילות של לוחית הרישוי באמצעות VoiceInteractionSession#startAssistantActivity(). הזה הפקודה מפעילה את ממשק המשתמש עם הגדרות החלון ודגלי הפעילות המתאימים.

public class MyVoiceInteractionSession extends CarVoiceInteractionSession {
    …

    @Override
    public void onPrepareShow(Bundle args, int showFlags) {
        super.onPrepareShow(args, showFlags);
        setUiEnabled(false);
    }

    @Override
    protected void onShow(String action, Bundle args, int showFlags) {
        closeSystemDialogs();
        Intent intent = new Intent(getContext(), VoicePlateActivity.class);
        intent.putExtra(VoicePlateActivity.EXTRA_ACTION, action);
        intent.putExtra(VoicePlateActivity.EXTRA_ARGS, args);
        startAssistantActivity(intent);
    }

    …
}

כדי לשמור על תקשורת בין הפעילות הזו לבין VoiceInteractionSession, קבוצה של מנגנוני Intent או קישורי שירות פנימיים עשויים להיות נדרש. לדוגמה, כשמפעילים את VoiceInteractionSession#onHide(), חייבים להיות מסוגלים להעביר את הבקשה לפעילות.

חשוב: בכלי רכב, רק עם הערות מיוחדות פעילויות או פעילויות שמפורטות ב'רשימת ההיתרים' של UXR ניתן להציג בזמן נהיגה. הקטגוריה הזו חלה על פעילויות שהתחילו ב- VoiceInteractionSession#startAssistantActivity() גם כן. חשוב לזכור להוסיף הערות לפעילות שלך עם <meta-data android:name="distractionOptimized" android:value="true"/> או לכלול את זה פעילות במפתח systemActivityWhitelist של /packages/services/Car/service/res/values/config.xml חדש. מידע נוסף זמין במאמר נהג/ת הנחיות בנושא הסחות דעת.

הטמעת זיהוי קולי

בחלק זה תלמדו כיצד ליישם זיהוי קולי באמצעות וזיהוי של מילות הפעלה. מילת הפעלה היא מילת הפעלה שמשמשת ליצירת שאילתה חדשה או פעולה קולית. לדוגמה, "Ok Google" או Ok Google.

זיהוי מילת הפעלה של DSP

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

  • יצירת אובייקט של AlwaysOnHotwordDetector.
  • רישום של מודל צליל לזיהוי מילת הפעלה.

הטמעת VoiceInteractionService יכולה ליצור מזהה מילות הפעלה באמצעות VoiceInteractionService#createAlwaysOnHotwordDetector(), להעביר את ביטוי המפתח ואת הלוקאל שבו הם רוצים להשתמש לצורך זיהוי. כתוצאה מכך, האפליקציה מקבלת onAvailabilityChanged() קריאה חוזרת (callback) עם אחד מהערכים האפשריים הבאים:

  • STATE_HARDWARE_UNAVAILABLE יכולת DSP לא זמינה במכשיר. במקרה הזה, נעשה שימוש בזיהוי של מילת ההפעלה בתוכנה.
  • STATE_HARDWARE_UNSUPPORTED באופן כללי אין תמיכה ב-DSP, אבל DSP לא תומך בשילוב נתון של ביטוי מפתח ולוקאל. האפליקציה יכולה להשתמש זיהוי של מילת הפעלה.
  • STATE_HARDWARE_ENROLLED זיהוי המילה החמה מוכן ואפשר להתחיל אותו על ידי קריאה ל-method startRecognition().
  • STATE_HARDWARE_UNENROLLED מודל צליל עבור ביטוי המפתח המבוקש אינו אבל אפשר להירשם.

ניתן לבצע רישום של מודלים של צלילים לזיהוי מילות הפעלה באמצעות IVoiceInteractionManagerService#updateKeyphraseSoundModel(). ניתן לרשום במערכת כמה מודלים בכל פעם, אבל רק אחד מהם. משויך ל-AlwaysOnHotwordDetector. יכול להיות שזיהוי מילת ההפעלה של DSP לא יהיה זמין בכל המכשירים. מפתחים שמשתמשים ב-VIA צריך לבדוק את יכולות החומרה באמצעות getDspModuleProperties() . לקוד לדוגמה שמוצג איך לרשום מודלים של צלילים: VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java. אפשר לעיין בקטע תיעוד בו-זמנית בנוגע זיהוי בו-זמנית של מילת הפעלה.

זיהוי מילת הפעלה בתוכנה

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

שני הקבועים האלה הם @hide וזמינים רק לאפליקציות בחבילה.

ניהול קלט אודיו וזיהוי קולי

קלט האודיו יוטמע באמצעות סיווג MediaRecorder. מידע נוסף על אופן השימוש ב-API הזה אפשר למצוא ב-MediaRecorder סקירה כללית שירותי האינטראקציה הקולית צפויים גם להיות RecognitionService של המחלקה. כל אפליקציה במערכת שדורשת זיהוי קולי משתמשת ב כדי לגשת ליכולת הזאת. כדי לבצע זיהוי קולי ולקבל גישה למיקרופון, VIA חייב להכיל android.permission.RECORD_AUDIO. אפליקציות שיש להן גישה ל-RecognitionService צריכים להחזיק גם בהרשאה הזו.

לפני Android 10, גישה למיקרופון ניתנה רק לאפליקציה אחת בכל (למעט זיהוי של מילת הפעלה, עיינו למעלה). החל מ-Android 10. ניתן לשתף את הגישה למיקרופון. לקבלת מידע נוסף, ראה שיתוף קלט אודיו.

גישה לפלט האודיו

כשה-VIA מוכן לתת תשובות מילוליות, חשוב ריכזנו כאן כמה הנחיות: