自 2025 年 3 月 27 日起,我們建議您使用 android-latest-release
而非 aosp-main
建構及貢獻 AOSP。詳情請參閱「Android 開放原始碼計畫變更」。
使用車輛行駛狀態和使用者體驗限制
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
本頁面說明應用程式如何順利轉換至專注最佳化 (DO) 使用者介面。說明如何使用車輛的駕駛狀態,以及相應的使用者體驗限制。如要進一步瞭解車輛使用者體驗 (UX) 限制,請參閱「車輛使用者體驗限制」,其中詳細說明三種行車狀態:停車、怠速和行駛。
目標對象
這份內容適用於想要設計可因應車輛行駛狀態變化和相應的使用者體驗限制的應用程式。
技術詳細資料
CarDrivingStateManager
車輛的駕駛狀態 (停車、空轉或移動) 是根據車輛硬體抽象層 (VHAL) 提供的感應器值而定。系統會使用基本感應器資訊 (例如車速和目前的檔位),推斷車輛目前的行駛狀態。
CarDrivingStateEvent
。
提供 @SystemApis,表示只有平台內部、已組合 APK (例如 SysUI 或設定) 和特權 APK (例如 GMSCore) 可以存取 API。這些 API 受到駕駛狀態
android.car.permission.CAR_DRIVING_STATE
專屬權限的保護。需要存取行車狀態資訊的用戶端必須要求這項權限。
CarUxRestrictionsManager
顯示依駕駛狀態而異的使用者介面時,應用程式必須監聽 CarUxRestrictionsManager
,這項元素會將駕駛狀態與使用者體驗限制對應起來,讓應用程式不必根據不同的市場安全規定進行調整。
注意:這些活動「必須」標示為已針對分心程度進行最佳化,如駕駛人分心程度指南所述。如果活動未標示為適當,就會遭到封鎖。
相反地,應用程式會監控 CarUxRestrictionsManager 公開的限制,而非 CarDrivingStateManager 公開的絕對駕駛狀態,以便監控與使用者介面或使用者體驗相關的任何內容。
程式碼範例
以下程式碼範例說明應用程式如何監控使用者體驗限制:
- 匯入 Car 程式庫套件:
import android.car.Car;
/* For CarUxRestrictions */
import android.car.drivingstate.CarUxRestrictions;
import android.car.drivingstate.CarUxRestrictionsManager;
- 實作
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);
}
};
- 呼叫 Car API 來建立名為 mCar 的車輛執行個體,並連線至車輛服務:
mCar = Car.createCar(context);
if (mCar == null) {
// handle car connection error
}
- 呼叫
mCar.getCarManager() - mCarUxRestrictionsManager
即可取得 CarUxRestrictionsManager
:CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
- 如要使用
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 物件提供兩種資訊:
- 目前是否有要求要最佳化分心程度?
- 如果是,目前有哪些限制?
從 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 殼層指令注入車輛事件。這項做法在開發和測試時相當實用。
如要模擬行車事件,請按照下列步驟操作:
- 如要將速度設為 0:
adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 0
- 如要將齒輪設為「Parked」(模擬 CarDrivingStateEvent 指向「PARKED」):
adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 4
- 如要將變速箱設為「Drive」,速度仍為 0 (模擬 CarDrivingStateEvent 指向 IDLING):
adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 8
- 如要將速度設為每秒 30 公尺 (模擬 CarDrivingStateEvent 指向 MOVING):
adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 30
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# Consume car driving state and UX restrictions\n\nThis page explains how apps can transition gracefully to distraction\noptimized (DO) user interfaces. It describes how to consume a car's driving state as well as the\ncorresponding user experience restrictions.\n\nFor more information about Car User Experience (UX) restrictions, see\n[Car User Experience Restrictions](/docs/automotive/driver_distraction/car_uxr),\nwhich details the three driving states of Parked, Idling, and Moving.\n\nAudience\n--------\n\nThis content is provided for those who want to design apps that adapt to changes in a\ncar's driving state and the correspondingly imposed UX restrictions.\n\nTechnical details\n-----------------\n\n### CarDrivingStateManager\n\nA car's driving state (Parked, Idling, or Moving) is derived from the sensor values provided by\nthe Vehicle Hardware Abstraction Layer (VHAL). Basic sensor information, such as vehicle speed and\ncurrent gear selection, is used to derive the vehicle's current driving state.\n[CarDrivingStateEvent](https://android.googlesource.com/platform/packages/services/Car/+/android16-release/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java?autodive=0%2F%2F%2F%2F%2F).\n\n\u003cbr /\u003e\n\nwhich provides @SystemApis, meaning that only Platform Internals, Bundled APKs (such as SysUI or Settings), and Privileged APKs (such as) GMSCore can access the APIs. The APIs are protected by permissions specific to driving state `android.car.permission.CAR_DRIVING_STATE`. Clients that require access to driving state information must request this permission.\n\n\u003cbr /\u003e\n\n### CarUxRestrictionsManager\n\nThose apps that display a user interface dependent upon driving state must listen to\n[CarUxRestrictionsManager](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictionsManager),\nwhich abstracts the mapping from driving state to UX restrictions so that apps don't need to\nadjust for different market safety requirements.\n\n**Note** : These activities *must* be marked as\ndistraction optimized, as described\nin [Driver distraction guidelines](/docs/automotive/driver_distraction/guidelines).\nIf the activities aren't marked accordingly, they're blocked.\n\nInstead, apps monitor restrictions exposed by the CarUxRestrictionsManager and not an\nabsolute driving state exposed by the CarDrivingStateManager for anything related to the user\ninterface or the user experience.\n\nCode sample\n-----------\n\nThe following sample code illustrates how an app monitors UX restrictions:\n\n1. Import the car library packages: \n\n ```python\n import android.car.Car;\n /* For CarUxRestrictions */\n import android.car.drivingstate.CarUxRestrictions;\n import android.car.drivingstate.CarUxRestrictionsManager;\n ```\n2. Implement `CarUxRestrictionManager.OnUxRestrictionsChangedListener` (`mUxRChangeListener`). This listener, when registered with the [CarUxRestrictionsManager](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictionsManager), is called when a change in the UX restrictions occurs. Handle the restriction changes to be distraction optimized, as needed: \n\n ```transact-sql\n @Nullable private CarUxRestrictionsManager mCarUxRestrictionsManager;\n private CarUxRestrictions mCurrentUxRestrictions;\n\n /* Implement the onUxRestrictionsChangedListener interface */\n private CarUxRestrictionsManager.OnUxRestrictionsChangedListener mUxrChangeListener =\n new CarUxRestrictionsManager.OnUxRestrictionsChangedListener()\n {\n @Override\n public void onUxRestrictionsChanged(CarUxRestrictions carUxRestrictions) {\n mCurrentUxRestrictions = carUxRestrictions;\n /* Handle the new restrictions */\n handleUxRestrictionsChanged(carUxRestrictions);\n }\n };\n \n ```\n3. Call the car APIs to create a car instance named mCar and connect to the car service: \n\n ```text\n mCar = Car.createCar(context);\n if (mCar == null) {\n // handle car connection error\n }\n ```\n4. Call `mCar.getCarManager() - mCarUxRestrictionsManager` to get the `CarUxRestrictionsManager`: \n\n ```scdoc\n CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)\n mCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);\n ```\n5. To register `mUxRChangeListener` implemented in Step 2 above with the `CarUxRestrictionsManager` call `mCarUxRestrictionsManager.registerListener()`: \n\n ```verilog\n mCarUxRestrictionsManager.registerListener(mUxrChangeListener);\n mUxrChangeListener.onUxRestrictionsChanged(\n mCarUxRestrictionsManager.getCurrentCarUxRestrictions());\n ```\n\nThe completed block of sample code (created in Step 3 through Step 5) results in the listener\nreceiving restriction changes when the drive state changes: \n\n```verilog\nmCar = Car.createCar(context);\nif (mCar == null) {\n// handle car connection error\n}\n\nCarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)\nmCar.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);\n\nmCarUxRestrictionsManager.registerListener(mUxrChangeListener);\nmUxrChangeListener.onUxRestrictionsChanged(\nmCarUxRestrictionsManager.getCurrentCarUxRestrictions());\n```\n\nCarUxRestrictions\n-----------------\n\nThe [CarUxRestrictions](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions) object provides two types of information:\n\n1. Is there a current requirement to be distraction optimized?\n2. If so, what restrictions are currently in place?\n\nWhen [CarUxRestrictions](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions) is obtained from either\n[getCurrentUxRestrictions()](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictionsManager.html#getCurrentCarUxRestrictions()) or the listener callback, apps can now use\nthe [isRequiresDistractionOptimization()](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions.html#isRequiresDistractionOptimization()) API to determine if Distraction\nOptimized\nis required. If this returns `false`, there is no requirement to be Distraction\nOptimized and an app can safely run any activity.\n\nIf optimization is required, then use the [getActiveRestrictions()](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions.html#getActiveRestrictions()) API to obtain the set of restrictions in place. This\nAPI returns an *int* , which is a bit mask of all the restrictions currently in effect. The\nset of restrictions currently notified is listed under ` `[CarUxRestrictions](https://developer.android.com/reference/android/car/drivingstate/CarUxRestrictions).\n\n**Note:** Minor changes to the set of restrictions are anticipated to\noccur in the near future.\n\nFor example, if an app wants to determine if a restriction to play video exists, upon\ngetting the CarUxRestrictions object, the app must check for the restriction: \n\n```scdoc\nint activeUxR = mCurrentCarUxRestrictions.getActiveRestrictions();\nif ((activeUxR & CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO) != 0) {\n handleStopPlayingVideo();\n}\n```\n\nDrivingState\n------------\n\nCarDrivingStateManager presents the actual driving state of the vehicle (Parked, Idling, or\nMoving). CarDrivingStateManager APIs can be called similar to the CarUxRestrictionsManager.\nApps can register a listener or get current driving state. The driving state is returned\nas CarDrivingStateEvent.\n[CarDrivingStateEvent](https://android.googlesource.com/platform/packages/services/Car/+/android16-release/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java?autodive=0%2F%2F%2F%2F%2F).\n\n\u003cbr /\u003e\n\nchanges, the `onDrivingStateChanged()` method is called with the new [CarDrivingStateEvent](https://android.googlesource.com/platform/packages/services/Car/+/android16-release/car-lib/src/android/car/drivingstate/CarDrivingStateEvent.java?autodive=0%2F%2F%2F%2F%2F).\n\n\u003cbr /\u003e\n\n```python\nimport android.car.Car;\n/* For CarDrivingState */\nimport android.car.drivingstate.CarDrivingStateEvent;\nimport android.car.drivingstate.CarDrivingStateManager;\n\nmDrivingStateManager = (CarDrivingStateManager) mCar.getCarManager(\n Car.CAR_DRIVING_STATE_SERVICE);\n/* Register the listener (implemented below) */\nmDrivingStateManager.registerListener(mDrivingStateEventListener);\n/* While we wait for a change to be notified, query the current state */\nmDrivingStateEvent = mDrivingStateManager.getCurrentCarDrivingState();\n\nprivate final CarDrivingStateManager.CarDrivingStateEventListener\nmDrivingStateEventListener =\n new CarDrivingStateManager.CarDrivingStateEventListener() {\n @Override\n public void onDrivingStateChanged(CarDrivingStateEvent event) {\n mDrivingStateEvent = event;\n /* handle the state change accordingly */\n handleDrivingStateChange();\n }\n};\n```\n\nTesting\n-------\n\nYou can mimic the changing of gears and speed to change the driving state. Use an ADB shell\ncommand to inject vehicle events. This can be useful development and testing.\n\nTo simulate driving events:\n\n1. To set speed to 0: \n\n ```text\n adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 0\n ```\n2. To set gear to Parked (to simulate CarDrivingStateEvent pointing to PARKED): \n\n ```text\n adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 4\n ```\n3. To set gear to Drive, with speed still at 0 (to simulate CarDrivingStateEvent pointing to IDLING): \n\n ```text\n adb shell dumpsys activity service com.android.car inject-vhal-event 0x11400400 8\n ```\n4. To set speed to 30 meters per second (to simulate CarDrivingStateEvent pointing to MOVING): \n\n ```text\n adb shell dumpsys activity service com.android.car inject-vhal-event 0x11600207 30\n ```"]]