Rozwiązywanie problemów z nakładkami zasobów środowiska wykonawczego

Za pomocą tych informacji możesz rozwiązać problemy z nieprawidłowym działaniem nakładki zasobów w czasie wykonywania (RRO) w implementacji Androida Automotive.

Więcej informacji o zmianach wartości zasobów aplikacji w czasie wykonywania znajdziesz w artykule Zmienianie wartości zasobów aplikacji w czasie wykonywania. Stale sprawdzaj dane wyjściowe logcat, które mogą zawierać przydatne informacje o tym, co dzieje się w trakcie całego procesu.

Krok 1. Wyświetl listę RRO

Aby wyświetlić listę RRO:

  1. Uruchom to polecenie:

    adb shell cmd overlay list --user current

    Wyświetlają się takie dane wyjściowe:

    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.rro
    
  2. Sprawdź, czy RRO znajduje się na liście. Te wskaźniki oznaczają stan RRO:

    Wskaźnik Stan RRO
    [ ] Zainstalowany i gotowy do aktywacji.
    [X] Zainstalowano i aktywowano.
    --- Zainstalowany, ale zawiera błędy.

    Jeśli Twoja RRO nie jest wymieniona pod nazwą pakietu docelowego, którego chcesz użyć, nie jest ona zainstalowana.

Krok 2. Włączanie i wyłączanie RRO

Jeśli masz zainstalowaną aplikację RRO:

  1. Aby włączyć (lub wyłączyć) RRO, użyj tego polecenia:

    adb shell cmd overlay [enable/disable] --user current [your RRO package name]

Krok 3. Sprawdź, czy usługa RRO jest zainstalowana

Aby sprawdzić, czy na urządzeniu jest zainstalowana usługa RRO, lub rozwiązać problem z jej włączeniem:

  1. Uruchom to polecenie:

    adb shell cmd overlay dump [your RRO package name]

    Wyświetlają się dane wyjściowe podobne do tych:

    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
    }
    
  2. Określ użytkownika (użytkowników) zainstalowanego RRO. W poprzednim przykładzie RRO jest dostępny dla użytkowników 010 (patrz wartości mUserId w górnym bloku kodu).

  3. Aby włączyć (lub wyłączyć) RRO dla użytkownika, przejdź do kroku 2.

  4. Aby sprawdzić wartość mState:

    • STATE_ENABLEDSTATE_ENABLED_IMMUTABLE. RRO jest włączone i stosowane do Twojego celu.

    • STATE_MISSING_TARGET. Cel nie jest zainstalowany.

    • STATE_NO_IDMAP. Coś jest nie tak z konfiguracją plików AndroidManifest.xml, overlays.xml lub overlayable.xml. Użyj adb logcat, aby uruchomić dzienniki, i poszukaj słowa kluczowego idmap, aby zidentyfikować błąd. Zobacz kroki 4 i 5.

    • STATE_UNKNOWN. Coś jest nie tak z OverlayManagerService.

Krok 4. Sprawdź plik AndroidManifest.xml

Aby zweryfikować AndroidManifest.xml:

  1. Sprawdź targetNametargetPackage.

    Wartość parametru android:targetName powinna być taka sama jak wartość grupy, którą można nakładać, zdefiniowana w aplikacji docelowej. Wymagane tylko w przypadku kierowania na nakładkę.

    Wartość android:targetPackage jest zawsze wymagana i powinna zawierać nazwę pakietu aplikacji docelowej.

  2. Sprawdź, czy RRO jest statyczny (czy nie). Statyczne RRO są domyślnie włączone w momencie uruchamiania. Dynamiczne RRO nie są domyślnie włączone podczas uruchamiania. Dodatkowe sposoby włączania dynamicznych RRO znajdziesz w artykule Zmienianie wartości zasobów aplikacji w czasie wykonywania.

  3. Sprawdź priorytet statycznych reguł RRO (priorytet dynamicznych reguł RRO jest zawsze ustawiony na Integer.MAX_VALUE, a kolejność ich stosowania zależy od momentu ich włączenia).

    Na ten sam obiekt docelowy może się nakładać wiele reguł RRO. RRO o wyższym priorytecie są stosowane na końcu. W skali od 0 do 10, gdzie 10 to najwyższa ocena, a 0 najniższa.

Krok 5. Sprawdź plik overlays.xml

  1. Zaznacz overlays.xml, aby potwierdzić, że wszystkie zasoby, które chcesz nakładać, są zdefiniowane w tym pliku. Oto przykład:overlays.xml

    <overlay>
        <item target="string/app_name" value="@string/overlaid_app_name" />
    </overlay>
    
  2. Musisz mieć pewność, że:

    • Zasób string o nazwie app_name istnieje już w aplikacji docelowej.
    • Zasób string o nazwie overlaid_app_name istnieje w Twoim RRO.
  3. Jeśli docelowe urządzenie ma plik overlayable.xml, sprawdź, czy zawiera on plik app_name. Upewnij się, że w pliku AndroidManifest.xml używasz prawidłowej wartości targetName (krok 4).

    Przykład:

    <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>
    

Krok 6. Wygeneruj mapę tożsamości

Na tym etapie wszystkie problemy z RRO powinny zostać rozwiązane. Następnie wygeneruj idmap swojego RRO, aby dowiedzieć się, jak jest rozwiązywany zasób i dlaczego ma inną wartość niż oczekiwana.

  1. Aby znaleźć ścieżkę do idmap na urządzeniu:

    adb shell
    su
    ls data/resource-cache
  2. Aby wyodrębnić zawartość tego pliku:

    adb root
    adb shell idmap2 dump --idmap-path [path to your RRO idmap file]

    Przykład:

    adb shell idmap2 dump --idmap-path data/resource-cache/system@app@CarUiPortraitLauncherReferenceRRO@CarUiPortraitLauncherReferenceRRO.apk@idmap

    Dane wyjściowe wyglądają podobnie do tych widocznych poniżej. Dane wyjściowe zawierają informacje o tym, który identyfikator z Twojego RRO jest zmapowany do którego identyfikatora w docelowym zasobie, a także nazwę nałożonego zasobu.

    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
    

Aby sprawdzić, jak są mapowane konkretne zasoby, użyj tego polecenia:

adb shell cmd overlay lookup --verbose --user 10 com.android.car.ui.paintbooth com.android.car.ui.paintbooth:color/widget_background

Dane wyjściowe to końcowa wartość zasobu:

#ff7986cb

Możesz też wyodrębnić pliki układu z plików APK, aby wyświetlić rozstrzygnięte identyfikatory, które pasują do danych wyjściowych powyżej:

aapt2 dump xmltree $OUT/system/priv-app/sharedlibraryclient/sharedlibraryclient.apk --file res/layout/activity_main.xml

Zwracane są dane wyjściowe podobne do tych:

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!!")

Nieudane próby rozwiązania mapowań są oznaczone od idmap2 do 3 znaków zapytania (???).

W tym przykładzie RRO ma zakodowaną na stałe wartość koloru nałożoną na zasób publiczny:

$ idmap2 dump --idmap-path [file]
0x00010402 -> color 0xff00ff00 (???)

W tym przykładzie RRO nakłada zasób publiczny, wskazując go na wewnętrzny (prywatny) zasób kolorów w tej samej bibliotece współdzielonej:

$ idmap2 dump --idmap-path [file]
0x00010402 -> 0x7f010000 (??? -> color/item_background_new)