이 콘텐츠를 사용하여 런타임 리소스 오버레이(RRO)가 Android Automotive 구현에서 의도한 대로 작동하지 않는 문제를 해결하세요.
관련 문서
Android의 RRO에 관한 자세한 내용은
런타임 시 앱 리소스의 값 변경을 참고하세요.
logcat 출력을 지속적으로 확인하세요. 이 출력은 프로세스 전체에서 발생하는 일에 관한 유용한 정보를 제공할 수 있습니다.
1단계: RRO 나열하기
RRO를 나열하는 방법은 다음과 같습니다.
다음 명령어를 실행합니다.
adb shell cmd overlay list --user current다음과 같은 출력이 표시됩니다.
com.android.systemui [ ] com.android.theme.icon_pack.rounded.systemui [ ] com.android.theme.icon_pack.filled.systemui [ ] com.android.theme.icon_pack.circular.systemui com.android.permissioncontroller --- com.android.permissioncontroller.googlecarui.rroRRO가 목록에 표시되는지 확인합니다. 다음 표시기는 RRO 상태를 나타냅니다.
표시기 RRO 상태 [ ]설치되었으며 활성화할 수 있습니다. [X]설치되고 활성화되었습니다. ---설치되었지만 오류가 있습니다. 오버레이하려는 타겟의 패키지 이름 아래에 RRO가 없다면 RRO가 설치되지 않은 것입니다.
2단계: RRO 사용 및 사용 중지하기
RRO가 설치된 경우 다음 안내를 따르세요.
다음 명령어를 사용하여 RRO를 사용 또는 사용 중지합니다.
adb shell cmd overlay [enable/disable] --user current [your RRO package name]
3단계: RRO가 설치되었는지 확인하기
RRO가 기기에 설치되어 있는지 확인하거나 RRO가 사용 설정되지 않은 문제를 해결하는 방법은 다음과 같습니다.
다음 명령어를 실행합니다.
adb shell cmd overlay dump [your RRO package name]다음과 같은 출력이 표시됩니다.
com.android.car.rotaryplayground.googlecarui.rro:0 { mPackageName...........: com.android.car.rotaryplayground.googlecarui.rro mUserId................: 0 mTargetPackageName.....: com.android.car.rotaryplayground mTargetOverlayableName.: car-ui-lib mBaseCodePath..........: /product/overlay/googlecarui-com-android-car-rotaryplayground/googlecarui-com-android-car-rotaryplayground.apk mState.................: STATE_MISSING_TARGET mIsEnabled.............: true mIsMutable.............: true mPriority..............: 10 mCategory..............: BypassIdMapV1 } com.android.car.rotaryplayground.googlecarui.rro:10 { mPackageName...........: com.android.car.rotaryplayground.googlecarui.rro mUserId................: 10 mTargetPackageName.....: com.android.car.rotaryplayground mTargetOverlayableName.: car-ui-lib mBaseCodePath..........: /product/overlay/googlecarui-com-android-car-rotaryplayground/googlecarui-com-android-car-rotaryplayground.apk mState.................: STATE_MISSING_TARGET mIsEnabled.............: true mIsMutable.............: true mPriority..............: 10 mCategory..............: BypassIdMapV1 }RRO를 설치한 사용자를 확인합니다. 위 예에서 RRO는 사용자
0과 사용자10에서 사용할 수 있습니다(상단 코드 블록의mUserId값 참고).특정 사용자의 RRO를 사용 설정 또는 중지하려면 2단계로 이동합니다.
mState의 값은 다음과 같이 확인할 수 있습니다.STATE_ENABLED및STATE_ENABLED_IMMUTABLE: RRO가 사용 설정되어 타겟에 적용되었습니다.STATE_MISSING_TARGET: 타겟이 설치되지 않았습니다.STATE_NO_IDMAP:AndroidManifest.xml,overlays.xml또는overlayable.xml파일 설정 방식에 문제가 있습니다.adb logcat을 사용하여 로그를 실행하고idmap키워드를 검색하여 오류를 식별합니다. 4단계 및 5단계 확인하기STATE_UNKNOWN:OverlayManagerService에 문제가 있습니다.
4단계: AndroidManifest.xml 확인하기
AndroidManifest.xml 확인 방법은 다음과 같습니다.
targetName과targetPackage를 확인합니다.android:targetName은 타겟 애플리케이션에서 정의된 오버레이 가능한 그룹과 동일한 값을 보유해야 합니다. 이는 오버레이를 타겟팅할 때만 필요합니다.android:targetPackage는 항상 필요하며 타겟 애플리케이션의 패키지 이름을 포함해야 합니다.RRO의 정적 여부를 확인합니다. 정적 RRO는 부팅 시 기본적으로 사용 설정됩니다. 동적 RRO는 부팅 시 기본적으로 사용 설정되지 않습니다. 동적 RRO를 사용 설정하는 다른 방법은 런타임 시 앱 리소스의 값 변경에 제공됩니다.
정적 RRO의 우선순위를 확인합니다. 동적 RRO 우선순위는 항상
Integer.MAX_VALUE로 설정되며 적용 순서는 사용 설정 시점을 기준으로 합니다.여러 RRO가 동일한 타겟에 적용될 수도 있습니다. 우선순위가 높은 RRO가 마지막으로 적용됩니다. 0에서 10 사이를 기준으로, 10이 가장 높고 0이 가장 낮습니다.
5단계: overlays.xml 확인하기
이 단계는 Android 11 이상에만 적용됩니다.
overlays.xml을 확인하여 오버레이하려는 모든 리소스가 이 파일에 정의되어 있는지 검토합니다. 예를 들어, 다음overlays.xml을 고려해 보세요.<overlay> <item target="string/app_name" value="@string/overlaid_app_name" /> </overlay>다음과 같아야 합니다.
- 이름이
app_name인string리소스가 타겟 앱에 있습니다. - 이름이
overlaid_app_name인string리소스가 RRO에 있습니다.
- 이름이
타겟에
overlayable.xml파일이 있으면 파일에app_name이 포함되어 있는지 확인합니다.AndroidManifest.xml파일에서 올바른targetName을 사용하는지 확인합니다(4단계).예:
<overlay> <item target="layout/car_ui_base_layout_toolbar" value="@layout/car_ui_base_layout_toolbar" /> <item target="id/car_ui_toolbar_background" value="@id/car_ui_toolbar_background" /> <item target="attr/layout_constraintTop_toBottomOf" value="@attr/layout_constraintTop_toBottomOf" /> </overlay>
6단계: idmap 덤프하기
이 단계에서는 RRO의 모든 문제가 해결되어야 합니다. 그런 다음 RRO의 idmap을 덤프하여 리소스가 결정되는 방법과 예상과 다른 값으로 결정되는 이유를 알아봅니다.
기기에서
idmap경로를 찾는 방법은 다음과 같습니다.adb shell su ls data/resource-cache이 파일의 콘텐츠를 덤프하는 방법은 다음과 같습니다.
idmap2 dump --idmap-path [path to your RRO idmap file]출력은 다음과 같이 표시됩니다. 출력에는 오버레이된 리소스 이름과 함께 RRO의 어떤 ID가 타겟의 어떤 ID에 매핑되는지 표시됩니다.
target apk path : /system/priv-app/CarMediaApp/CarMediaApp.apk overlay apk path : /product/overlay/googlecarui-com-android-car-media/googlecarui-com-android-car-media.apk 0x7f040008 -> 0x7f010000 bool/car_ui_toolbar_logo_fills_nav_icon_space 0x7f040009 -> 0x7f010001 bool/car_ui_toolbar_nav_icon_reserve_space 0x7f04000b -> 0x7f010002 bool/car_ui_toolbar_tab_flexible_layout 0x7f04000c -> 0x7f010003 bool/car_ui_toolbar_tabs_on_second_row 0x7f09006c -> 0x7f020000 id/car_ui_base_layout_content_container 0x7f090073 -> 0x7f020001 id/car_ui_recycler_view 0x7f090074 -> 0x7f020002 id/car_ui_scroll_bar 0x7f090075 -> 0x7f020003 id/car_ui_scrollbar_page_down 0x7f090076 -> 0x7f020004 id/car_ui_scrollbar_page_up 0x7f090077 -> 0x7f020005 id/car_ui_scrollbar_thumb 0x7f090078 -> 0x7f020006 id/car_ui_scrollbar_track 0x7f09007a -> 0x7f020007 id/car_ui_toolbar_background 0x7f09007e -> 0x7f020008 id/car_ui_toolbar_logo 0x7f090084 -> 0x7f020009 id/car_ui_toolbar_menu_items_container 0x7f090085 -> 0x7f02000a id/car_ui_toolbar_nav_icon 0x7f090086 -> 0x7f02000b id/car_ui_toolbar_nav_icon_container 0x7f090087 -> 0x7f02000c id/car_ui_toolbar_progress_bar 0x7f090089 -> 0x7f02000d id/car_ui_toolbar_row_separator_guideline 0x7f09008d -> 0x7f02000e id/car_ui_toolbar_search_view_container 0x7f09008f -> 0x7f02000f id/car_ui_toolbar_subtitle 0x7f090092 -> 0x7f020010 id/car_ui_toolbar_tabs 0x7f090093 -> 0x7f020011 id/car_ui_toolbar_title 0x7f090094 -> 0x7f020012 id/car_ui_toolbar_title_container 0x7f090095 -> 0x7f020013 id/car_ui_toolbar_title_logo 0x7f090096 -> 0x7f020014 id/car_ui_toolbar_title_logo_container 0x7f0c0024 -> 0x7f030000 layout/car_ui_base_layout_toolbar 0x7f0c0035 -> 0x7f030001 layout/car_ui_recycler_view 0x7f0c0038 -> 0x7f030002 layout/car_ui_toolbar 0x7f0c003f -> 0x7f030003 layout/car_ui_toolbar_two_row
다음 명령어를 사용하여 특정 리소스를 검색하여 어떻게 매핑되는지 확인합니다.
adb shell cmd overlay lookup --verbose --user 10 com.android.car.ui.paintbooth com.android.car.ui.paintbooth:color/widget_background
출력은 리소스의 최종 값입니다.
#ff7986cb
APK에서 레이아웃 파일을 덤프하여 위 출력과 일치하도록 결정된 ID를 볼 수도 있습니다.
aapt2 dump xmltree $OUT/system/priv-app/sharedlibraryclient/sharedlibraryclient.apk --file res/layout/activity_main.xml
다음과 같은 출력이 반환됩니다.
N: android=http://schemas.android.com/apk/res/android (line=2)
N: app=http://schemas.android.com/apk/res-auto (line=2)
N: lib=http://schemas.android.com/apk/com.android.car.ui.sharedlibrary.test (line=2)
E: androidx.constraintlayout.widget.ConstraintLayout (line=2)
A: http://schemas.android.com/apk/res/android:layout_width(0x010100f4)=-1
A: http://schemas.android.com/apk/res/android:layout_height(0x010100f5)=-1
E: TextView (line=19)
A: http://schemas.android.com/apk/res/android:layout_width(0x010100f4)=-2
A: http://schemas.android.com/apk/res/android:layout_height(0x010100f5)=-2
A: http://schemas.android.com/apk/res/android:text(0x0101014f)=@0x020f0000
A: http://schemas.android.com/apk/res-auto:layout_constraintBottom_toBottomOf(0x7f0200fb)=0
A: http://schemas.android.com/apk/res-auto:layout_constraintLeft_toLeftOf(0x7f02010e)=0
A: http://schemas.android.com/apk/res-auto:layout_constraintRight_toRightOf(0x7f020112)=0
A: http://schemas.android.com/apk/res-auto:layout_constraintTop_toTopOf(0x7f020118)=0
E: com.android.car.ui.sharedlibrary.test.MyRecyclerView (line=28)
A: http://schemas.android.com/apk/res/android:layout_width(0x010100f4)=-2
A: http://schemas.android.com/apk/res/android:layout_height(0x010100f5)=-2
A: http://schemas.android.com/apk/com.android.car.ui.sharedlibrary.test:implClass="HelloWorld!" (Raw: "HelloWorld!")
E: com.android.car.ui.sharedlibraryclient.CustomView (line=34)
A: http://schemas.android.com/apk/res/android:layout_width(0x010100f4)=-2
A: http://schemas.android.com/apk/res/android:layout_height(0x010100f5)=-2
A: http://schemas.android.com/apk/res-auto:implClass2(0x7f0200e8)="HelloWorld!!" (Raw: "HelloWorld!!")