在停車時使用的應用程式中新增 Android Automotive OS 支援功能

將應用程式發布至 Android Automotive OS 裝置時,請留意一些板型規格特有的注意事項。本指南將說明這些考量。

在 Android Automotive OS 模擬器上測試現有應用程式

如要開始建構適用於 Android Automotive OS 的應用程式,請先在 Android Automotive OS 模擬器測試現有應用程式。如要設定模擬器,請按照「使用 Android Automotive OS 模擬器進行測試」的步驟操作,然後依據「在模擬器上執行應用程式」說明,執行應用程式。

執行應用程式時請留意相容性問題,例如:

  • 資訊娛樂系統的畫面為固定螢幕方向。為符合車用應用程式品質指南規定,應用程式必須同時支援直向和橫向螢幕方向。
  • 其他裝置適用的 API 可能不適用於 Android Automotive OS。舉例來說,Android Automotive OS 並不支援某些 Google Play 服務 API。如要進一步瞭解如何處理這些問題,請參閱「停用功能」一節。

設定應用程式的資訊清單檔案

應用程式必須含有特定的資訊清單項目,才能將 Android Automotive OS 裝置設為目標平台。選擇加入發布至 Android Automotive OS 裝置後,Google Play 會審查相容的應用程式,確保可在車上安全使用。詳情請參閱「發行至車輛」一文。

必要的 Android Automotive OS 功能

所有專為 Android Automotive OS 建構的應用程式,都必須符合特定規定,才能透過 Google Play 發布。詳情請參閱「符合 Google Play 功能規定」。

特定類別的資訊清單項目

除了上述適用於所有停車應用程式的規定外,影片和遊戲類別還有其他規定:

符合駕駛人分心等級規定

將應用程式導入車輛時,請務必避免駕駛人分心。對於停車時使用的應用程式,主要做法是在使用者體驗 (UX) 限制生效時,防止應用程式使用或播放音訊,如 DD-2 和 DD-3 品質指南所述。

在使用者體驗限制生效時禁止使用

根據預設,使用者體驗限制生效時,無法使用或啟動活動。為確保應用程式適用這項行為,資訊清單中的任何 <activity> 元素都不得包含下列 <meta-data> 元素:

<!-- NOT ALLOWED -->
<meta-data
  android:name="distractionOptimized"
  android:value="true"/>

如果使用者體驗限制啟動時,應用程式中的活動處於「已恢復」狀態,則會遭到作業系統擁有的活動遮蓋。

至少,應用程式的活動會轉換為暫停生命週期狀態。這項操作會以 onPause 生命週期回呼的方式進行,期間您必須暫停播放應用程式中的影片和音訊。

在搭載 Android Automotive OS 相容模式的裝置上,系統封鎖會導致應用程式活動從「暫停」狀態轉換為「已停止」狀態。

停止播放並防止繼續播放

對某些應用程式來說,只要在 onPause() 期間暫停播放,並追蹤狀態以防止在 onResume() 之前恢復播放,就足以符合駕駛人分心等級規定。

如果對生命週期回呼做出反應不足以滿足應用程式需求,您可以直接監聽使用者體驗限制狀態,如下一節所述。舉例來說,支援子母畫面的應用程式可能偏好直接監聽,而不是在生命週期回呼中進行條件檢查。

監聽使用者體驗限制

如要監聽使用者體驗限制,請先在應用程式模組的 build.gradle 檔案中,新增 android.car 程式庫的依附元件。這是 Android SDK 的擴充功能,提供 Android Automotive OS 專用的 API。

android {
    ...
    useLibrary("android.car")
}

使用 CarUxRestrictionsManager 讀取使用者體驗限制狀態。請勿嘗試從其他硬體狀態 (例如檔位或速度) 判斷使用者體驗限制狀態,因為車輛內各螢幕的使用者體驗限制可能不同。

