Android Automotive 認為,語音是消費者
確保使用者的安全
在行車期間與 Android Automotive OS 互動。因此,我們擴充了
Android 語音助理 API (包括 VoiceInteractionSession
)
讓語音助理可以為使用者執行工作
難以在開車時做到的事項
輕觸即可朗讀功能可讓語音助理在開啟及回覆簡訊時朗讀內容
(代表使用者與訊息通知互動時)。為了提供
,您可以將語音助理與
CarVoiceInteractionSession
。
在 Automotive 中,系統發現發布至通知中心的通知
本裝置:INBOX
或 INBOX_IN_GROUP
(例如簡訊) 包含
「播放」按鈕。使用者可以按一下「播放」選取
語音助理會朗讀通知內容,您也可以選擇透過語音回覆。
圖 1. 附有「播放」按鈕的輕觸閱讀通知。
與 CarVoiceInteractionSession 整合
以下各節將說明如何整合語音助理與語音助理。
CarVoiceInteractionSession
。
支援語音互動
提供車輛語音互動服務的應用程式必須
整合現有的 Android 語音互動功能詳情請參閱「Android 版 Google 助理」一文
(VoiceInteractionSession
除外)。雖然所有語音互動 API 都適用
元素與在行動裝置上實作 CarVoiceInteractionSession
的效果相同
(詳情請參閱「實作 CarVoiceInteractionSession」一文)
VoiceInteractionSession
。如需詳細資訊,請參閱以下頁面:
實作 CarVoiceInteractionSession
CarVoiceInteractionSession
將會揭露 API,您可以使用這些 API 讓語音助理朗讀文字訊息,
代使用者回覆這些訊息。
CarVoiceInteractionSession
和
這就是 VoiceInteractionSession
類別
CarVoiceInteractionSession
的「onShow
」動作票證
以便語音助理立即偵測使用者要求的背景資訊
CarVoiceInteractionSession
會啟動工作階段。onShow
的參數
請參閱下表:
CarVoiceInteractionSession | 語音互動工作階段 |
---|---|
onShow 會使用以下三個參數:
|
onShow 會使用以下兩個參數:
|
Android 10 的異動
從 Android 10 開始,平台會呼叫 VoiceInteractionService.onGetSupportedVoiceActions
偵測支援的動作語音助理會覆寫和
實作 VoiceInteractionService.onGetSupportedVoiceActions
,
如以下範例所示:
public class MyInteractionService extends VoiceInteractionService { private static final ListSUPPORTED_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 |
含鍵的 Parcelable。KEY_NOTIFICATION
對應至 StatusBarNotification 。需要 android.permission.BIND_NOTIFICATION_LISTENER_SERVICE 。 |
提示使用者撰寫回覆訊息,然後輸入回覆訊息
待處理意圖的 RemoteInputReply ,然後觸發
待處理意圖 |
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
、
此方法可從通知中擷取訊息,並寫入
回覆訊息至適當的待處理意圖。在
語音助理讀出訊息,則語音助理「必須」觸發 Mark
讀取意圖
「輕觸閱讀」先決條件符合要求
預設語音只有 VoiceInteractionSession
使用者觸發要朗讀的語音和訊息時,助理會收到通知
回覆訊息。如上所述,必須一併讓這個預設的語音助理
具備通知事件監聽器權限
序列圖
下圖顯示 CarVoiceInteractionSession actions
的邏輯流程:
圖 2. VOICE_ACTION_READ_NOTIFICATION 的循序圖。
以圖 3 為例,建議應用程式權限要求的頻率限制:
圖 3. VOICE_ACTION_REPLY_NOTIFICATION 的序列圖。
圖 4. VOICE_ACTION_HANDLE_EXCEPTION 的序列圖。
讀取應用程式名稱
如果希望語音助理在練習期間 訊息朗讀 (例如,「來自 Hangouts 的 Sam 表示了...」) 建立函式,如下所示 在以下程式碼範例中,確保 Google 助理讀取的是正確名稱:
@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; }