การแก้ไขปัญหารันไทม์รีซอร์สโอเวอร์เลย์

ใช้เนื้อหานี้เพื่อแก้ปัญหาว่าทำไม Runtime Resource Overlay (RRO) อาจไม่ทำงานตามที่ตั้งใจไว้ในการใช้งาน Android Automotive

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ RRO ใน Android โปรดดู Runtime Resource Overlays (RRO) ตรวจสอบให้แน่ใจว่าได้เฝ้าระวังเอาต์พุตของ logcat อย่างสม่ำเสมอ ซึ่งสามารถให้ข้อมูลที่ดีเกี่ยวกับสิ่งที่เกิดขึ้นตลอดกระบวนการ

ขั้นตอนที่ 1: แสดงรายการ RROs

ในการแสดงรายการ RROs:

  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 ในตัวอย่างข้างต้น RRO พร้อมใช้งานสำหรับผู้ใช้ 0 และผู้ใช้ 10 (ดูค่าสำหรับ mUserId ในบล็อกโค้ดบนสุด

  3. หากต้องการเปิดใช้งาน (หรือปิดใช้งาน) RRO สำหรับผู้ใช้ที่ต้องการ ให้ไปที่ขั้นตอนที่ 2

  4. ในการตรวจสอบค่าของ 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 :

  1. ตรวจสอบ targetName และ targetPackage

    android:targetName ควรมีค่าเดียวกันกับกลุ่มที่วางซ้อนได้ที่กำหนดไว้ในแอปพลิเคชันเป้าหมาย สิ่งนี้จำเป็น เฉพาะ เมื่อกำหนดเป้าหมายการวางซ้อน

    android:targetPackage จำเป็นเสมอและควรมีชื่อแพ็คเกจของแอปพลิเคชันเป้าหมาย

  2. ตรวจสอบว่า RRO ของคุณเป็นแบบคงที่ (หรือไม่) RRO แบบคงที่จะเปิดใช้งานโดยค่าเริ่มต้นในเวลาบูต RRO แบบไดนามิกไม่ได้เปิดใช้งานตามค่าเริ่มต้นเมื่อเปิดเครื่อง มีวิธีการเพิ่มเติมในการเปิดใช้งาน RRO แบบไดนามิกใน Runtime Resource Overlays (RRO)

  3. ตรวจสอบลำดับความสำคัญของ RRO แบบคงที่ของคุณ (คุณไม่สามารถตรวจสอบลำดับความสำคัญของ RRO แบบไดนามิกได้)

    RRO หลายรายการอาจนำไปใช้กับเป้าหมายเดียวกัน RRO ที่มีลำดับความสำคัญสูงกว่าจะถูกนำมาใช้เป็นลำดับสุดท้าย ในระดับ 0 ถึง 10 0 คือสูงสุดและ 10 คือต่ำสุด

ขั้นตอนที่ 5: ตรวจสอบ overlays.xml

การตรวจสอบนี้ใช้กับ Android 11 เท่านั้น (และสูงกว่า)

  1. ตรวจสอบ overlays.xml เพื่อยืนยันทรัพยากรทั้งหมดที่คุณต้องการวางซ้อนในไฟล์นี้ ตัวอย่างเช่น พิจารณา overlays.xml ต่อไปนี้:

    <overlay>
        <item target="string/app_name" value="@string/overlaid_app_name" />
    </overlay>
    
  2. คุณต้องแน่ใจว่า a:

    • ทรัพยากร string ที่มีชื่อ app_name มีอยู่ในแอปเป้าหมาย
    • ทรัพยากร string ที่มีชื่อ overlaid_app_name มีอยู่ใน RRO ของคุณ
  3. หากเป้าหมายของคุณมีไฟล์ overlayable.xml ตรวจสอบให้แน่ใจว่า app_name มีอยู่ในไฟล์นั้น ตรวจสอบให้แน่ใจว่าคุณใช้ targetName ที่ถูกต้องในไฟล์ AndroidManifest.xml (ขั้นตอนที่ 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 ของคุณควรได้รับการแก้ไข ถัดไป ดัมพ์ idmap ของ RRO ของคุณเพื่อเรียนรู้ว่าทรัพยากรได้รับการแก้ไขอย่างไร และเหตุใดทรัพยากรจึงถูกแก้ไขเป็นค่าอื่นที่คุณคาดหวัง

  1. วิธีค้นหาเส้นทางไปยัง idmap บนอุปกรณ์ของคุณ:

    adb shell
    su
    ls data/resource-cache
    
  2. ในการดัมพ์เนื้อหาของไฟล์นั้น:

    idmap2 dump --idmap-path [path to your RRO idmap file]
    

    ผลลัพธ์ที่ปรากฏคล้ายกับต่อไปนี้ ผลลัพธ์แสดงว่า ID จาก RRO ของคุณถูกแมปกับ 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
    

คุณยังสามารถดัมพ์ไฟล์เลย์เอาต์จาก 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!!")