執行階段資源重疊問題疑難排解

請參考本文內容,瞭解執行階段資源重疊 (RRO) 為何在 Android Automotive 實作項目中無法正常運作。

如要進一步瞭解 Android 中的 RRO,請參閱「在執行階段變更應用程式的資源值」。請務必持續警戒 logcat 輸出內容,掌握整個流程的運作情況。

步驟 1:列出 RRO

如何列出 RRO:

  1. 執行下列指令:

    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.rro
    
  2. 確認清單中是否顯示您的 RRO。下列指標表示 RRO 狀態:

    指標 RRO 狀態
    [ ] 已安裝,可以立即啟用。
    [X] 已安裝並啟用。
    --- 已安裝,但含有錯誤。

    如果 RRO 未列於要重疊的目標套件名稱下方,表示系統不會安裝 RRO,

步驟 2:啟用及停用 RRO

如果已安裝 RRO:

  1. 使用下列指令啟用 (或停用) RRO:

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

步驟 3:確認已安裝 RRO

如何確認裝置已安裝 RRO,或排解無法啟用 RRO 的原因:

  1. 執行下列指令:

    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
    }
    
  2. 找出已安裝 RRO 的使用者 (或使用者)。在上述範例中,使用者 0 和使用者 10 皆可使用 RRO 作業 (請參閱頂端程式碼區塊中 mUserId 的值)。

  3. 如要為所需使用者啟用 (或停用) RRO,請前往步驟 2。

  4. 如要查看 mState 的值,請按照下列步驟操作:

    • STATE_ENABLEDSTATE_ENABLED_IMMUTABLE RRO 會啟用並套用至目標。

    • STATE_MISSING_TARGET。您的目標尚未安裝。

    • STATE_NO_IDMAPAndroidManifest.xmloverlays.xmloverlayable.xml 檔案的設定方式有問題。使用 adb logcat 執行記錄,並搜尋關鍵字 idmap 來找出錯誤。查看步驟 4 和 5

    • STATE_UNKNOWNOverlayManagerService發生問題。

步驟 4:檢查 AndroidManifest.xml

如何驗證 AndroidManifest.xml

  1. 請查看targetNametargetPackage

    android:targetName 應與目標應用程式中定義的可重疊群組具有相同的值。「只有」在指定疊加層時才需要提出。

    android:targetPackage 一律為必要項目,且應包含目標應用程式的套件名稱。

  2. 檢查 RRO 是否為靜態狀態。系統會在啟動時預設啟用靜態 RRO。開機時預設不會啟用動態 RRO。關於啟用動態 RRO 的其他方式,請參閱「在執行階段變更應用程式的資源值」。

  3. 檢查靜態 RRO 的優先順序 (動態 RRO 一律設為 Integer.MAX_VALUE,且套用順序取決於啟用時機)。

    同一個目標可能會有多個 RRO 指標。優先順序較高的 RRO 會在最後套用。以 0 到 10 分表示,10 為最高分,0 分代表最低。

步驟 5:檢查 Overlay.xml

這項檢查「僅」適用於 Android 11 以上版本。

  1. 查看 overlays.xml,確認您要疊加的所有資源都已在這個檔案中定義。例如,請考慮使用 overlays.xml

    <overlay>
        <item target="string/app_name" value="@string/overlaid_app_name" />
    </overlay>
    
  2. 請務必確保:

    • 目標應用程式中已有 string 項名為「app_name」的資源。
    • RRO 中已有 string 項名為「overlaid_app_name」的資源。
  3. 如果您的目標有 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,瞭解資源解析方式,以及資源解析為與預期不同的值。

  1. 如何在裝置上找到 idmap 的路徑:

    adb shell
    su
    ls data/resource-cache
    
  2. 如何傾印檔案內容:

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

    範例: posix-terminal adb shell idmap2 dump --idmap-path data/resource-cache/system@app@CarUiPortraitLauncherReferenceRRO@CarUiPortraitLauncherReferenceRRO.apk@idmap

    輸出結果會與下列內容相似。輸出結果會顯示 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!!")