消費汽車駕駛狀態和用戶體驗限制

本文解釋了應用程序如何優雅地過渡到分心優化 (DO) 用戶界面。它描述瞭如何消費汽車的駕駛狀態以及相應的用戶體驗限制。有關汽車用戶體驗 (UX) 限制規則的更多信息,請參閱汽車用戶體驗限制,其中詳細介紹了停車、怠速和行駛中的三種駕駛狀態。

觀眾

此內容是為那些想要設計適應汽車駕駛狀態變化和相應施加的用戶體驗限制的應用程序的人提供的。

技術細節

汽車駕駛狀態管理器

汽車的駕駛狀態(停車、怠速或行駛)源自車輛硬件抽象層 (VHAL) 提供的傳感器值。基本傳感器信息,例如車速和當前檔位選擇,用於得出車輛的當前駕駛狀態。

此信息通過提供 @SystemApis 的CarDrivingStateManager向特權客戶端公開,這意味著只有 Platform Internals、捆綁的 APK(例如 SysUI 或 Settings)和 Privileged APK(例如)GMSCore 可以訪問 API。 API 受特定於駕駛狀態android.car.permission.CAR_DRIVING_STATE的權限的保護。需要訪問駕駛狀態信息的客戶必須請求此權限。

CarUxRestrictionsManager

那些根據駕駛狀態顯示用戶界面的應用程序必須監聽CarUxRestrictionsManager ,它抽象了從駕駛狀態到 UX 限制的映射,因此應用程序無需針對不同的市場安全要求進行調整。

注意:這些活動必須標記為 DistractionOptimized,如駕駛員分心指南中所述。如果活動沒有相應地標記,它們將被阻止。

相反,應用程序監視 CarUxRestrictionsManager 公開的限制,而不是 CarDrivingStateManager 公開的與用戶界面或用戶體驗相關的任何內容的絕對駕駛狀態。

代碼示例

以下示例代碼說明了應用程序如何監控 UX 限制:

  1. 導入汽車庫包:
    import android.car.Car;
    /* For CarUxRestrictions */
    import android.car.drivingstate.CarUxRestrictions;
    import android.car.drivingstate.CarUxRestrictionsManager;
    
  2. 實現CarUxRestrictionManager.OnUxRestrictionsChangedListener ( mUxRChangeListener )。這個監聽器一旦註冊到CarUxRestrictionsManager ,就會在 UX 限制發生變化時被調用。根據需要處理限制更改以優化分心:
    @Nullable private CarUxRestrictionsManager mCarUxRestrictionsManager;
    private CarUxRestrictions mCurrentUxRestrictions;
    
    /* Implement the onUxRestrictionsChangedListener interface */
    private CarUxRestrictionsManager.OnUxRestrictionsChangedListener mUxrChangeListener =
                new CarUxRestrictionsManager.OnUxRestrictionsChangedListener()
        {
            @Override
            public void onUxRestrictionsChanged(CarUxRestrictions carUxRestrictions) {
            mCurrentUxRestrictions = carUxRestrictions;
            /* Handle the new restrictions */
            handleUxRestrictionsChanged(carUxRestrictions);
            }
        };
      
  3. 調用汽車 API 創建一個名為 mCar 的汽車實例並連接到汽車服務:
    mCar = Car.createCar(context);
    if (mCar == null) {
    // handle car connection error
    }
    
  4. 調用mCar.getCarManager() - mCarUxRestrictionsManager以獲取CarUxRestrictionsManager
    CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
    mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
    
  5. 使用CarUxRestrictionsManager調用mCarUxRestrictionsManager.registerListener()註冊上面第 2 步中實現的mUxRChangeListener
    mCarUxRestrictionsManager.registerListener(mUxrChangeListener);
    mUxrChangeListener.onUxRestrictionsChanged(
    mCarUxRestrictionsManager.getCurrentCarUxRestrictions());
    

完整的示例代碼塊(在步驟 3 到步驟 5 中創建)導致偵聽器在驅動器狀態更改時接收限制更改:

mCar = Car.createCar(context);
if (mCar == null) {
// handle car connection error
}

CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);

mCarUxRestrictionsManager.registerListener(mUxrChangeListener);
mUxrChangeListener.onUxRestrictionsChanged(
mCarUxRestrictionsManager.getCurrentCarUxRestrictions());

CarUx 限制

CarUxRestrictions對象提供兩種類型的信息:

  1. 當前是否有分散注意力優化的要求?
  2. 如果是這樣,目前有哪些限制?

getCurrentUxRestrictions()或偵聽器回調獲得CarUxRestrictions後,應用程序現在可以使用isRequiresDistractionOptimization() API 來確定是否需要 Distraction Optimized。如果返回 false,則不需要進行分心優化,應用程序可以安全地運行任何活動。

如果需要優化,則使用getActiveRestrictions() API 來獲取適當的限制集。此 API 返回一個int,它是當前有效的所有限制的位掩碼。當前通知的一組限制列在CarUxRestrictions下。

注意:預計在不久的將來會發生對限制集的微小更改。

例如,如果應用程序想要確定是否存在播放視頻的限制,則在獲取 CarUxRestrictions 對像後,應用程序必須檢查該限制:

int activeUxR = mCurrentCarUxRestrictions.getActiveRestrictions();
if ((activeUxR & CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO) != 0) {
      handleStopPlayingVideo();
}

駕駛狀態

CarDrivingStateManager 呈現車輛的實際駕駛狀態(停車、怠速或移動)。 CarDrivingStateManager API 的調用方式與 CarUxRestrictionsManager 類似。應用程序可以註冊一個監聽器和/或獲取當前的駕駛狀態。駕駛狀態作為 CarDrivingStateEvent 返回。

與 CarUxRestrictionsManager API 類似,客戶端可以使用registerListener()為駕駛狀態註冊一個監聽器,並傳遞CarDrivingStateEventListener的實現。在駕駛狀態發生變化時,將使用新的CarDrivingStateEvent調用 onDrivingStateChanged() 方法。

import android.car.Car;
/* For CarDrivingState */
import android.car.drivingstate.CarDrivingStateEvent;
import android.car.drivingstate.CarDrivingStateManager;

mDrivingStateManager = (CarDrivingStateManager) mCar.getCarManager(
       Car.CAR_DRIVING_STATE_SERVICE);
/* Register the listener (implemented below) */
mDrivingStateManager.registerListener(mDrivingStateEventListener);
/* While we wait for a change to be notified, query the current state */
mDrivingStateEvent = mDrivingStateManager.getCurrentCarDrivingState();

private final CarDrivingStateManager.CarDrivingStateEventListener
mDrivingStateEventListener =
       new CarDrivingStateManager.CarDrivingStateEventListener() {
   @Override
   public void onDrivingStateChanged(CarDrivingStateEvent event) {
       mDrivingStateEvent = event;
       /* handle the state change accordingly */
       handleDrivingStateChange();
   }
};

測試

您可以模仿檔位和速度的變化來改變駕駛狀態。使用 ADB shell 命令注入車輛事件。這可能是有用的開發和測試。

模擬駕駛事件:

  1. 將速度設置為 0:
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 0
    
  2. 將檔位設置為 Parked(模擬 CarDrivingStateEvent 指向 PARKED):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 4
    
  3. 將檔位設置為 Drive,速度仍為 0(模擬 CarDrivingStateEvent 指向 IDLING):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 8
    
  4. 將速度設置為每秒 30 米(模擬 CarDrivingStateEvent 指向 MOVING):
    adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 30