IVI 시장에서 FLO Android 살아남기




안녕하세요. AOS 개발팀 Zinzer입니다.

저희 팀에서는 Android 전반에 걸쳐 다양한 OS 개발을 진행하고 있습니다.

그 중에서 이번 글에서는 FLO 차량용 앱의 변화 과정 및 구현 기능에 대해 포스팅해보려고 합니다.


최근 전기차, 자율 주행 등으로 자동차 관련 이슈들이 화두가 되면서 많은 자동차 제조업체들이 자동차 엔터테인먼트 콘텐츠 확보에 열을 올리고 있습니다.


이런 변화 때문인지 2021 Google IO에서도 차량용 Android의 업데이트에 대한 내용과 Volvo/Porsche 등 많은 자동차 제조업체들이 Android Automotive OS와 Android Auto를 신차에 탑재하고 있다는 내용을 발표했는데요.


이에 맞추어 FLO에서도 Automotive OS 용 앱 개발 및 Auto 업데이트를 적극적으로 진행하고 있습니다.






1. 차량용 Android 용어

Google이 지원하는 차량용 Android를 이야기할 때 Android Auto, Automotive OS, IVI 라는 용어를 많이 사용합니다. 그렇다면 이 용어들은 어떤 뜻일까요?


  • Android Auto : 사용자의 휴대전화에서 실행되는 플랫폼으로, USB 연결을 통해 호환되는 차량용 인포테인먼트 시스템에 차량 내 사용을 위해 설계된 앱을 지원합니다.


  • Android Automotive OS : 사용자의 휴대전화의 확장이 아니라, 완전히 독립되어 차량 내 하드웨어에서 직접 실행되는 운영체제 및 플랫폼입니다. 자동차 제조사의 구현에 따라 HVAC(Heating, Ventilation and Air Conditioning) 및 기타 자동차 시스템을 제어할 수 있는 특징이 있습니다.


  • IVI (In-Vehicle Infotainment) : 정보를 뜻하는 인포메이션(Information)과 오락을 뜻하는 엔터테인먼트(Entertainment)의 합성어로 운전자에게 여러 정보와 오락 기능을 동시에 제공하는 시스템을 뜻합니다. Android Automotive 기기의 사용자 대상 기능을 설명할 때 헤드 유닛과 동의어로 자주 사용됩니다.




2. MediaBrowserService 워크플로우

Automotive OS는 독립된 운영체제를 가지고 있고 제조사들에 따라서도 다르게 구현할 수 있기 때문에 Auto와 완전히 다르다고 예상할 수 있지만, 이 둘은 MediaBrowserService 를 사용하여 동일한 워크 플로우를 따르는 공통점이 있습니다.


차량용뿐만이 아니라 스마트폰 이외의 외부 기기에서 음악을 제어하려면 MediaBrowserSercice를 구현해야합니다.


먼저, Android Auto 또는 Android Automotive에서 미디어 앱을 실행시키려면 Manifest에 MediaBrowserService를 상속받은 클래스를 Service로 명시해야합니다.



* 이때 MediaBroswerService가 없는 경우 앱 아이콘이 노출되지 않아 차량용 미디어 앱을 사용할 수 없습니다.




| onGetRoot()


onGetRoot 메서드는 루트 미디어 항목을 가져옵니다. 루트 미디어 항목은 UI에 노출될 내용을 담고 있는 게 아니라, 콘텐츠 계층 구조의 루트 노드에 관한 정보를 반환해서 onLoadChildren 메서드로 콘텐츠를 요청하는 역할을 합니다.


FLO에서는 Auto와 Automotive 모두 지원하기 때문에 하나의 MediaBrowserService 클래스에서 Auto, Automotvie인지를 구분하여 각각의 루트로 BrowserRoot 객체를 생성하여 return 합니다.




| onLoadChildren()


onLoadChildren 메서드는 루트 미디어 항목의 하위 요소를 가져옵니다.

하위 요소는 Playable Media Item(재생 가능한 요소), Browsable Media Item(하위 메뉴로 이동 가능한 요소) 두 가지 타입으로 구분할 수 있습니다.


1) Browsable Media Item

Auto에서 Browsable Media Item은 화면에 오른쪽 화살표가 노출되어 Playable Item과 구분할 수 있습니다.

사용자가 Browsable Media Item을 선택하면 onLoadChildren 함수가 재 호출되어 선택한 메뉴 항목의 하위 요소를 검색합니다. 이때 검색은 parentId 값을 기준으로 검색합니다.