val car = Car.createCar(context) ?: return
val carUxRestrictionsManager =
    car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE) as? CarUxRestrictionsManager ?: return

// You can either read the state directly ...
val currentUxRestrictions = carUxRestrictionsManager.currentCarUxRestrictions

// or listen to state changes
carUxRestrictionsManager.registerListener { carUxRestrictions: CarUxRestrictions ->
    // Handle UX restrictions
}

// Don't forget to teardown and release resources when they're no longer needed
carUxRestrictionsManager.unregisterListener()
car.disconnect()

CarUxRestrictions 提供的唯一值,也就是應用程式參照的值,是 isRequiresDistractionOptimization 的傳回值。其他值僅適用於標示為分心因素已排除的活動。

測試實作成果

請按照下列程序,驗證應用程式是否符合駕駛人分心等級規定:

  1. 在沒有 Google Play 商店或相容模式的系統映像檔上安裝應用程式。
  2. 開啟啟動器應用程式排列顯示,模擬駕駛,並確認應用程式無法開啟。
  3. 停止模擬行車狀態,開啟應用程式並前往播放畫面,然後開始播放。
  4. 再次模擬駕駛,確認播放暫停。
    1. 如果應用程式支援與 MediaSession 整合,請使用 adb shell cmd media_session dispatch play,並確認播放作業不會繼續。

為 Android Automotive OS 最佳化應用程式

為盡可能提供最佳車內體驗,建構 Android Automotive OS 應用程式時,請留意下列事項:

使用視窗插邊和螢幕凹口

與其他板型規格一樣,Android Automotive OS 包含系統 UI 元素,例如狀態列和導覽列,並支援非矩形螢幕。

根據預設,應用程式會在不與系統資訊列或螢幕凹口重疊的區域繪製。不過,您可能希望應用程式隱藏系統資訊列、在系統資訊列後方繪製內容,或在螢幕凹口中顯示內容,如「在視窗內嵌中設定應用程式版面配置」一文所述。如果您的應用程式會執行上述任何操作,請參閱下列子節,進一步瞭解如何讓應用程式在 Android Automotive OS 裝置生態系統中順利運作。

系統資訊列、沉浸模式和無邊框轉譯

車輛中的系統資訊列大小和位置,可能與其他板型規格不同。舉例來說,導覽列可能位於螢幕的左側、右側或底部。即使頂端有狀態列,底部有導覽列 (與大多數手機和平板電腦一樣),這些元素在車輛中的尺寸也可能大得多。

此外,Android Automotive OS 可讓原始設備製造商 (OEM) 控制應用程式是否能顯示或隱藏系統資訊列,以進入和退出沉浸模式。舉例來說,OEM 可以禁止應用程式隱藏系統資訊列,確保車輛控制項 (例如溫度控制項) 一律會顯示在螢幕上供隨時存取。如果原始設備製造商 (OEM) 禁止應用程式控制系統資訊列,則應用程式呼叫 WindowInsetsController (或 WindowInsetsControllerCompat) API 來顯示或隱藏系統資訊列時,不會發生任何動作。請參閱 show 和 hide 的說明文件,進一步瞭解如何偵測應用程式是否能修改插邊。

同樣地,原始設備製造商 (OEM) 也可以控制應用程式是否能設定系統資訊列的顏色和半透明度,確保系統資訊列和其中包含的元素隨時清晰可見。如果應用程式採用無邊框設計,請確認只有非重要內容會繪製在系統資訊列後方。如果裝置原始設備製造商 (OEM) 禁止設定資訊列的顏色或半透明度,則可能無法顯示這項內容。

<!-- Depending on OEM configuration, these style declarations
     (and the corresponding runtime calls) may be ignored -->
<style name="...">
  <item name="android:statusBarColor">...</item>
  <item name="android:navigationBarColor">...</item>
  <item name="android:windowTranslucentStatus">...</item>
  <item name="android:windowTranslucentNavigation">...</status>
