使用 Instrument Cluster API (Android API) 顯示導航應用程式。
包括 Google 地圖 (顯示在車上的第二台螢幕上),例如
儀表板上的方向盤。本頁說明如何
服務控制該次要顯示器,以及將服務整合到
CarService
,讓導航應用程式可顯示
存取 API
術語
本頁面使用的字詞如下。
CarManager
的例項,可讓外部應用程式在
檢測叢集,並在儀表板準備就緒時接收回呼
活動。android:singleUser
屬性的 Android 服務。在
無論何時,在 Android 系統上最多只能執行一個服務執行個體。必要條件
繼續操作之前,請務必備妥下列元素:
- Android 開發環境。如何設定 Android 開發環境的詳細說明,請參閱 建構需求。
- 下載 Android 原始碼。取得最新版本的 從 Pi-car-release 分支版本 (或之後版本) 的 Android 原始碼 https://android.googlesource.com。
- 車用運算主機 (HU)。可執行 搭載 Android 9 以上版本。此裝置必須裝有專屬顯示器,且 利用新版 Android 刷新螢幕
- 「Instrument Cluster」是下列其中一種:
- 連接至 HU 的實體次要螢幕。如果 裝置硬體和核心支援管理多個螢幕。
- 獨立單位。任何連線至 透過網路連線使用 HU,能夠接收和顯示影片串流 獨立的顯示器
- 模擬顯示畫面。在開發期間,您可以使用
模擬環境:
- 模擬的次要螢幕。如要啟用模擬功能 任何 Android 開放原始碼計畫 Android 發行版的次要螢幕,請前往「開發人員選項」 「設定」系統應用程式中的設定,然後選取「模擬次要動作」 顯示 此設定等同於附加實體 螢幕,差別在於這個螢幕的限制會疊加在主要畫面上 螢幕。
- 模擬的儀表板。內附 Android 模擬器 搭配 AAOS 提供選擇顯示檢測儀表板的 ClusterRenderingService。
整合架構
整合元件
Instrument Cluster API 的任何整合項目皆由下列三個元件組成:
CarService
- 導航應用程式
- 原始設備製造商 (OEM) 檢測叢集服務
CarService
CarService
會在導航應用程式和車輛之間進行中介,確保只會
只有一個導航應用程式會同時啟用,且只能使用
android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
權限可傳送資料
。
「CarService
」會啟動所有車輛專用服務,並提供存取權
我們會提供各式各樣的服務如要與服務互動
運行中的應用程式可存取這些管理員。
如要導入儀表板,汽車原始設備製造商 (OEM) 必須建立自訂 實作 InstrumentClusterRendererService,然後更新 ClusterRenderingService。
轉譯檢測叢集時,在啟動程序期間
CarService
會讀取InstrumentClusterRendererService
ClusterRenderingService
找出 InstrumentClusterService
的實作。在 Android 開放原始碼計畫中,這個項目
指向 Navigation State API 範例叢集實作轉譯服務:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
這個項目中參照的服務經過初始化並繫結至
CarService
。導航應用程式 (例如 Google 地圖) 時要求
CarInstrumentClusterManager
和 CarService
提供的管理員
從繫結的 InstrumentClusterRenderingService
更新檢測叢集狀態。
(在本例中,bound 是指
Android 版
服務)
儀表板服務
原始設備製造商 (OEM) 必須建立 Android 套件 (APK),其中包含 ClusterRenderingService。
這個類別有兩個用途:
- 提供 Android 介面和「Instrument Cluster」轉譯裝置 (本頁目的)。
- 接收及呈現導航狀態更新,例如即時路線 導航指引。
針對第一個用途,原始設備製造商 (OEM) 的 InstrumentClusterRendererService
實作
必須初始化次要顯示器,用來在車櫃的螢幕上呈現資訊,並
藉由呼叫CarService
InstrumentClusterRendererService.setClusterActivityOptions()
和
InstrumentClusterRendererService.setClusterActivityState()
方法。
如果是第二個函式,檢測叢集服務必須提供
導入
ClusterRenderingService
接收導覽狀態更新「事件」的介面,這類事件會編碼為
透過套件編碼的 eventType
和事件資料。
整合序列
下圖說明導覽狀態的實作 轉譯更新的內容:
在本圖中,顏色代表的意義如下:
- 黃色。「
CarService
」和「CarNavigationStatusManager
」 Android 平台提供的功能詳情請參閱: Car 和 CAR_NAVIGATION_SERVICE。 - 青色已導入
InstrumentClusterRendererService
。 - 紫色。由 Google 和第三方實作的導航應用程式 開發人員。
- 綠色。跳到
CarAppFocusManager
的位置。詳情請參閱: 使用 CarAppFocusManager API 下方和 CarAppFocusManager。
導覽狀態資訊流程會遵循以下順序:
CarService
會初始化InstrumentClusterRenderingService
。- 在初始化期間,
InstrumentClusterRenderingService
會更新CarService
,其中包含:- 儀表板顯示屬性,例如未模糊邊界 (稍後查看更多未模糊界線的詳細資料)。
- 透過儀表板螢幕啟動活動所需的活動選項。 詳情請參閱: ActivityOptions。
- 導航應用程式 (例如 Android Automotive 專用的 Google 地圖,或任何地圖應用程式
並授予必要權限):
- 使用 Car-lib 中的 Car 類別取得
CarAppFocusManager
。 - 即時路線導航開始之前,如果:
通過
CarAppFocusManager.requestFocus()
次CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
做為appType
參數。
- 使用 Car-lib 中的 Car 類別取得
CarAppFocusManager
將這項要求傳送給CarService
。 如果獲授予,CarService
會檢查導航應用程式套件,然後找出 活動已標示android.car.cluster.NAVIGATION
類別。- 如果找到,導航應用程式會使用以下指標回報的
ActivityOptions
: 使用InstrumentClusterRenderingService
來啟動活動,並包含 在意圖中,檢測叢集顯示屬性做為額外項目。
整合 API
InstrumentClusterRenderingService
實作必須:
- 將下列值新增至單例模式服務
AndroidManifest.xml 檔案有效確保
即使在初始化和使用者切換期間,仍會檢測叢集服務:
android:singleUser="true"
- 保留
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
系統權限。這個 保證只有儀表板轉譯服務隨附在 的 Android 系統映像檔已與CarService
繫結:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
實作 InstrumentClusterRenderingService
如要建構服務:
- 編寫可擴充的類別
ClusterRenderingService
並將對應的項目新增至
AndroidManifest.xml
檔案。本課程 控制儀表板螢幕,並可 (選用) 轉譯導覽狀態 API 資料。 - 在
onCreate()
期間,使用此服務初始化與 轉譯硬體選項包括:- 決定檢測叢集要使用的次要螢幕。
- 建立虛擬螢幕,讓「Instrument Cluster」應用程式顯示及傳輸 將圖像算繪至外部單位 (使用 H.264 等影片串流格式)。
- 上述螢幕準備就緒時,該服務必須呼叫
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
: 在顯示活動時,必須用來ActivityOptions
儀表板。使用下列參數:category.
ClusterRenderingService。ActivityOptions.
可選用的ActivityOptions
執行個體 用來在儀表板中啟動活動例如 在 Android 開放原始碼計畫中檢測叢集實作:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- 當儀表叢集準備好顯示活動時,此服務必須叫用
InstrumentClusterRenderingService#setClusterActivityState()
。使用這些 參數:category
ClusterRenderingService。- 已產生
state
套組 ClusterRenderingService。 請務必提供以下資料:visible
將檢測叢集指定為可見,且可供使用 顯示內容。unobscuredBounds
用來定義 用於儀表板螢幕,可顯示內容可以安全顯示。舉例來說 能遮蔽用電器和測量儀表板
- 覆寫
Service#dump()
方法,並回報適合以下項目的狀態資訊: 偵錯 (請參閱 dumpsys 的說明)。
InstrumentClusterRenderingService 實作範例
以下範例說明 InstrumentClusterRenderingService
實作,建立 VirtualDisplay
以顯示檢測設備
在遠端實體螢幕上將內容叢集化。
或者,此程式碼也可以傳遞實體次要函式的 displayId
電腦連接到 HU (如果有的話)。
/** * Sample {@link InstrumentClusterRenderingService} implementation */ public class SampleClusterServiceImpl extends InstrumentClusterRenderingService { // Used to retrieve or create displays private final DisplayManager mDisplayManager; // Unique identifier for the display to be used for instrument // cluster private final String mUniqueId = UUID.randomUUID().toString(); // Format of the instrument cluster display private static final int DISPLAY_WIDTH = 1280; private static final int DISPLAY_HEIGHT = 720; private static final int DISPLAY_DPI = 320; // Area not covered by instruments private static final int DISPLAY_UNOBSCURED_LEFT = 40; private static final int DISPLAY_UNOBSCURED_TOP = 0; private static final int DISPLAY_UNOBSCURED_RIGHT = 1200; private static final int DISPLAY_UNOBSCURED_BOTTOM = 680; @Override public void onCreate() { super.onCreate(); // Create a virtual display to render instrument cluster activities on mDisplayManager = getSystemService(DisplayManager.class); VirtualDisplay display = mDisplayManager.createVirtualDisplay( mUniqueId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, null, 0 /* flags */, null, null); // Do any additional initialization (e.g.: start a video stream // based on this virtual display to present activities on a remote // display). onDisplayReady(display.getDisplay()); } private void onDisplayReady(Display display) { // Report activity options that should be used to launch activities on // the instrument cluster. String category = CarInstrumentClusterManager.CATEGORY_NAVIGATION; ActionOptions options = ActivityOptions.makeBasic() .setLaunchDisplayId(display.getDisplayId()); setClusterActivityOptions(category, options); // Report instrument cluster state. Rect unobscuredBounds = new Rect(DISPLAY_UNOBSCURED_LEFT, DISPLAY_UNOBSCURED_TOP, DISPLAY_UNOBSCURED_RIGHT, DISPLAY_UNOBSCURED_BOTTOM); boolean visible = true; ClusterActivityState state = ClusterActivityState.create(visible, unobscuredBounds); setClusterActivityState(category, options); } }
使用 CarAppFocusManager API
CarAppFocusManager API 提供名為 getAppTypeOwner()
的方法,讓
執行原始設備製造商 (OEM) 編寫的叢集服務,以瞭解哪個導航應用程式在任何指定位置都有瀏覽焦點
讓應用程式從可以最快做出回應的位置
回應使用者要求原始設備製造商 (OEM) 可使用現有的 CarAppFocusManager#addFocusListener()
方法,以及
然後使用 getAppTypeOwner()
瞭解哪些應用程式有焦點。有了這些資訊
原始設備製造商 (OEM) 可以:
- 將叢集中顯示的活動切換至導航應用程式提供的叢集活動 正在保留焦點。
- 可偵測焦點導覽應用程式是否有叢集活動。如果焦點已聚焦 導航應用程式沒有叢集活動 (或這類活動已停用),原始設備製造商 (OEM) 可以 將這個信號傳送到汽車 DIM,這樣就能完全略過叢集的導航面向。
使用 CarAppFocusManager
即可設定及監聽目前的應用程式焦點,例如
主動導航或語音指令通常這類應用程式只有一個,
系統中執行 (或聚焦) 的程序。
使用 CarAppFocusManager#addFocusListener(..)
方法監聽應用程式焦點
變更:
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); mAppFocusManager.addFocusListener(this, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); ... public void onAppFocusChanged(int appType, boolean active) { // Use the CarAppFocusManager#getAppTypeOwner(appType) method call // to retrieve a list of active package names }
使用 CarAppFocusManager#getAppTypeOwner(..)
方法擷取套件
關注的特定應用程式類型目前擁有者的名稱。這個方法可能會傳回
如果目前擁有者使用 android:sharedUserId
功能,就會有多個套件名稱。
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); List<String> focusOwnerPackageNames = mAppFocusManager.getAppTypeOwner( CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); if (focusOwnerPackageNames == null || focusOwnerPackageNames.isEmpty()) { // No Navigation app has focus // OEM may choose to show their default cluster view } else { // focusOwnerPackageNames // Use the PackageManager to retrieve the cluster activity for the package(s) // returned in focusOwnerPackageNames } ...
附錄:使用範例應用程式
Android 開放原始碼計畫提供實作 Navigation State API 的範例應用程式。
如要執行這個範例應用程式:
- 在支援的 HU 上建構 Android Auto 並刷新。使用 您裝置專屬的 Android 建構和刷新指示。如需指示,請參閱: 使用參考板。
- 將實體次要螢幕連接至 HU (如果支援的話),或開啟虛擬
次要 HU:
- 在「設定」應用程式中選取「開發人員模式」。
- 前往「設定」>系統 >進階 >開發人員選項 > 模擬次要螢幕。
- 重新啟動 HU
- 如要啟動 KitchenSink 應用程式:
- 開啟導覽匣。
- 前往「Inst.叢集。
- 按一下「開始中繼資料」。
KitchenSink 要求 NAVIGATION 焦點時,會指示 DirectRenderingCluster
以在儀表板上顯示模擬使用者介面的使用者介面。