2) Playable Media Item

사용자가 재생 가능한 미디어 항목을 선택하면 Android Automotive OS 또는 Android Auto에서 적절한 미디어 세션 콜백 메서드를 호출합니다.




Browsable/Playable Media Item들은 MediaItem의 flag 값으로 설정할 수 있습니다.




| onSearch()


검색 기능을 사용하려면 onGetRoot에서 BrowserRoot를 return 할 때 Bundle 값에 아래 키값을 추가합니다.



onSearch 메소드에서 사용자가 입력한 String값으로 api 호출 등을 구현합니다.






3. Automotive 특화 기능

위에 MediaBroswerService 워크플로우를 보시면 알겠지만, UI를 구성할 수 있는 부분이 없습니다. Layout XML과 연결되는 부분도 없죠.

MediaBrowserServiceCompat을 통해서 MediaSession에 Media Item을 전달하면 Meta 데이터를 OS에서 규격에 맞는 UI에 노출해주는 구조입니다.



그래서 UI를 커스텀 하기 굉장히 제한적인 조건을 가지고 있습니다.

특히 Auto의 경우는 Automotive보다 더 UI 활용이 제한적인데요. Auto에 Toast를 띄우거나 Activity를 띄우려고 하면 Auto 화면에 띄워지는게 아니라 사용자의 모바일에 Toast가 띄워집니다.

즉, Auto UI가 아니라 모바일이 영향을 받게 됩니다.


이에 비해 Automotive OS는 독립적인 OS이기 때문에 Android 컴포넌트들의 활용이 가능해 조금 더 자유로운 UI 및 기능을 구현할 수 있습니다.


이 덕분에 FLO에서는 Automotive OS에 특화된 기능을 개발 할 수 있었는데요, 크게 4가지의 기능을 소개 할 수 있을 것 같습니다.

  • 주행 제한 화면 커스텀

  • OTP (One Time Password) Login

  • OTA (Over-The-Air programming)

  • Intent Scheme으로 앱 활성화/비활성화




| FLO 주행 제한 화면 커스텀 화면 구성


Google은 운전자 주의 분산 행동을 방지하기 위해 차량이 주행 중일 경우 화면 조작 제한을 필수로 하고 있습니다. 그래서 Automotive OS에서는 차량의 주행 상태에 따라 주행 제한 화면을 노출합니다.

주행 제한 화면은 Automotive OS에서 Restriction 이벤트를 받아서 커스텀이 가능한데요.

FLO도 아래의 방법으로 FLO의 주행 제한 화면을 만들어 사용하고 있습니다.



먼저 Manifest에서 Activity 별로 distractionOptimized 값을 설정해줍니다.


FLO Automotive 앱에서 Activity들이 상속받아 사용하는 FloAutomotiveBaseActivity에 주행 제한 화면 커스텀 관련 로직을 추가합니다.



isShowRestrictionScreen == true (해당 Activity에 주행 제한 화면을 띄우는) 경우, 차량이 주행 중임을 탐지하는 OnUxRestrictionsChangedListener를 추가해 커스텀 주행 제한 화면을 띄워줍니다.

isShowRestrictionScreen == false인 경우 주행 제한 화면 자체가 노출되지 않습니다.

커스텀 뷰는 OTP 로그인 화면의 Dialog 위에 노출되어야 하기 때문에 View가 아니라 Dialog로 구현되어있습니다.




| OTP (One Time Password) Login


FLO에 OTP 로그인 방식이 추가된 건 Automotive OS에서 웹 뷰 로그인 방식을 대체하기 위함이었습니다.

웹 뷰 로그인 화면에서 소셜 로그인 화면을 통해 서칭이 가능한 웹 브라우저로 접근 할 수 있어 데이터 사용 이슈가 생길 가능성이 높았습니다.


앱 내에서 웹 뷰 로그인 화면을 대체하여 좀 더 간편하게 이용할 수 있는 로그인 방식을 적용하기 위해서 OTP 로그인이 도입되었습니다.



| OTA (Over-The-Air programming)


최근에 Automotive OS 용 Play Store가 지원되었지만, FLO에서 개발하던 중에는 Automotive OS 용 Play Store가 존재하지 않아 다른 방식으로 업데이트를 지원해야 했습니다.


