Uma sobreposição de recursos no ambiente de execução (RRO) é um pacote que altera os valores de recursos de um pacote de destino no ambiente de execução. Por exemplo, um app instalado no sistema a imagem pode mudar de comportamento com base no valor de um recurso. Em vez de fixar no código o valor do recurso no tempo de build, uma RRO instalada em um pode alterar os valores dos recursos do aplicativo no ambiente de execução.
As RROs podem ser ativadas ou desativadas. Você pode definir programaticamente o ativar/desativar o estado para alternar a capacidade de uma RRO de alterar valores de recursos. RROs ficam desativados por padrão. No entanto, as RROs estáticas são ativadas padrão).
Recursos de sobreposição
As sobreposições funcionam mapeando os recursos definidos no pacote de sobreposição para recursos definidos no pacote de destino. Quando um aplicativo tenta resolver o valor de um no pacote de destino, o valor do recurso de sobreposição que o destino recurso é mapeado será retornado.
Configurar o manifesto
Um pacote é considerado RRO se tiver uma tag <overlay>
como
filho da tag <manifest>
.
O valor do atributo obrigatório
android:targetPackage
especifica o nome. do pacote que a RRO pretende sobrepor.O valor do atributo opcional
android:targetName
especifica o nome do o subconjunto sobreposto de recursos do pacote de destino que a RRO pretende sobreposição. Se o destino não definir um conjunto de recursos sobreposto, este não deve estar presente.
O código a seguir mostra um exemplo de sobreposição 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>
As sobreposições não podem sobrepor código, por isso não podem ter arquivos DEX. Além disso,
Atributo android:hasCode
de <application
> no manifesto precisa ser
Defina como false
.
Definir o mapa de recursos
No Android 11 ou versões mais recentes, o mecanismo recomendado para
definir o mapa de recursos de sobreposição é criar um arquivo no res/xml
do pacote de sobreposição, enumerar os recursos de destino que devem ser
sobrepostas e seus valores de substituição, defina o valor do
android:resourcesMap
da tag de manifesto <overlay>
a uma referência
ao arquivo de mapeamento de recursos.
O código abaixo mostra um exemplo de arquivo 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>
O código a seguir mostra um exemplo de manifesto de sobreposição.
<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>
Criar o pacote
O Android 11 ou versões mais recentes oferecem suporte a uma regra de build Soong para
sobreposições que impedem o Android Asset Packaging Tool 2 (AAPT2) de tentar
eliminar a duplicação de configurações de recursos com o mesmo valor
(--no-resource-deduping
) e da remoção de recursos sem padrão
(--no-resource-removal
). O código a seguir mostra um exemplo
arquivo Android.bp
.
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
Resolver recursos
Se um recurso de destino ou de sobreposição tiver várias configurações definidas para o recurso que está sendo consultado, o ambiente de execução de recursos retorna o valor do que melhor corresponda à configuração do dispositivo. Para determinar qual é a configuração mais adequada, mescle o um conjunto de configurações de recursos de sobreposição no conjunto de recursos de destino e seguir o fluxo regular de resolução de recursos (por exemplo, detalhes, consulte Como o Android encontra as melhores recurso).
Por exemplo, se uma sobreposição define um valor para a configuração drawable-en
e o destino define um valor para drawable-en-port
, drawable-en-port
tem uma correspondência melhor, portanto, o valor da configuração de destino drawable-en-port
é escolhido no tempo de execução. Para sobrepor todas as configurações de drawable-en
, a sobreposição
precisa definir um valor para cada configuração de drawable-en
definida pelo destino.
As sobreposições podem referenciar seus próprios recursos, com comportamentos diferentes entre Versões do Android.
No Android 11 ou versões mais recentes, cada sobreposição tem espaço de ID de recurso reservado que não se sobrepõe ao espaço de ID do recurso de destino ou outros espaços de ID de recurso de sobreposição, de modo que as sobreposições que fazem referência aos próprios recursos funcionar da forma esperada.
No Android 10 ou versões anteriores, as sobreposições e os pacotes de destino compartilham o mesmo recurso ID do cliente, que pode causar colisões e comportamentos inesperados quando tentam para referenciar os próprios recursos usando a sintaxe
@type/name
.
Ativar/desativar sobreposições
Usar a API OverlayManager
para ativar e desativar sobreposições mutáveis (extrair
a interface da API usando Context#getSystemService(Context.OVERLAY_SERVICE)
). Um
sobreposição pode ser ativada somente pelo pacote que ela segmenta ou por um pacote com o
android.permission.CHANGE_OVERLAY_PACKAGES
. Quando uma sobreposição é
ativados ou desativados, os eventos de alteração de configuração são propagados para o pacote de destino
e das atividades de destino.
Restringir recursos sobrepostos
No Android 10 ou versões mais recentes, a tag XML <overlayable>
expõe um conjunto de recursos
que as RROs podem sobrepor. No exemplo a seguir,
O arquivo res/values/overlayable.xml
, string/foo
e integer/bar
são recursos
usado para aplicar temas à aparência do dispositivo; para sobrepor esses recursos, uma sobreposição
precisa segmentar explicitamente o conjunto de recursos que podem ser sobrepostos por nome.
<!-- 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>
Um APK pode definir várias tags <overlayable>
, mas cada tag precisa ter uma tag exclusiva.
dentro do pacote. Por exemplo, ela é:
OK para dois pacotes diferentes definirem
<overlayable name="foo">
.Não é aceitável que um único APK tenha dois blocos
<overlayable name="foo">
.
O código abaixo mostra um exemplo de sobreposição na 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>
Quando um app define uma tag <overlayable>
, as sobreposições que segmentam esse app:
É necessário especificar
targetName
.Pode sobrepor apenas os recursos listados na tag
<overlayable>
.É possível segmentar apenas um nome
<overlayable>
.
Não é possível ativar uma sobreposição que segmenta um pacote que expõe
recursos, mas não usa android:targetName
para visar um
<overlayable>
.
Políticas de restrição
Use a tag <policy>
para aplicar restrições a recursos que podem ser sobrepostos. A
O atributo type
especifica quais políticas uma sobreposição precisa preencher para substituir
os recursos incluídos. Os tipos compatíveis incluem os seguintes.
public
: Qualquer sobreposição pode substituir o recurso.system
: Qualquer sobreposição na partição do sistema pode substituir os recursos.vendor
: Qualquer sobreposição na partição do fornecedor pode substituir os recursos.product
: Qualquer sobreposição na partição do produto pode substituir os recursos.oem
: Qualquer sobreposição na partição do OEM pode substituir os recursos.odm
: Qualquer sobreposição na partição odm pode substituir os recursos.signature
: Qualquer sobreposição assinada com a mesma assinatura do APK de destino pode substituir os recursos.actor
: Qualquer sobreposição assinada com a mesma assinatura do APK do ator pode substituir os recursos. O ator é declarado na tag names-actor do sistema. configuraçãoconfig_signature
: Qualquer sobreposição com a mesma assinatura do O apk overlay-config pode substituir os recursos. O overlay-config é declarado na tag overlay-config-signature na configuração do sistema.
O código a seguir mostra um exemplo de tag <policy>
na
arquivo 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>
Para especificar várias políticas, use barras verticais (|) como caracteres separadores.
Quando várias políticas são especificadas, uma sobreposição precisa atender a apenas uma
para substituir os recursos listados na tag <policy>
.
Configurar sobreposições
O Android oferece suporte a diferentes mecanismos para configurar a mutabilidade, a estado e prioridade das sobreposições, dependendo da versão de lançamento do Android.
Dispositivos com o Android 11 ou versões mais recentes podem usar uma
OverlayConfig
(config.xml
) em vez de atributos de manifesto. Usar um é o método recomendado para sobreposições.Todos os dispositivos podem usar atributos de manifesto (
android:isStatic
eandroid:priority
) para configurar RROs estáticas.
Usar OverlayConfig
No Android 11 ou versões mais recentes, você pode usar OverlayConfig
para
configurar a mutabilidade, o estado padrão e a prioridade das sobreposições. Para configurar
uma sobreposição, crie ou modifique o arquivo localizado em
partition/overlay/config/config.xml
, em que partition
é a partição do
a ser configurada. Para ser configurada, uma sobreposição deve residir no
Diretório overlay/
da partição em que a sobreposição está configurada. A
o código a seguir mostra um exemplo de 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>"
A tag <overlay>
requer um atributo package
que indica qual sobreposição
está sendo configurado. O atributo opcional enabled
controla se
a sobreposição será ativada por padrão (o padrão é false
). O parâmetro opcional
O atributo mutable
controla se a sobreposição é mutável e pode ter
o estado ativado mudou programaticamente no momento da execução (o padrão é true
).
As sobreposições não listadas em um arquivo de configuração são mutáveis e desativadas por
padrão.
Precedência da sobreposição
Quando várias sobreposições substituem os mesmos recursos, a ordem delas é muito importante. Uma sobreposição tem maior precedência do que as sobreposições com configurações anterior à própria configuração. A ordem de precedência de sobreposições em diferentes partições diferentes (da precedência menor para a maior) é a seguinte.
system
vendor
odm
oem
product
system_ext
Mesclar arquivos
O uso de tags <merge>
permite que outros arquivos de configuração sejam mesclados no
no arquivo de configuração. O atributo path
da tag
representa o caminho do arquivo a ser mesclado em relação ao diretório que contém
arquivos de configuração de sobreposição.
Usar atributos de manifesto/RROs estáticas
No Android 10 ou versões anteriores, a imutabilidade e a precedência de sobreposição são configuradas usando os seguintes atributos de manifesto.
android:isStatic
: Quando o valor desse atributo booleano é definido comotrue
, a sobreposição é ativada por padrão e é imutável, o que impede que a sobreposição sejam desativados.android:priority
: O valor desse atributo numérico (que afeta apenas sobreposições estáticas) configura a precedência da sobreposição quando vários as sobreposições segmentam o mesmo valor de recurso. Quanto maior o número, maior precedência.
O código abaixo mostra um exemplo de 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>
Mudanças no Android 11
No Android 11 ou mais recente, se um arquivo de configuração for
localizados em partition/overlay/config/config.xml
, as sobreposições são configuradas usando
esse arquivo e android:isStatic
e android:priority
não afetam
superposições de dados
localizadas na partição. Definir um arquivo de configuração de sobreposição em qualquer
a partição aplica a precedência da partição de sobreposição.
Além disso, o Android 11 ou versões mais recentes removem a capacidade
usar sobreposições estáticas para afetar os valores de recursos lidos durante o pacote
e instalação. Para o caso de uso comum de se usar sobreposições estáticas para alterar o
de booleanos que configuram o estado ativado do componente, use o valor
Tag SystemConfig
<component-override>
(nova no Android)
11).
Depurar sobreposições
Para ativar, desativar e despejar sobreposições manualmente, use a seguinte sobreposição gerenciador de shell do Cloud.
adb shell cmd overlay
OverlayManagerService
usa idmap2
para mapear IDs de recursos no destino.
aos IDs de recursos no pacote de sobreposição. Os mapeamentos de ID gerados são
armazenada em /data/resource-cache/
. Se sua sobreposição não estiver funcionando corretamente, encontre
o arquivo idmap
correspondente para sua sobreposição em /data/resource-cache/
e, em seguida,
execute o comando a seguir.
adb shell idmap2 dump --idmap-path [file]
Esse comando imprime o mapeamento de recursos conforme mostrado abaixo.
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType