使用車輛行駛狀態和使用者體驗限制

本頁面說明應用程式如何順利轉換至專注最佳化 (DO) 使用者介面。說明如何使用車輛的駕駛狀態,以及相應的使用者體驗限制。如要進一步瞭解車輛使用者體驗 (UX) 限制,請參閱「車輛使用者體驗限制」,其中詳細說明三種行車狀態:停車、怠速和行駛。

目標對象

這份內容適用於想要設計可因應車輛行駛狀態變化和相應的使用者體驗限制的應用程式。

技術詳細資料

CarDrivingStateManager

車輛的駕駛狀態 (停車、空轉或移動) 是根據車輛硬體抽象層 (VHAL) 提供的感應器值而定。系統會使用基本感應器資訊 (例如車速和目前的檔位),推斷車輛目前的行駛狀態。

CarDrivingStateEvent

提供 @SystemApis,表示只有平台內部、已組合 APK (例如 SysUI 或設定) 和特權 APK (例如 GMSCore) 可以存取 API。這些 API 受到駕駛狀態 android.car.permission.CAR_DRIVING_STATE 專屬權限的保護。需要存取行車狀態資訊的用戶端必須要求這項權限。

CarUxRestrictionsManager

顯示依駕駛狀態而異的使用者介面時,應用程式必須監聽 CarUxRestrictionsManager,這項元素會將駕駛狀態與使用者體驗限制對應起來,讓應用程式不必根據不同的市場安全規定進行調整。

注意:這些活動「必須」標示為已針對分心程度進行最佳化,如駕駛人分心程度指南所述。如果活動未標示為適當,就會遭到封鎖。

相反地,應用程式會監控 CarUxRestrictionsManager 公開的限制,而非 CarDrivingStateManager 公開的絕對駕駛狀態,以便監控與使用者介面或使用者體驗相關的任何內容。

程式碼範例

以下程式碼範例說明應用程式如何監控使用者體驗限制:

  1. 匯入 Car 程式庫套件:
    import android.car.Car;
    /* For CarUxRestrictions */
    import android.car.drivingstate.CarUxRestrictions;
    import android.car.drivingstate.CarUxRestrictionsManager;
  2. 實作 CarUxRestrictionManager.OnUxRestrictionsChangedListener (mUxRChangeListener)。當使用者介面限制發生變更時,如果此事件監聽器已註冊至 CarUxRestrictionsManager,系統就會呼叫這個事件監聽器。視需要處理限制變更,以便最佳化分心程度:
    @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. 呼叫 Car 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());

CarUxRestrictions

CarUxRestrictions 物件提供兩種資訊:

  1. 目前是否有要求要最佳化分心程度?
  2. 如果是,目前有哪些限制?

getCurrentUxRestrictions() 或事件監聽器回呼取得 CarUxRestrictions 後,應用程式現在可以使用 isRequiresDistractionOptimization() API 判斷是否需要啟用 Distraction Optimization。如果傳回 false,就不需要進行分心因素最佳化,應用程式也可以安全地執行任何活動。

如果需要最佳化,請使用 getActiveRestrictions() API 取得已實施的限制組合。這個 API 會傳回 int,這是目前所有有效限制的位元遮罩。 CarUxRestrictions 下方會列出目前通知的限制條件組合。

注意:我們預計近期會對這組限制進行些微調整。

舉例來說,如果應用程式想要判斷是否存在播放影片的限制,則在取得 CarUxRestrictions 物件時,應用程式必須檢查限制:

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

DrivingState

CarDrivingStateManager 會顯示車輛的實際行駛狀態 (停車、空轉或移動)。CarDrivingStateManager API 的呼叫方式與 CarUxRestrictionsManager 類似。應用程式可以註冊事件監聽器或取得目前行駛狀態。駕駛狀態會以 CarDrivingStateEvent 的形式傳回。

CarDrivingStateEvent

變更時,系統會使用新的 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 殼層指令注入車輛事件。這項做法在開發和測試時相當實用。

如要模擬行車事件,請按照下列步驟操作:

  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