自定義應用程序

既然將 Car UI 庫組件和資源放入應用程序中,為了自定義這些應用程序,OEM 必須提供兩個疊加層:

  • 構建時覆蓋。這是覆蓋將添加 RRO 所需的任何資源。這包括:

    • 可繪製對象
    • 樣式(例如,文本外觀)
    • 共享資源(例如顏色)

  • RRO 覆蓋。此文件夾包含用於為每個目標應用程序生成一個 RRO 的資源。這些資源只能參考:

    • 在同一 RRO 中定義的值(例如,對於顏色,這將是一個十六進制值)。
    • Android 框架資源(例如,@android @android:color/accent )。
    • 在上述構建時覆蓋中定義的資源。

一般結構

建議的定制覆蓋結構如下:

  • <path-to-OEM-overlays>/

    • overlay/framework/base/core/res/ 。構建時覆蓋資源

    • rro/

      • Android.mk 。 Makefile 用於根據此文件夾中包含的資源為每個目標包生成 RRO。

      • AndroidManifest.xml 。上述 makefile 使用的清單文件模板。

      • res/ 。適用於所有目標應用程序的運行時覆蓋。

OEM 可能擁有多個這些結構,具體取決於他們希望在單個構建目標中處理的品牌數量(請參閱處理多個品牌)。

運行時資源覆蓋

OEM 覆蓋文件夾中的 RRO 文件夾應包含要應用於所有目標應用程序的資源。 RRO 具有影響其覆蓋複合資源的能力的局限性。總之,RRO:

  • 無法引用目標 APK 或 RRO 本身中定義的資源標識符。這意味著 RRO 不能添加新的標識符,例如新的可繪製對象、顏色或樣式。

  • 指框架中定義的資源標識符,無論這些資源是在/frameworks/base/core/res中定義還是通過構建時覆蓋定義。這些標識符必須使用android:命名空間來引用:

    • 對於公共DeviceDefault RRO,請使用android
      例如, @android:style/TextAppearance.DeviceDefault.Large

    • 對於所有其他人 (非公共或通過構建時覆蓋添加的資源),使用*android
      例如, @*android/style:TextAppearance.OEM.Brand1.Title

除了資源之外,RRO 文件夾還必須包含:

  • AndroidManifest.xml 。在下面的示例中, RRO_PACKAGE_NAMETARGET_PACKAGE_NAME是 makefile 的佔位符:

    <?xml version=“1.0” encoding=“utf-8”?>
    <manifest xmlns:android=“http://schemas.android.com/apk/res/android”
        package=“{{RRO_PACKAGE_NAME}}” />
        <application android:hasCode=“false” />
        <overlay android:priority=“10”
            Android:targetPackage=“{{TARGET_PACKAGE_NAME}}”
            Android:requiredSystemPropertyName=“ro.product.sku”
            Android:requiredSystemPropertyValue=“<your-product-sku>” />
    </manifest>
    
  • Android.mk ,其中以下 makefile 中的oem定義了所有生成的 RRO 將具有的前綴。
      LOCAL_PATH := $(call my-dir)
      include $(CLEAR_VARS)
      CAR_UI_RRO_SET_NAME := oem
      CAR_UI_RESOURCE_DIR := $(LOCAL_PATH)/res
      CAR_UI_RRO_TARGETS := $(CAR_UI_RRO_PACKAGE_NAMES)
      include packages/apps/Car/libs/car-ui-lib/generate_rros.mk
      

配置 RRO 覆蓋

支持一個新的配置文件overlayable.xml ,您可以使用它來定義訪問控制。例如,您可以指定誰可以覆蓋資源以及可以覆蓋哪些資源。因此,現在可以以不同的方式對資源進行分組,以使它們可以被不同的 RRO 覆蓋。

要設置 RRO 訪問控制:

  1. res/values文件夾中,創建overlayable.xml
  2. 創建<overlayable>資源標籤。
  3. <overlayable>標籤定義name屬性,該標籤在包中必須是唯一的。每個疊加層只能針對一個可疊加組。
  4. <overlayable>中定義<policy>標籤。
  5. 定義可以覆蓋的資源組。例如:
      <resources>
          <overlayable name="OverlayableResources">
              <policy type="public">
                  <item type="string" name="app_title" />
              </policy>
          </overlayable>
      </resources>
      

將以下更改應用於您的 RRO 項目:

  1. res/xml文件夾中,創建overlays.xml 。有關overlay ,請參見下面代碼示例中的條目。
  2. 定義要覆蓋的資源。
  3. android:resourcesMap="@xml/overlays"添加到AndroidManifest.xml<overlay>標記中。例如,在下面的代碼示例中,請參閱<overlay>的條目。
  4. 為靜態覆蓋設置android:isStatic=”true” 。每個覆蓋只能針對可以覆蓋的組之一。