</style>

如果應用程式採用無邊框設計,請勿對系統資訊列的大小、數量、類型或位置做出假設。請改用視窗插邊 API,根據系統資訊列的位置,調整應用程式內容的版面配置。如要進一步瞭解如何使用這些 API,請參閱「在應用程式中以無邊框方式顯示內容」。我們不建議在任何板型規格中使用硬式編碼邊框間距值,但在車輛中,這類值可能完全無法將內容保留在安全區域內。

配合不規則形狀的螢幕

除了矩形螢幕外,部分車輛可能配備不規則形狀的螢幕,如圖 1 所示:

Android Automotive OS 裝置,螢幕右側為弧形。
圖 1:Android Automotive OS 裝置,右側為曲面螢幕。綠色區域是安全矩形,不會與曲線螢幕凹口的定界框重疊。

如果應用程式未採用無邊框設計,您就不必採取任何行動,系統會自動在安全區域內算繪。

如果應用程式採用無邊框轉譯,您可以選擇應用程式在螢幕凹口處的行為。如要達成這個目標,您可以使用資源,為應用程式的主題設定 android:windowLayoutInDisplayCutoutMode 屬性,或在執行階段修改視窗的 layoutInDisplayCutoutMode 屬性。

Android Automotive OS 裝置上的螢幕凹口類型與行動裝置不同,因此請勿使用 LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 或 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES,因為這些 API 的行為已針對行動裝置上的凹口進行最佳化。請改用 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 或 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS,一律避開或一律進入凹口。如果選擇後者,請參閱「支援螢幕凹口」,進一步瞭解與螢幕凹口相關的 API。

如果應用程式會在螢幕凹口區域算繪,且您希望 Android Automotive OS 和行動裝置有不同的行為,請參閱「停用功能」一節,瞭解如何在執行階段設定這項行為,或參閱「使用替代資源」一節,瞭解如何使用資源檔案設定這項行為。

停用功能

如果您打算在 Android Automotive OS 上提供現有的行動應用程式,某些特性和功能可能會不適合或無法使用。舉例來說,汽車通常不會授予相機存取權限。此外,Android Automotive OS 只支援部分 Google Play 服務,詳情請參閱「車用 Google Play 服務」一文。

您可以使用 PackageManager.hasSystemFeature API,檢查應用程式是否具備 FEATURE_AUTOMOTIVE 功能,偵測應用程式是否在 Android Automotive OS 上執行。如以下範例所示:

val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
if (isCar) {
    // Enable or disable a given feature
}

此外,如果您的應用程式也有 Android Auto 元件,則可使用車輛專用 Android 應用程式庫 中的 CarConnection API 偵測應用程式是否在 Android Automotive OS 或 Android Auto 上執行,或是否未與任何車輛連線。

針對子母畫面 (PiP) 功能,請按照既定的最佳做法檢查該功能是否可用,並進行適當回應。

處理離線情況

雖然越來越多車輛都能連上網際網路,但仍建議您確保應用程式即使沒有網路連線也能執行,例如下列情況:

  • 使用者可能會選擇停用汽車製造商在訂閱套裝組合中提供的行動數據。
  • 部分地區的行動數據存取功能可能會受到限制。
  • 配備 Wi-Fi 無線電的車輛可能不在 Wi-Fi 訊號範圍內,或者原始設備製造商 (OEM) 可能停用 Wi-Fi 而改用行動網路。

為因應應用程式中的這些情境,請對需要網路連線能力的功能進行優雅降級,例如提供離線內容。詳情請參閱「最佳化網路的最佳做法」。

使用替代資源

為協助調整車輛應用程式,您可以在搭載 Android Automotive OS 的車輛上使用 car 資源限定詞,來提供替代資源。舉例來說,如果您使用維度資源來儲存邊框間距值,可以針對 car 資源集使用較大的值,讓觸控目標更大。