Instrument Cluster API(Android API)를 사용하면 Google 지도를 비롯한 내비게이션 앱을 자동차의 보조 디스플레이(예: 계기판 핸들 뒤)에 표시할 수 있습니다. 이 페이지에서는 보조 디스플레이를 제어하는 서비스를 생성한 다음 내비게이션 앱이 사용자 인터페이스를 표시할 수 있도록
와 서비스를 통합하는 방법을 설명합니다.CarService
술어
이 페이지에서는 다음 용어가 사용됩니다.
용어 | 설명 |
---|---|
CarInstrumentClusterManager | 외부 앱이 계기판에서 활동을 시작하고 계기판이 활동을 표시할 준비가 되면 콜백을 수신할 수 있게 해주는 CarManager 인스턴스입니다. |
CarManager | CarService 에서 구현한 자동차 관련 서비스와 상호작용하기 위해 외부 앱에서 사용하는 모든 관리자의 기본 클래스입니다. |
CarService | 외부 앱(Google 지도 포함)과 Instrument Cluster 액세스와 같은 자동차 관련 기능 간의 통신을 제공하는 Android 플랫폼 서비스입니다. |
목적지 | 차량이 이동할 최종 목적지입니다. |
도착 예정 시간 | 목적지 도착 예상 시간. |
헤드유닛(HU) | 자동차에 내장된 기본 계산 단위입니다. HU는 모든 Android 코드를 실행하며 자동차의 중앙 디스플레이에 연결됩니다. |
계기판 | 스티어링 휠 뒤, 차량 계기판 사이에 위치한 보조 디스플레이입니다. 이는 자동차 내부 네트워크(CAN 버스)를 통해 HU에 연결된 독립적인 계산 장치이거나 HU에 연결된 보조 디스플레이일 수 있습니다. |
InstrumentClusterRenderingService | Instrument Cluster 디스플레이와 인터페이스하는 데 사용되는 서비스의 기본 클래스입니다. OEM은 OEM 관련 하드웨어와 상호 작용하는 이 클래스의 확장을 제공해야 합니다. |
키친싱크 앱 | Android Automotive에 포함된 테스트 앱입니다. |
노선 | 차량이 목적지에 도달하기 위해 이동하는 특정 경로입니다. |
싱글톤 서비스 | android:singleUser 속성이 있는 Android 서비스입니다. 언제든지 최대 하나의 서비스 인스턴스가 Android 시스템에서 실행됩니다. |
전제 조건
통합을 개발하려면 다음 요소가 있어야 합니다.
- 안드로이드 개발 환경. Android 개발 환경을 설정하려면 빌드 요구 사항을 참조하세요.
- 안드로이드 소스코드를 다운로드하세요. https://android.googlesource.com 의 pi-car-release 분기(또는 그 이상)에서 최신 버전의 Android 소스 코드를 받으세요.
- 헤드유닛(HU). Android 9 이상을 실행할 수 있는 Android 기기. 이 기기에는 자체 디스플레이가 있어야 하며 새로운 Android 빌드로 디스플레이를 플래시할 수 있어야 합니다.
- 계기판은 다음 중 하나입니다.
- HU에 연결된 물리적 보조 디스플레이입니다. 장치 하드웨어 및 커널이 다중 디스플레이 관리를 지원하는지 여부.
- 독립 유닛. 네트워크 연결을 통해 HU에 연결된 모든 계산 장치로, 자체 디스플레이에 비디오 스트림을 수신하고 표시할 수 있습니다.
- 에뮬레이트된 디스플레이. 개발 중에 다음과 같은 에뮬레이트된 환경 중 하나를 사용할 수 있습니다.
- 시뮬레이션된 보조 디스플레이. AOSP Android 배포판에서 시뮬레이션된 보조 디스플레이를 활성화하려면 설정 시스템 앱의 개발자 옵션 설정으로 이동한 다음 보조 디스플레이 시뮬레이션을 선택하세요. 이 구성은 물리적 보조 디스플레이를 연결하는 것과 동일하지만 이 디스플레이는 기본 디스플레이 위에 겹쳐진다는 제한이 있습니다.
- 에뮬레이트된 계기판. Android Automotive에 포함된 Android 에뮬레이터는 ClusterRenderingService 서비스가 보조 디스플레이에 연결된 계기판을 표시하는 옵션을 제공합니다. 에뮬레이터 _qemu-pipes . ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다.
이 에뮬레이트된 외부 디스플레이에 연결하기 위한 참조 계기판 구현입니다.
통합 아키텍처
통합 구성 요소
Instrument Cluster API의 모든 통합은 다음 세 가지 구성 요소로 구성됩니다.
-
CarService
- 내비게이션 앱
- OEM 계기판 서비스
자동차 서비스
CarService
내비게이션 앱과 자동차 사이를 중재하여 주어진 시간에 하나의 내비게이션 앱만 활성화되고 android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
권한이 있는 앱만 자동차에 데이터를 보낼 수 있도록 합니다.
CarService
모든 자동차 관련 서비스를 부트스트랩하고 일련의 관리자를 통해 이러한 서비스에 대한 액세스를 제공합니다. 서비스와 상호작용하기 위해 자동차에서 실행되는 앱은 이러한 관리자에 액세스할 수 있습니다.
계기판 구현을 위해 자동차 OEM은 InstrumentClusterRendererService의 사용자 정의 구현을 생성하고 ClusterRenderingService 서비스가 보조 디스플레이에 연결되도록 업데이트해야 합니다.
Instrument Cluster를 렌더링할 때 부팅 프로세스 중에 CarService
ClusterRenderingService 서비스의 InstrumentClusterRendererService
키를 읽고 보조 디스플레이에 연결됩니다. InstrumentClusterService
구현을 찾습니다. AOSP에서 이 항목은 Navigation State API 샘플 클러스터 구현 렌더링 서비스를 가리킵니다.
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
이 항목에 언급된 서비스는 초기화되어 CarService
에 바인딩됩니다. Google 지도와 같은 내비게이션 앱이 CarInstrumentClusterManager
요청하면 CarService
바인딩된 InstrumentClusterRenderingService
에서 Instrument Cluster 상태를 업데이트하는 관리자를 제공합니다. (이 경우 바운드는 Android Services 를 나타냅니다.)
계기판 서비스
OEM은 보조 디스플레이에 연결된 ClusterRenderingService 서비스의 하위 클래스를 포함하는 Android 패키지(APK)를 생성해야 합니다. ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다. 샘플을 위해.
이 클래스는 두 가지 용도로 사용됩니다.
- 인터페이스 Android 및 Instrument Cluster 렌더링 장치를 제공합니다(이 페이지의 목적).
- 단계별 내비게이션 안내와 같은 내비게이션 상태 업데이트를 수신하고 렌더링합니다.
첫 번째 목적으로 InstrumentClusterRendererService
의 OEM 구현은 차량 내부 화면에 정보를 렌더링하는 데 사용되는 보조 디스플레이를 초기화하고 InstrumentClusterRendererService.setClusterActivityOptions()
및 InstrumentClusterRendererService.setClusterActivityState()
메서드를 호출하여 이 정보를 CarService
에 전달해야 합니다.
두 번째 기능의 경우 Instrument Cluster 서비스는 보조 디스플레이에 연결된 ClusterRenderingService 서비스 구현을 제공해야 합니다. eventType
으로 인코딩된 탐색 상태 업데이트 이벤트 와 번들로 인코딩된 이벤트 데이터를 수신하는 인터페이스입니다.
통합 순서
다음 다이어그램은 업데이트를 렌더링하는 탐색 상태의 구현을 보여줍니다.
이 그림에서 색상은 다음을 나타냅니다.
- 노란색.
CarService
및CarNavigationStatusManager
Android 플랫폼에서 제공됩니다. 자세한 내용은 자동차 및 CAR_NAVIGATION_SERVICE를 참조하세요. - 청록색. OEM이 구현한
InstrumentClusterRendererService
입니다. - 보라. Google 및 타사 개발자가 구현한 내비게이션 앱입니다.
- 녹색.
CarAppFocusManager
. 자세한 내용은 아래 CarAppFocusManager API 사용 및 CarAppFocusManager 를 참조하세요.
탐색 상태 정보 흐름은 다음 순서를 따릅니다.
-
CarService
InstrumentClusterRenderingService
를 초기화합니다. - 초기화 중에
InstrumentClusterRenderingService
다음을 사용하여CarService
업데이트합니다.- 모호하지 않은 경계와 같은 계기판 표시 속성(나중에 모호하지 않은 경계에 대한 자세한 내용 참조)
- Instrument Cluster 디스플레이 내에서 활동을 시작하는 데 필요한 활동 옵션(자세한 내용은 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
카테고리로 표시된 활동을 찾습니다. - 탐색 앱이 발견되면
InstrumentClusterRenderingService
에서 보고한ActivityOptions
사용하여 활동을 시작하고 Instrument Cluster 디스플레이 속성을 인텐트에 추가 항목으로 포함합니다.
API 통합
InstrumentClusterRenderingService
구현은 다음을 수행해야 합니다.
- AndroidManifest.xml에 다음 값을 추가하여 싱글톤 서비스로 지정합니다. 이는 초기화 및 사용자 전환 중에도 Instrument Cluster 서비스의 단일 복사본이 실행되도록 하는 데 필요합니다.
android:singleUser="true"
-
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
시스템 권한을 보유하세요. 이는 Android 시스템 이미지의 일부로 포함된 계기판 렌더링 서비스만CarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
에 의해 바인딩되도록 보장합니다.
InstrumentClusterRenderingService 구현
서비스를 구축하려면:
- ClusterRenderingService 서비스에서 확장되는 클래스를 작성하여 보조 디스플레이에 연결합니다. 그런 다음
-
onCreate()
중에 이 서비스를 사용하여 렌더링 하드웨어와의 통신을 초기화합니다. 옵션은 다음과 같습니다:- 계기판에 사용할 보조 디스플레이를 결정합니다.
- Instrument Cluster 앱이 렌더링된 이미지를 외부 장치로 렌더링하고 전송할 수 있도록 가상 디스플레이를 생성합니다(H.264와 같은 비디오 스트리밍 형식 사용).
- 위에 표시된 디스플레이가 준비되면 이 서비스는
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
호출하여 Instrument Cluster에 활동을 표시하는 데 사용해야 하는 정확한ActivityOptions
정의해야 합니다. 다음 매개변수를 사용하세요.- 범주. ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다.
-
ActivityOptions.
Instrument Cluster에서 활동을 시작하는 데 사용할 수 있는ActivityOptions
인스턴스입니다. 예를 들어 AOSP의 샘플 Instrument Cluster 구현에서:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Instrument Cluster가 활동을 표시할 준비가 되면 이 서비스는
InstrumentClusterRenderingService#setClusterActivityState()
호출해야 합니다. 다음 매개변수를 사용하세요.-
category
ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다. - ClusterRenderingService 서비스로 생성된
state
은 보조 디스플레이에 연결됩니다. 다음 데이터를 제공하십시오. -
visible
계기판을 표시하고 콘텐츠를 표시할 준비가 되도록 지정합니다. -
unobscuredBounds
콘텐츠를 표시하기에 안전한 계기판 디스플레이 내 영역을 정의하는 직사각형입니다. 예를 들어 다이얼과 게이지로 덮이는 영역입니다.
-
-
Service#dump()
메서드를 재정의하고 디버깅에 유용한 상태 정보를 보고합니다(자세한 내용은 dumpsys 참조).
AndroidManifest.xml
파일에 해당 항목을 추가합니다. 이 클래스는 계기판 디스플레이를 제어하고 탐색 상태 API 데이터를 ( 선택적으로 ) 렌더링할 수 있습니다.샘플 InstrumentClusterRenderingService 구현
다음 예에서는 원격 물리적 디스플레이에 계측기 클러스터 콘텐츠를 표시하기 위해 VirtualDisplay
생성하는 InstrumentClusterRenderingService
구현을 간략하게 설명합니다.
또는 이 코드는 사용 가능한 것으로 알려진 경우 HU에 연결된 물리적 보조 디스플레이의 displayId
전달할 수 있습니다.
/** * 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는 OEM이 작성한 클러스터 서비스가 주어진 시간에 탐색 포커스가 있는 탐색 앱을 알 수 있도록 하는 getAppTypeOwner()
라는 메서드를 제공합니다. 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 } ...
부록: 샘플 앱 사용
AOSP는 Navigation State API를 구현하는 샘플 앱을 제공합니다.
이 샘플 앱을 실행하려면 다음 안내를 따르세요.
- 지원되는 HU에서 Android Auto를 빌드하고 플래시하세요. 귀하의 기기에 맞는 Android 구축 및 플래싱 지침을 사용하세요. 지침은 참조 보드 사용을 참조하십시오.
- 물리적 보조 디스플레이를 HU(지원되는 경우)에 연결하거나 가상 보조 HU를 켭니다.
- 설정 앱에서 개발자 모드를 선택하세요.
- 설정 > 시스템 > 고급 > 개발자 옵션 > 보조 디스플레이 시뮬레이션 으로 이동합니다.
- HU를 재부팅합니다. ClusterRenderingService 서비스는 보조 디스플레이에 연결됩니다.
- KitchenSink 앱을 실행하려면:
- 서랍을 열어보세요.
- 인스타그램 으로 이동 무리 .
- 메타데이터 시작 을 클릭하세요.
KitchenSink는 DirectRenderingCluster
서비스에 Instrument Cluster에 모형 사용자 인터페이스를 표시하도록 지시하는 NAVIGATION 포커스를 요청합니다.