考慮以下示例。第一部分屬於AndroidManifest.xml ,而第二部分屬於overlays.xml

  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.android.car.ui.rro"
      android:versionCode="1"
      android:versionName="1.0">
      <overlay android:targetName="OverlayableResources"
               android:resourcesMap="@xml/overlays"
               android:targetPackage="com.android.car.ui"
               android:priority="1"
               android:isStatic="false" />
  </manifest>
  <overlay>
      <item target="string/app_title" value="@ string/app_title" />
  </overlay>
  

需要注意的是,以前存在的 RRO 將繼續在 Android 10 中運行。需要注意的是,要與 PackageManagerRRO 一起安裝,包必須預先安裝或使用與目標應用相同的密鑰進行簽名。在 Android 10 中,佈局文件可以疊加。但是,這樣做需要在獲取視圖時使用requireViewById()而不是findViewById() 。在 Android 10 中,此更改已實施到 car-ui-lib 以支持佈局疊加。

Android 的下一個主要版本將使您能夠覆蓋佈局文件並在 RRO 包中定義新資源並在內部引用它們。

添加 OEM 特定資源

要克服阻止添加 OEM 資源的 RRO 限制:

  • 使用構建時覆蓋擴展框架/基礎,添加任何必要的資源。
  • 使用*android:命名空間參考來自 OEM RRO 的這些資源。

例如,以下是添加 OEM 特定可繪製對象並在 RRO 中使用它的方法:

  • <path-to-OEM-overlays>

    • overlay/framework/base/core/res/res/drawable/

      • oem_background_drawable.xml

    • rro/res/values

      • drawables.xml

        <resources>
            <item type="drawable" name="car_ui_toolbar_background">
                @*android:drawable/oem_background_drawable
            </item>
        </resources>
        

處理多個品牌

RRO 清單文件具有允許根據系統屬性有條件地應用它們的語法。要在單個系統映像中處理多個品牌,OEM 可以按如下方式使用它(請參閱一般結構)。

<?xml version=“1.0” encoding=“utf-8”?>
<manifest xmlns:android=“http://schemas.android.com/apk/res/android”
    package=“{{RRO_PACKAGE_NAME}}”/>
    <application android:hasCode=“false”/>
    <overlay android:priority=“10”
        Android:targetPackage=“{{TARGET_PACKAGE_NAME}}”
        Android:requiredSystemPropertyName=“ro.product.sku”
        Android:requiredSystemPropertyValue=“<your-product-sku>”/>
</manifest>

android:requiredSystemPropertyNameandroid:requiredSystemPropertyValue的語法將導致當相應的系統屬性與提供的值匹配時才啟用此 RRO。然後,OEM 可以定義多個這些 RRO,所有這些 RRO 都是靜態啟用的,並且一次只有一個處於活動狀態。

將汽車 UI 庫添加到目標

要將 Car UI 庫合併到 Android 目標,您必須包含以下代碼片段:

# Include build-time overlays
    PRODUCT_PACKAGE_OVERLAYS += \
      <path-to-oem-overlays>/overlay
    # Define package names to generate RROs for
    CAR_UI_RRO_PACKAGE_NAMES += \
      com.android.car.ui.paintbooth \
      com.android.car.media \
      com.android.car.dialer \
      com.android.car.linkviewer \
      com.android.car.settings \
      com.android.car.systemupdater \
      com.google.android.apps.automotive.inputmethod \
      com.google.android.apps.automotive.templates.host \
      ...
    # Include generated RROs
    PRODUCT_PACKAGES += \
      oem-com-android-car-ui-paintbooth \
      oem-com-android-car-media \
      oem-com-android-car-dialer \
      oem-com-android-car-linkviewer \
      oem-com-android-car-settings \
      oem-com-android-car-systemupdater \
      oem-com-google-android-apps-automotive-inputmethod \
      oem-com-google-android-apps-automotive-templates-host \
      ...
  • 導致<path-to-OEM-overlays>/rro/Android.mkCAR_UI_RRO_PACKAGE_NAMES中命名的每個包生成一個 RRO。

  • PRODUCT_PACKAGES中包含生成的 RRO。

  • PRODUCT_PACKAGE_OVERLAYS中包含構建時覆蓋以添加 OEM 特定資源。

要了解哪些包支持car-ui-lib ,請參閱car-ui-lib 支持的包