그래서 OTA(Over-The-Air programming)라는 '유선이 아닌 무선으로 업데이트 할 수 있는 방식'을 사용하여 업데이트를 지원하게 되었습니다. OTA는 다음과 같은 단계로 진행됩니다.


  1. API를 호출하여 업데이트 여부 확인

  2. 업데이트 진행이 필요한 경우 URL로 APK 파일 다운로드

  3. 다운로드받은 APK 로컬 파일 URI를 intent로 OS에 전달



모바일에서 Play Store가 아닌 다른 루트로 앱을 설치하려고 하면 사용자의 권한을 받아야 하는데요.

Automotive에서는 권한을 설정할 수 있는 화면이 따로 없었기 때문에

putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true) intent 값로 사용자의 권한 획득 동작을 대신합니다.




| Intent Scheme으로 앱 활성화(Foreground) / 비활성화(Background)


Automotive에서도 모바일 앱과 동일하게 intent scheme 호출로 앱을 활성화, 다시 비활성화하는 동작 구현이 가능합니다.


FLO는 NUGU와의 연동 기능 구현을 위하여 해당 기능을 추가했습니다.

Manifest에 Receiver와 intent filter를 정의합니다.




FloActionReceiver에서 action type에 따라 실행할 함수를 정의해줍니다.



앱을 활성화하는 경우 ComponentName 은 '실행하고자 하는 타겟 패키지명 + Media template 과 연결될 MediaBrowserService' 명으로 생성하여 intent Bundle 값에 담아 startActivity를 호출합니다.

비활성화하는 경우 intent에 'addCategory(Intent.Category)' 담아 startActivity를 호출하여 홈 스크린을 현재 화면으로 끌고 와서 앱을 background로 내리는 방식으로 구현합니다.





4. Android Auto의 변화

Auto에서도 UI에 노출할 수 있는 요소 및 기능에 대한 업데이트가 활발히 이루어지고 있습니다.

FLO도 이런 변화에 대응하기 위해 작년부터 크게 2번의 Auto 업데이트를 진행했습니다.



| 앨범, 대표 아이콘 이미지 노출 (v5.7.0)


FLO 5.7.0 이전 버전의 초기 Auto 화면입니다. 앨범 이미지나 대표 아이콘들 없이 단조로운 UI의 리스트로 구성되어있었습니다.

5.7.0 버전 업데이트를 통해 Grid Layout 구성과 이미지/아이콘을 적용하면서 UI에 큰 변화가 생겼습니다.


이 업데이트를 진행하면서 기존 List Style만 지원했던 코드에 Grid Style 관련 코드도 추가되었습니다.

콘텐츠의 Grid/List style을 적용하기 위해서 다음과 같이 Bundle key 값을 이용해야 합니다.


  • CONTENT_STYLE_BROWSABLE_HINT : 탐색이 가능한 아이템의 Style Key

  • CONTENT_STYLE_PLAYABLE_HINT : 재생이 가능한 아이템의 Style Key



기존에는 위의 방식처럼 Bundle의 key 값과 value 값을 상수로 선언해서 사용해야 했는데 현재는 androidx MediaConstants 라이브러리의 Bundle key, value 값으로 사용할 수 있습니다.



Media Item을 생성할 때 Bundle 값을 넘겨서 하위 항목 style을 설정할 수 있지만, MediBrowserService의 onGetRoot에서 전역 기본 스타일 값을 설정할 수도 있습니다.



FLO Auto에서는 onGetRoot에서 return 하는 BrowserRoot에 TABS_OPT_IN_HINT Bundle 키값을 넘기고 있는데요. 이 key값으로 인해 FLO의 Auto 두번째 업데이트가 진행되게 됩니다.





| 상위 탭 적용 (v5.7.2)


이 업데이트가 이루어지기 전까지는 루트 아이템은 무조건 리스트 형태로 노출되었는데요. TABS_OPT_IN_HINT 라는 key값이 도입되면서 Auto도 Automotive와 유사하게 상위 탭을 가지는 UI로 구성할 수 있게 되었습니다. (현재는 default로 상위 탭이 노출됩니다)



이 키값도 현재는 androidx MediaConstants 라이브러리 값으로 적용하면 됩니다.


지금까지 차량용 Android는 어떤 특징을 가지고 있고, IVI 시장에서 FLO는 Auto 업데이트와 Automotive OS에 어떻게 대응하고 있는지 설명드렸습니다 😀



FLO에서는 지금 Android 개발자 채용이 진행중입니다.

최신 기술 도입과 적용을 적극! 장려하는 FLO AOS개발팀에 합류하고 싶으시다면 아래 링크를

확인해주세요 :)


👉 AOS 개발자 채용