Android Head Unit 네비게이션(Navigation) 출력 변경 (BMW, AUDI, JAGUAR, LANDROVER)
중국 쇼핑몰(Aliexpress, Alibaba)에서 안드로이드 해드 유닛을 구입해 장착할 경우 아래 이미지와 같은 작은 스피커를 함께 동봉하는 제품들이 있다. 주로 아우디, 벤츠, 재규어, 랜드로버 등용 제품이 대상이며, 스피커가 없어도 “SPK OUT”과 같은 출력 단자가 있는 제품도 동일한 경우에 속한다.
이 스피커의 정식 명칭은 보통의 ‘외부 스피커’로 목적은 내비게이션/음성 안내 등의 소리를 출력하는 역할을 한다. 문제는 이 스피커가 동작할 때마다 앰프가 동작하는 소리가 들리며 (딸각딸각) 음질 또한 조악하다는 데 있다. 잘 출력되고 있던 노래를 음소거하며 어색한 환경을 만들기도 한다. 차라리 내비게이션을 사용 말아야지 하는 생각이 드는 경우도 꽤 될 정도.
국내외 많은 포럼에서 이 문제를 해결하기 위해 노력한 흔적을 발견할 수 있었다. 주로 하드웨어 개선에 목적을 두고 있었는데, 딸각 거리는 소리를 없애기 위해 앰프를 교체해 보고 소리 품질을 향상하기 위해 스피커를 바꾸는 사례도 있었다. 그러나, 만족할큼 개선된 사례는 전무했다.
모든 소리가 이 스피커에서 나오는 건 아니다. 시스템에서 지정한 내비게이션만 이 스피커에서 소리가 나오는 듯했다. YouTube Music이나 여타 다른 프로그램에서는 자동차 스피커에서 소리를 들을 수 있었기 때문. 가정을 세웠다.
“기본 네비로 지정된 경우가 아니라면 이 스피커에서 소리가 나오지 않을 것이다”
그래서 T 맵을 설치하고, 기본 내비게이션 프로그램을 Maps(Google Maps)로 지정했다. 별도로 설치된 T 맵을 실행 해 봤는데, 역시나 저 스피커에서 소리가 나오는 게 아닌가. 포기할려던 찰나. T맵 버그가 신경 쓰였다.
바로 “정차 시 제자리 뺑뺑이” 버그. 그래서 대안으로 카카오 네비를 설치했다. 그런데! 이건 자동차 스피커에서 안내 음성이 나오는 게 아닌가!? 그래서 기본 내비게이션 프로그램으로 카카오 네비를 선택하려고 하니 목록에 나오지 않았던 것. 그래서 두 번째 가정이 생겼다.
“기본 내비게이션으로 지정할 수 없는 앱의 경우(목록에 나오지 않는 경우) 자동차 스피커에서 소리가 나온다”
이를 확인하기 위해 런처를 추출해 디컴파일을 시도했다. 그 결과 역시나. 아래 제어문을 발견할 수 있었다. com.skt.tmap.ku가 있기 때문에 티맵은 저 스피커에서 소리가 났던 것.
public static boolean isNavgation(String str) { boolean v0 = ((str.equals("com.google.android.apps.maps")) || (str.equals("com.autonavi.amapauto")) || (str.contains("com.baidu.BaiduMap")) || (str.contains("navi")) || (str.contains("com.papago")) || (str.contains("com.waze")) || (str.contains("com.sygic")) || (str.contains("navi")) || (str.contains("com.cyberon")) || (str.contains("com.kingwaytek")) || (str.equals("com.nng.igo.primong.hun10th")) || (str.contains(".igo")) || (str.contains("com.skt.tmap.ku")) || (str.contains("map")) || (str.contains("Map")) || (str.contains("cld.kld")) || (str.contains("ru.yandex.yandexnavi")) || (str.contains("com.loco")) || (str.contains("com.mireo")) || (str.contains("com.nng.igoprimoisrael.javaclient") ) || (str.contains("com.ivolk.StrelkaGPS")) || (str.contains("cityguide.probki.net"))) && !str.contains(".mapgoo") && !str.contains(".amaplocation") && !str.contains("map.location") && !str.contains("com.android.simappdialog") ? true : false; return v0; }
이 부분을 중국 엔지니어에게 수정해달라고 했지만, 전역 설정 부분이라 건드리기 어렵다는 회신을 받았다. 스피커만 바이패스 하면 되는데. 런처가 디컴파일이 완벽하게 되지 않아 다시 컴파일할 때 문제가 생기더군요. 그래서 직접 수정은 실패. 위 조건에 해당되지 않는 APP ID를 갖고 있는 내비게이션 앱을 찾아봤다. 다행히 티맵 스토어 버전을 제외하면 모두 위 조건에 해당되지 않았다.
- 티맵 : com.skt.skaf.l001 mtm091 (플레이 스토어 버전이 아님)
- 맵피 : com.mnsoft.mappyobn
- 카카오 네비 : com.locnall.KimGiSa
이들을 설치하면 저 작은 스피커에서 소리가 나오지 않고 자동차에서 소리가 나온다. 그럼 잘 해결된 걸까? 그렇지 않다. 설정 > 내비게이션 선택 옵션에서 선택된 내비게이션 앱만 UI와 상호작용을 하기 때문이다. 즉, 아래 화면에서 선택할 수 없다면 내비게이션 앱을 실행하기 매우 번거로워진다.
사용성이 중요하기 때문에 Fake App을 만들어야 한다. 원리는 간단하다.
- com.skt.tmap.ku의 APP ID를 갖고 있는 앱을 만들자.
- 안드로이드 유닛 런처는 T-Map이 설치되어 있다고 생각할 것이다.
- 2번의 이유로 설정>내비게이션(탐색)에서 이 앱을 선택한다.
- 이 앱은 내가 원하는 내비게이션 앱을 실행한다.
코드 예제는 매우 간단하며, 다음과 같다.
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.mnsoft.mappyobn"); if (launchIntent != null) { startActivity(launchIntent);//null pointer check in case package name was not found } android.os.Process.killProcess(android.os.Process.myPid()); System.exit(1);
위 예제는 맵피(com.mnsoft.mappyobn)를 실행하는 경우다. Fake App이 실행되면, 맵피를 실행한다. Fake App이 너무 가볍기 때문에 눈에 잘 뜨이지 않는다.
아래 코드가 전문이다. 이 예제는 위 제어구조에서 발견된 외국 내비게이션 APP ID를 사용한 Fake App이다.
- APP ID : com.autonavi.amapauto
package com.autonavi.amapauto; import android.content.Intent; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.mnsoft.mappyobn"); if (launchIntent != null) { startActivity(launchIntent); } else { // 앱이 없다. 걍 종료 } android.os.Process.killProcess(android.os.Process.myPid()); System.exit(1); } }
이 방법은 다양한 경우에 응용할 수 있다. 예를 들어 중국 안드로이드 유닛에 대부분 설치되어 있는 EasyConnect를 Carlinkit의 AutoPlay로 바꾼다거나. 여튼. 매우 유용한 방법!