Пакет, изменяющий значения ресурсов целевого пакета во время выполнения (RRO), — это пакет, который изменяет значения ресурсов целевого пакета в процессе выполнения. Например, приложение, установленное на образе системы, может изменять свое поведение в зависимости от значения ресурса. Вместо того чтобы жестко задавать значение ресурса во время сборки, пакет RRO, установленный на другом разделе, может изменять значения ресурсов приложения во время выполнения.
RRO можно включать или отключать. Вы можете программно установить состояние включения/отключения, чтобы переключать возможность RRO изменять значения ресурсов. По умолчанию RRO отключены (однако статические RRO включены по умолчанию).
Наложенные ресурсы
Наложения работают путем сопоставления ресурсов, определенных в пакете наложения, с ресурсами, определенными в целевом пакете. Когда приложение пытается получить значение ресурса в целевом пакете, вместо этого возвращается значение ресурса наложения, с которым сопоставлен целевой ресурс.
Настройте манифест.
Пакет считается пакетом RRO, если он содержит тег <overlay> в качестве дочернего элемента тега <manifest> .
Значение обязательного атрибута
android:targetPackageуказывает имя пакета, который RRO намеревается наложить поверх.Значение необязательного атрибута
android:targetNameуказывает имя накладываемого подмножества ресурсов целевого пакета, на который RRO намеревается наложить ресурсы. Если целевой пакет не определяет накладываемый набор ресурсов, этот атрибут не должен присутствовать.
Приведённый ниже код демонстрирует пример наложения в файле AndroidManifest.xml .
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:targetName="OverlayableResources"/>
</manifest>
Наложения не могут накладывать код, поэтому они не могут содержать DEX-файлы. Кроме того, атрибут android:hasCode тега <application в манифесте должен быть установлен в false .
Определите карту ресурсов
В Android 11 и более поздних версиях рекомендуемый механизм определения карты ресурсов наложения заключается в создании файла в каталоге res/xml пакета overlay, перечислении целевых ресурсов, которые должны быть наложены, и их значений замены, а затем установке значения атрибута android:resourcesMap тега манифеста <overlay> на ссылку на файл сопоставления ресурсов.
Приведенный ниже код демонстрирует пример файла res/xml/overlays.xml .
<?xml version="1.0" encoding="utf-8"?>
<overlay xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Overlays string/config1 and string/config2 with the same resource. -->
<item target="string/config1" value="@string/overlay1" />
<item target="string/config2" value="@string/overlay1" />
<!-- Overlays string/config3 with the string "yes". -->
<item target="string/config3" value="@android:string/yes" />
<!-- Overlays string/config4 with the string "Hardcoded string". -->
<item target="string/config4" value="Hardcoded string" />
<!-- Overlays integer/config5 with the integer "42". -->
<item target="integer/config5" value="42" />
</overlay>
Приведённый ниже код демонстрирует пример манифеста наложения.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:targetName="OverlayableResources"
android:resourcesMap="@xml/overlays"/>
</manifest>
Соберите пакет
В Android 11 и более поздних версиях поддерживается правило сборки Soong для оверлеев, которое предотвращает попытки Android Asset Packaging Tool 2 (AAPT2) дедуплицировать конфигурации ресурсов с одинаковым значением ( --no-resource-deduping ) и удалять ресурсы без конфигураций по умолчанию ( --no-resource-removal ). Следующий код демонстрирует пример файла Android.bp .
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
Решить проблему с ресурсами
Если для целевого ресурса или ресурса наложения определено несколько конфигураций, среда выполнения ресурсов возвращает значение той конфигурации, которая наилучшим образом соответствует конфигурации устройства. Чтобы определить, какая конфигурация является наиболее подходящей, объедините набор конфигураций ресурса наложения с набором конфигураций целевого ресурса, а затем следуйте стандартному процессу разрешения ресурсов (подробнее см. в разделе «Как Android находит наиболее подходящий ресурс »).
Например, если наложение определяет значение для конфигурации drawable-en , а целевая платформа определяет значение для drawable-en-port , то drawable-en-port лучше подходит, поэтому во время выполнения выбирается значение конфигурации drawable-en-port целевой платформы. Чтобы наложить все конфигурации drawable-en , наложение должно определить значение для каждой конфигурации drawable-en определенной целевой платформой.
Наложения могут ссылаться на собственные ресурсы, при этом их поведение различается в зависимости от версии Android.
В Android 11 и более поздних версиях каждое наложение имеет собственное зарезервированное пространство идентификаторов ресурсов, которое не пересекается с пространством идентификаторов целевых ресурсов или пространствами идентификаторов ресурсов других наложений, поэтому наложения, ссылающиеся на собственные ресурсы, работают должным образом.
В Android 10 и более ранних версиях наложения и целевые пакеты используют одно и то же пространство идентификаторов ресурсов, что может привести к конфликтам и неожиданному поведению при попытке сослаться на собственные ресурсы с помощью синтаксиса
@type/name.
Включение/отключение наложений
Наложения можно включать/отключать вручную и программно.
Вручную отключите или включите наложения.
Для ручного включения и проверки RRO выполните следующую команду:
adb shell cmd overlay enable --user current com.example.carrro
adb shell cmd overlay list --user current | grep -i com.example com.example.carrro Это включает RRO для системного пользователя ( userId = 0 ), которому принадлежит SystemUI. Эта инструкция не влияет на приложения, запущенные пользователем переднего плана ( userId = 10 ). Чтобы включить RRO для пользователя переднего плана, используйте параметр -–user 10 :
adb shell cmd overlay enable --user 10 com.example.carrroПрограммное включение или отключение наложений.
Используйте API OverlayManager для включения и отключения изменяемых наложений (получите интерфейс API с помощью Context#getSystemService(Context.OVERLAY_SERVICE) ). Наложение может быть включено только целевым пакетом или пакетом с разрешением android.permission.CHANGE_OVERLAY_PACKAGES . При включении или выключении наложения события изменения конфигурации распространяются на целевой пакет, и целевые действия перезапускаются.
Ограничить накладываемые ресурсы
В Android 10 и более поздних версиях XML-тег <overlayable> предоставляет набор ресурсов, которые RRO могут накладывать. В следующем примере файла res/values/overlayable.xml ресурсы string/foo и integer/bar используются для оформления внешнего вида устройства; для наложения этих ресурсов необходимо явно указать имя набора накладываемых ресурсов.
<!-- The collection of resources for theming the appearance of the device -->
<overlayable name="ThemeResources">
<policy type="public">
<item type="string" name="foo/" />
<item type="integer" name="bar/" />
</policy>
...
</overlayable>
В APK-файле можно определить несколько тегов <overlayable> , но каждый тег должен иметь уникальное имя внутри пакета. Например, это:
Допустимо, чтобы два разных пакета определяли
<overlayable name="foo">.Недопустимо, чтобы один APK-файл содержал два блока
<overlayable name="foo">.
Приведённый ниже код демонстрирует пример наложения в файле AndroidManifest.xml .
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.theme.overlay">
<application android:hasCode="false" />
<!-- This overlay will override the ThemeResources resources -->
<overlay android:targetPackage="android" android:targetName="ThemeResources">
</manifest>
Когда приложение определяет тег <overlayable> , создаются наложения, ориентированные на это приложение:
Необходимо указать
targetName.Можно накладывать поверх только ресурсы, перечисленные внутри тега
<overlayable>.Можно выбрать только одно имя
<overlayable>.
Нельзя включить наложение, ориентированное на пакет, который предоставляет ресурсы, доступные для наложения, но не использует android:targetName для выбора конкретного тега <overlayable> .
Ограничить политику
Используйте тег <policy> для применения ограничений к ресурсам, которые можно переналожить. Атрибут type указывает, каким политикам должно соответствовать наложение, чтобы переопределить включенные ресурсы. Поддерживаются следующие типы.
-
public. Любое наложение может переопределить этот ресурс. -
system. Любое наложение на системный раздел может переопределить ресурсы. -
vendor. Любое наложение на раздел поставщика может переопределить ресурсы. -
product. Любое наложение на раздел продукта может переопределить ресурсы. -
oem. Любое наложение на OEM-раздел может переопределить его ресурсы. -
odm. Любое наложение на раздел odm может переопределить ресурсы. -
signature. Любое наложение, подписанное той же подписью, что и целевой APK-файл, может переопределить ресурсы. -
actor. Любое наложение, подписанное той же подписью, что и APK актёра , может переопределить ресурсы. Актёр объявляется в теге named-actor в системной конфигурации. -
config_signature. Любое наложение, подписанное той же подписью, что и APK-файл overlay-config, может переопределить ресурсы. overlay-config объявляется в теге overlay-config-signature в системной конфигурации.
Приведенный ниже код демонстрирует пример использования тега <policy> в файле res/values/overlayable.xml .
<overlayable name="ThemeResources">
<policy type="vendor" >
<item type="string" name="foo" />
</policy>
<policy type="product|signature" >
<item type="string" name="bar" />
<item type="string" name="baz" />
</policy>
</overlayable>
Для указания нескольких политик используйте вертикальные черты (|) в качестве разделительных символов. При указании нескольких политик наложению достаточно соответствовать только одной политике, чтобы переопределить ресурсы, перечисленные в теге <policy> .
Настройка наложений
В зависимости от версии Android, Android поддерживает различные механизмы настройки изменяемости, состояния по умолчанию и приоритета наложений.
На устройствах под управлением Android 11 и выше можно использовать файл
OverlayConfig(config.xml) вместо атрибутов манифеста. Использование файла оверлея — рекомендуемый метод для создания оверлеев.Все устройства могут использовать атрибуты манифеста (
android:isStaticиandroid:priority) для настройки статических RRO.
Используйте OverlayConfig
В Android 11 и более поздних версиях вы можете использовать OverlayConfig для настройки изменяемости, состояния по умолчанию и приоритета наложений. Чтобы настроить наложение, создайте или измените файл, расположенный по адресу partition/overlay/config/config.xml , где partition — это раздел накладываемого наложения. Для настройки наложение должно находиться в каталоге overlay/ того раздела, в котором оно настроено. Следующий код показывает пример файла product/overlay/config/config.xml .
<config>
<merge path="OEM-common-rros-config.xml" />
<overlay package="com.oem.overlay.device" mutable="false" enabled="true" />
<overlay package="com.oem.green.theme" enabled="true" />
</config>"
Тег <overlay> требует атрибута package , указывающего, какой пакет оверлея настраивается. Необязательный атрибут enabled определяет, включено ли оверлей по умолчанию (по умолчанию - false ). Необязательный атрибут mutable определяет, является ли оверлей изменяемым и может ли его состояние включения изменяться программно во время выполнения (по умолчанию - true ). Оверлеи, не указанные в файле конфигурации, являются изменяемыми и отключены по умолчанию.
Приоритет наложения
Когда несколько наложений переопределяют одни и те же ресурсы, порядок их расположения имеет значение. Наложенное соединение имеет более высокий приоритет, чем наложенные соединения, конфигурации которых предшествуют его собственной конфигурации. Порядок приоритета наложений в разных разделах (от наименьшего к наибольшему приоритету) выглядит следующим образом.
-
system -
vendor -
odm -
oem -
product -
system_ext
Объединить файлы
Использование тегов <merge> позволяет объединять другие конфигурационные файлы в указанном месте с данным конфигурационным файлом. Атрибут path тега указывает путь к файлу для объединения относительно каталога, содержащего файлы конфигурации наложения.
Используйте атрибуты манифеста/статические RRO.
В Android 10 и более ранних версиях неизменяемость и приоритет наложений настраиваются с помощью следующих атрибутов манифеста.
android:isStatic. Когда значение этого логического атрибута установлено наtrue, наложение включено по умолчанию и является неизменяемым, что предотвращает его отключение.android:priority. Значение этого числового атрибута (который влияет только на статические наложения) определяет приоритет наложения, когда несколько статических наложений обращаются к одному и тому же значению ресурса. Большее число указывает на более высокий приоритет.
Приведённый ниже код демонстрирует пример файла AndroidManifest.xml .
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:isStatic="true"
android:priority="5"/>
</manifest>
Изменения в Android 11
В Android 11 и более поздних версиях, если файл конфигурации находится в partition/overlay/config/config.xml , наложения настраиваются с использованием этого файла, и android:isStatic и android:priority не влияют на наложения, расположенные в этом же разделе. Определение файла конфигурации наложения в любом разделе обеспечивает приоритет наложений в этом разделе.
Кроме того, в Android 11 и более поздних версиях удалена возможность использования статических наложений для изменения значений ресурсов, считываемых во время установки пакета. Для распространенного случая использования статических наложений для изменения значений логических переменных, определяющих состояние включения компонента, используйте тег SystemConfig <component-override> (новый в Android 11).
Отладочные наложения
Для ручного включения, отключения и удаления наложений используйте следующую команду оболочки диспетчера наложений.
adb shell cmd overlayИспользование enable без указания пользователя влияет на текущего пользователя, то есть на системного пользователя ( userId = 0 ), которому принадлежит системный пользовательский интерфейс. Это не влияет на пользователя переднего плана ( userId = 10 ), которому принадлежат приложения. Чтобы включить RRO для пользователя переднего плана, используйте параметр –-user 10 :
adb shell cmd overlay enable --user 10 com.example.carrroOverlayManagerService использует idmap2 для сопоставления идентификаторов ресурсов в целевом пакете с идентификаторами ресурсов в пакете оверлея. Сгенерированные сопоставления идентификаторов хранятся в /data/resource-cache/ . Если ваш оверлей работает некорректно, найдите соответствующий файл idmap для вашего оверлея в /data/resource-cache/ , а затем выполните следующую команду.
adb shell idmap2 dump --idmap-path [file]Эта команда выводит на экран сопоставление ресурсов, как показано ниже.
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType