Gestire i file manifest

In questa pagina viene descritto come funziona l'unione del manifest e come puoi applicare le preferenze di unione per risolvere i conflitti di unione. Per un'introduzione al file manifest dell'app, consulta la panoramica del file manifest dell'app.

Unisci più file manifest

Il tuo file APK o Android App Bundle può contenere un solo file AndroidManifest.xml, ma il tuo progetto Android Studio potrebbe contenere diversi file manifest forniti dal set di origine principale, dalle varianti della build e dalle librerie importate. Quando crei la tua app, la build Gradle unisce tutti i file manifest in un unico file manifest pacchettizzato nella tua app.

Lo strumento di unione dei file manifest combina tutti gli elementi XML di ogni file seguendo l'euristica di unione e rispettando le preferenze di unione che hai definito con attributi XML speciali.

Suggerimento: usa la visualizzazione Manifest unito, descritta in una sezione che segue, per visualizzare l'anteprima dei risultati del file manifest unito e trovare gli errori di conflitto.

Unisci priorità

Lo strumento di unione combina tutti i file manifest in un unico file in sequenza, in base alla priorità di ciascun file manifest. Ad esempio, se hai tre file manifest, quello con priorità più bassa viene unito a quello con la priorità più alta, che viene poi unito nel file manifest con la priorità più alta, come mostrato nella Figura 1.

Figura 1. Il processo per unire tre file manifest, con priorità più bassa a priorità più alta.

Esistono tre tipi di file manifest di base che possono essere uniti l'uno all'altro e le relative priorità di unione sono le seguenti (prima la priorità più alta):

  1. File manifest per la variante della build

    Se hai più set di origini per la variante, le priorità del file manifest sono le seguenti:

    • Manifest della variante di build (ad esempio src/demoDebug/)
    • Manifest del tipo di build (ad esempio src/debug/)
    • File manifest dei gusti del prodotto (ad esempio src/demo/)

      Se utilizzi le dimensioni personalizzate, le priorità del file manifest corrispondono all'ordine in cui ogni dimensione è elencata nella proprietà flavorDimensions (la prima è la priorità più alta).

  2. File manifest principale per il modulo dell'app
  3. File manifest da una libreria inclusa

    Se hai più librerie, le priorità dei manifest corrispondono all'ordine in cui vengono visualizzate nel blocco dependencies di Gradle.

Ad esempio, il manifest di una libreria viene unito nel manifest principale, quindi il manifest principale viene unito nel manifest della variante della build. Tieni presente che si tratta delle stesse priorità di unione per tutti i set di origini, come descritto in Creare con set di origini.

Importante: le configurazioni di build dal file build.gradle sostituiscono qualsiasi attributo corrispondente nel file manifest unito. Ad esempio, minSdk del file build.gradle o build.gradle.kts sostituisce l'attributo corrispondente nell'elemento manifest <uses-sdk>. Per evitare confusione, escludi l'elemento <uses-sdk> e definisci queste proprietà solo nel file build.gradle. Per ulteriori dettagli, consulta Configurare la build.

Unisci euristiche dei conflitti

Lo strumento di unione può associare logicamente ogni elemento XML di un manifest a un elemento corrispondente in un altro manifest. Per maggiori dettagli su come funziona la corrispondenza, consulta la sezione sull'unione delle priorità nella sezione precedente.

Se un elemento del file manifest con priorità più bassa non corrisponde ad alcun elemento del file manifest con priorità più alta, viene aggiunto al manifest unito. Tuttavia, se esiste un elemento corrispondente, lo strumento di unione tenta di combinare tutti gli attributi di ogni elemento nello stesso elemento. Se lo strumento rileva che entrambi i file manifest contengono lo stesso attributo con valori diversi, si verifica un conflitto di unione.

La tabella 1 mostra i possibili risultati quando lo strumento di fusione tenta di combinare tutti gli attributi nello stesso elemento.

Tabella 1. Comportamento predefinito di unione per i valori degli attributi

Attributo ad alta priorità Attributo a bassa priorità Risultato unito dell'attributo
Per niente preziosa Per niente preziosa Nessun valore (utilizza il valore predefinito)
Valore B Valore B
Valore A Per niente preziosa Valore A
Valore A Valore A
Valore B Errore in conflitto: devi aggiungere un indicatore delle regole di unione.

Tuttavia, esistono alcune situazioni in cui lo strumento di unione si comporta in modo diverso per evitare conflitti di unione:

  • Gli attributi nell'elemento <manifest> non vengono mai uniti, ma vengono utilizzati solo gli attributi del file manifest con la massima priorità.
  • L'attributo android:required negli elementi <uses-feature> e <uses-library> utilizza un'unione OR. In caso di conflitto, viene applicato "true" e la funzionalità o la libreria richiesta da un file manifest è sempre inclusa.
  • Gli attributi dell'elemento <uses-sdk> utilizzano sempre il valore del manifest con priorità più alta, tranne nelle seguenti situazioni:
    • Quando il manifest con priorità più bassa ha un valore minSdk superiore, si verifica un errore, a meno che non applichi la regola di unione overrideLibrary.
    • Quando il file manifest con priorità inferiore ha un valore targetSdkVersion inferiore, lo strumento di unione utilizza il valore del file manifest con priorità più alta e aggiunge anche le eventuali autorizzazioni di sistema necessarie per garantire che la libreria importata continui a funzionare correttamente (per i casi in cui la versione successiva di Android presenta maggiori limitazioni relative alle autorizzazioni). Per ulteriori informazioni su questo comportamento, consulta la sezione sulle autorizzazioni di sistema implicite.
  • L'elemento <intent-filter> non corrisponde mai ai file manifest. Ciascuno viene considerato univoco e viene aggiunto all'elemento principale comune nel manifest unito.

Per tutti gli altri conflitti tra attributi, ricevi un errore e devi indicare allo strumento di unione come risolverlo aggiungendo un attributo speciale nel file manifest con priorità più alta. Consulta la seguente sezione sull'unione degli indicatori delle regole.

Non dipendere dai valori predefiniti degli attributi. Poiché tutti gli attributi univoci vengono combinati nello stesso elemento, potrebbero verificarsi risultati imprevisti se il manifest con priorità più alta dipende in realtà dal valore predefinito di un attributo senza dichiararlo. Ad esempio, se il manifest con priorità più alta non dichiara l'attributo android:launchMode, verrà utilizzato il valore predefinito "standard". Tuttavia, se il manifest con priorità più bassa dichiara questo attributo con un valore diverso, questo valore viene applicato al manifest unito, sostituendo il valore predefinito. Dovresti definire esplicitamente ogni attributo come preferisci. I valori predefiniti per ogni attributo sono documentati nel riferimento del file manifest.

Unisci indicatori delle regole

Un indicatore delle regole di unione è un attributo XML che puoi utilizzare per esprimere la tua preferenza su come risolvere i conflitti di unione o rimuovere elementi e attributi indesiderati. Puoi applicare un indicatore a un intero elemento o solo ad attributi specifici di un elemento.

Quando unisci due file manifest, lo strumento di unione cerca questi indicatori nel file manifest con priorità più alta.

Tutti gli indicatori appartengono allo spazio dei nomi tools di Android, quindi devi prima dichiarare questo spazio dei nomi nell'elemento <manifest>, come mostrato qui:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp"
    xmlns:tools="http://schemas.android.com/tools">

Indicatori di nodo

Per applicare una regola di unione a un intero elemento XML (a tutti gli attributi di un determinato elemento manifest e a tutti i relativi tag figlio), utilizza i seguenti attributi:

tools:node="merge"
Quando non ci sono conflitti, unisci tutti gli attributi in questo tag e tutti gli elementi nidificati utilizzando l'euristica dei conflitti di unione. Questo è il comportamento predefinito per gli elementi.

Manifest con priorità bassa:

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Manifest con priorità elevata:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:node="merge">
</activity>

Risultato del file manifest unito:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
tools:node="merge-only-attributes"
Unisci solo gli attributi in questo tag; non unire gli elementi nidificati.

Manifest con priorità bassa:

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <data android:type="image/*" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Manifest con priorità elevata:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:node="merge-only-attributes">
</activity>

Risultato del file manifest unito:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
</activity>
tools:node="remove"
Rimuovi questo elemento dal manifest unito. Categoria relativa a un elemento fornito da un file manifest con priorità inferiore che non è sotto il tuo controllo nel file manifest unito, ad esempio una libreria importata.

Manifest con priorità bassa:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="cow"
      android:value="@string/moo"/>
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>

Manifest con priorità elevata:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="cow"
      tools:node="remove"/>
</activity-alias>

Risultato del file manifest unito:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>
tools:node="removeAll"
Simile a tools:node="remove", ma rimuove tutti gli elementi che corrispondono a questo tipo di elemento (all'interno dello stesso elemento principale).

Manifest con priorità bassa:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="cow"
      android:value="@string/moo"/>
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>

Manifest con priorità elevata:

<activity-alias android:name="com.example.alias">
  <meta-data tools:node="removeAll"/>
</activity-alias>

Risultato del file manifest unito:

<activity-alias android:name="com.example.alias">
</activity-alias>
tools:node="replace"
Sostituisci completamente l'elemento con priorità più bassa. In altre parole, se esiste un elemento corrispondente nel file manifest con priorità più bassa, ignoralo e utilizza questo elemento esattamente come appare nel file manifest.

Manifest con priorità bassa:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="cow"
      android:value="@string/moo"/>
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>

Manifest con priorità elevata:

<activity-alias android:name="com.example.alias"
    tools:node="replace">
  <meta-data android:name="fox"
      android:value="@string/dingeringeding"/>
</activity-alias>

Risultato del file manifest unito:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="fox"
      android:value="@string/dingeringeding"/>
</activity-alias>
tools:node="strict"
Genera un errore di build ogni volta che questo elemento nel file manifest con priorità inferiore non corrisponde esattamente all'elemento nel file manifest con priorità più alta (a meno che non venga risolto da altri indicatori delle regole di unione). Questa operazione sostituisce l'euristica dei conflitti di unione. Ad esempio, se il manifest con priorità inferiore include un attributo aggiuntivo, la build non riesce (mentre il comportamento predefinito aggiunge l'attributo in più al manifest unito).

Manifest con priorità bassa:

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Manifest con priorità elevata:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:node="strict">
</activity>

Viene creato un errore di unione del manifest. I due elementi del manifest non possono differire affatto in modalità restrittiva. Devi applicare altri indicatori delle regole di unione per risolvere queste differenze. Senza tools:node="strict", questi due file possono essere uniti senza errori, come mostrato nell'esempio per tools:node="merge".

Indicatori attributo

Per applicare una regola di unione solo ad attributi specifici in un tag manifest, utilizza i seguenti attributi. Ogni attributo accetta uno o più nomi di attributi (incluso lo spazio dei nomi dell'attributo), separati da virgole.

tools:remove="attr, ..."
Rimuovi gli attributi specificati dal manifest unito. Utilizzato quando il file manifest con priorità inferiore include questi attributi e vuoi assicurarti che non vengano inseriti nel manifest unito.

Manifest con priorità bassa:

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">

Manifest con priorità elevata:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:remove="android:windowSoftInputMode">

Risultato del file manifest unito:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait">
tools:replace="attr, ..."
Sostituisci gli attributi specificati nel manifest con priorità inferiore con quelli di questo manifest. In altre parole, mantieni sempre i valori del manifest con priorità più alta.

Manifest con priorità bassa:

<activity android:name="com.example.ActivityOne"
    android:theme="@oldtheme"
    android:exported="false"
    android:windowSoftInputMode="stateUnchanged">

Manifest con priorità elevata:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    tools:replace="android:theme,android:exported">

Risultato del file manifest unito:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
tools:strict="attr, ..."
Genera un errore di build ogni volta che questi attributi nel manifest con priorità inferiore non corrispondono esattamente agli attributi nel manifest con priorità più alta. Questo è il comportamento predefinito per tutti gli attributi, ad eccezione di quelli con comportamenti speciali, come descritto nell'euristica dei conflitti di unione.

Manifest con priorità bassa:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="landscape">
</activity>

Manifest con priorità elevata:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:strict="android:screenOrientation">
</activity>

Viene creato un errore di unione del manifest. Devi applicare altri indicatori delle regole di unione per risolvere il conflitto. Questo è il comportamento predefinito, quindi si verifica lo stesso risultato aggiungendo esplicitamente tools:strict="screenOrientation".

Puoi anche applicare più indicatori a un singolo elemento, come illustrato nell'esempio seguente:

Manifest con priorità bassa:

<activity android:name="com.example.ActivityOne"
    android:theme="@oldtheme"
    android:exported="false"
    android:allowTaskReparenting="true"
    android:windowSoftInputMode="stateUnchanged">

Manifest con priorità elevata:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    tools:replace="android:theme,android:exported"
    tools:remove="android:windowSoftInputMode">

Risultato del file manifest unito:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:allowTaskReparenting="true"
    android:screenOrientation="portrait">

Selettore indicatore

Se vuoi applicare gli indicatori delle regole di unione solo a una specifica libreria importata, aggiungi l'attributo tools:selector con il nome del pacchetto delle librerie.

Ad esempio, con il seguente manifest, la regola di unione remove viene applicata solo se il file manifest con priorità più bassa appartiene alla libreria com.example.lib1:

<permission android:name="permissionOne"
    tools:node="remove"
    tools:selector="com.example.lib1">

Se il manifest con priorità inferiore proviene da un'altra origine, la regola di unione remove viene ignorata.

Nota: se lo utilizzi con uno degli indicatori di attributo, viene applicato a tutti gli attributi specificati nell'indicatore.

Esegui l'override di <uses-sdk> per le librerie importate

Per impostazione predefinita, quando importi una libreria con un valore minSdk superiore a quello del file manifest principale, si verifica un errore e la libreria non può essere importata.

Per fare in modo che lo strumento di unione ignori questo conflitto e importa la libreria mantenendo il valore minSdk più basso dell'app, aggiungi l'attributo overrideLibrary al tag <uses-sdk>. Il valore dell'attributo può corrispondere a uno o più nomi di pacchetti di librerie (separati da virgole), a indicare le librerie che possono eseguire l'override del minSdk del manifest principale.

Ad esempio, se il file manifest principale dell'app si applica overrideLibrary come segue:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.app"
          xmlns:tools="http://schemas.android.com/tools">
  <uses-sdk tools:overrideLibrary="com.example.lib1, com.example.lib2"/>
...

Quindi il seguente manifest può essere unito senza un errore relativo al tag <uses-sdk> e il manifest unito conserva minSdk="2" dal file manifest dell'app.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.lib1">
   <uses-sdk android:minSdk="4" />
...

Autorizzazioni di sistema implicite

Alcune API per Android che un tempo erano accessibili senza costi dalle app sono state limitate dalle autorizzazioni di sistema nelle versioni recenti di Android.

Per evitare di danneggiare le app che si aspettano di accedere a queste API, le versioni recenti di Android consentono alle app di continuare ad accedere alle API senza l'autorizzazione se il valore targetSdkVersion è impostato su un valore inferiore alla versione in cui è stata aggiunta la limitazione. Questo comportamento concede all'app un'autorizzazione implicita per consentire l'accesso alle API. Possono essere interessati i manifest uniti che hanno valori diversi per targetSdkVersion.

Se il file manifest con priorità inferiore ha un valore inferiore per targetSdkVersion che fornisce un'autorizzazione implicita e il manifest con priorità più alta non ha la stessa autorizzazione implicita (perché il suo targetSdkVersion è uguale o superiore alla versione in cui è stata aggiunta la limitazione), lo strumento di unione aggiunge esplicitamente l'autorizzazione di sistema al manifest unito.

Ad esempio, se l'app imposta targetSdkVersion su 4 o un numero successivo e importa una libreria con targetSdkVersion impostato su 3 o su un valore inferiore, lo strumento di unione aggiunge l'autorizzazione WRITE_EXTERNAL_STORAGE al manifest unito.

La tabella 2 elenca tutte le possibili autorizzazioni che potrebbero essere aggiunte al manifest unito:

Tabella 2. Elenco di autorizzazioni che lo strumento di unione potrebbe aggiungere al manifest unito

Il file manifest con priorità più bassa dichiara Autorizzazioni aggiunte al manifest unito
targetSdkVersion è pari o inferiore a 3 WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
targetSdkVersion è pari o inferiore a 15 e utilizza READ_CONTACTS READ_CALL_LOG
targetSdkVersion è pari o inferiore a 15 e utilizza WRITE_CONTACTS WRITE_CALL_LOG

Esamina il manifest unito e individua i conflitti

Ancora prima di creare l'app, puoi visualizzare un'anteprima del file manifest unito. Per visualizzare un'anteprima, procedi nel seguente modo:

  1. In Android Studio, apri il file AndroidManifest.xml.
  2. Fai clic sulla scheda Manifest unito nella parte inferiore dell'editor.

La visualizzazione Manifest unito mostra i risultati del file manifest unito a sinistra e le informazioni su ciascun file manifest unito a destra, come mostrato nella Figura 2.

Gli elementi uniti dai file manifest con priorità inferiore sono evidenziati con colori diversi a sinistra. La chiave per ogni colore è specificata in Origini manifest.

Figura 2. Visualizzazione Manifest unito.

I file manifest che facevano parte della build, ma che non hanno fornito elementi o attributi sono elencati nella sezione Altri file manifest.

Per visualizzare le informazioni sulla provenienza di un elemento, fai clic sull'elemento nel riquadro a sinistra e i dettagli verranno visualizzati in Log di unione.

Gli eventuali conflitti vengono visualizzati in Errori di unione con un suggerimento su come risolverlo utilizzando gli indicatori delle regole di unione.

Gli errori vengono stampati anche nella finestra Log eventi. Per visualizzarli, seleziona Visualizza > Finestre degli strumenti > Log eventi.

Per visualizzare un log completo della struttura decisionale per l'unione, puoi trovare il file di log nella directory build/outputs/logs/ del modulo, denominata manifest-merger-buildVariant-report.txt.

Unisci criteri

Lo strumento di unione dei manifest può associare logicamente ogni elemento XML di un file manifest a un elemento corrispondente in un altro file. La fusione associa ogni elemento utilizzando una chiave di corrispondenza, ovvero un valore di attributo univoco (come android:name) o l'unicità naturale del tag stesso (ad esempio, può esistere un solo elemento <supports-screen>).

Se due manifest hanno lo stesso elemento XML, lo strumento unisce i due elementi utilizzando uno dei tre criteri di unione:

Unisci
Combina tutti gli attributi non in conflitto nello stesso tag e unisci gli elementi secondari in base al rispettivo criterio di unione. Se alcuni attributi sono in conflitto tra loro, uniscili con gli indicatori delle regole di unione.
Unisci solo i publisher secondari
Non combinare o unire gli attributi (mantieni solo gli attributi forniti dal file manifest con la priorità più alta) e non unire gli elementi secondari in base ai rispettivi criteri di unione.
Conserva
Lascia l'elemento così com'è e aggiungilo all'elemento principale comune nel file unito. Viene utilizzato solo quando è accettabile che esistano più dichiarazioni dello stesso elemento.

Nella tabella 3 sono elencati ogni tipo di elemento, il tipo di criterio di unione utilizzato e la chiave utilizzata per determinare una corrispondenza di elementi tra due manifest:

Tabella 3. Le norme di unione degli elementi manifest e le chiavi di corrispondenza

Elemento Criterio di unione Chiave di corrispondenza
<action> Unisci Attributo android:name
<activity> Unisci Attributo android:name
<application> Unisci Ce n'è una sola per <manifest>.
<category> Unisci Attributo android:name
<data> Unisci Ce n'è una sola per <intent-filter>.
<grant-uri-permission> Unisci Ce n'è una sola per <provider>.
<instrumentation> Unisci Attributo android:name
<intent-filter> Conserva Nessuna corrispondenza; sono consentite diverse dichiarazioni all'interno dell'elemento principale.
<manifest> Unisci solo i publisher secondari È disponibile un solo file per file.
<meta-data> Unisci Attributo android:name
<path-permission> Unisci Ce n'è una sola per <provider>.
<permission-group> Unisci Attributo android:name
<permission> Unisci Attributo android:name
<permission-tree> Unisci Attributo android:name
<provider> Unisci Attributo android:name
<receiver> Unisci Attributo android:name
<screen> Unisci Attributo android:screenSize
<service> Unisci Attributo android:name
<supports-gl-texture> Unisci Attributo android:name
<supports-screen> Unisci Ce n'è una sola per <manifest>.
<uses-configuration> Unisci Ce n'è una sola per <manifest>.
<uses-feature> Unisci Attributo android:name (se non presente, l'attributo android:glEsVersion)
<uses-library> Unisci Attributo android:name
<uses-permission> Unisci Attributo android:name
<uses-sdk> Unisci Ce n'è una sola per <manifest>.
Elementi personalizzati Unisci Nessuna corrispondenza; sono sconosciute allo strumento di unione e sono sempre incluse nel manifest unito.

Inserisci le variabili di build nel manifest

Se devi inserire nel file AndroidManifest.xml variabili definite nel file build.gradle, puoi farlo con la proprietà manifestPlaceholders. Questa proprietà accetta una mappa di coppie chiave-valore, come mostrato qui:

Trendy

android {
    defaultConfig {
        manifestPlaceholders = [hostName:"www.example.com"]
    }
    ...
}

Kotlin

android {
    defaultConfig {
        manifestPlaceholders["hostName"] = "www.example.com"
    }
    ...
}

Puoi quindi inserire uno dei segnaposto nel file manifest come valore dell'attributo:

<intent-filter ... >
    <data android:scheme="https" android:host="${hostName}" ... />
    ...
</intent-filter>

Per impostazione predefinita, gli strumenti di creazione forniscono anche l'ID applicazione dell'app nel segnaposto ${applicationId}. Il valore corrisponde sempre all'ID applicazione finale per la build corrente, incluse le modifiche per le varianti di build. Questo è utile quando vuoi utilizzare uno spazio dei nomi univoco per gli identificatori, ad esempio un'azione intent, anche tra le varianti della build.

Ad esempio, se il tuo file build.gradle ha il seguente aspetto:

Trendy

android {
    defaultConfig {
        applicationId "com.example.myapp"
    }
    flavorDimensions "type"
    productFlavors {
        free {
            applicationIdSuffix ".free"
            dimension "type"
        }
        pro {
            applicationIdSuffix ".pro"
            dimension "type"
        }
    }
}

Kotlin

android {
    defaultConfig {
        applicationId = "com.example.myapp"
    }
    flavorDimensions += "type"
    productFlavors {
        create("free") {
            applicationIdSuffix = ".free"
            dimension = "type"
        }
        create("pro") {
            applicationIdSuffix = ".pro"
            dimension = "type"
        }
    }
}

Poi potrai inserire l'ID applicazione nel file manifest nel seguente modo:

<intent-filter ... >
    <action android:name="${applicationId}.TRANSMOGRIFY" />
    ...
</intent-filter>

Il risultato del manifest quando crei la versione di prodotto "senza costi" è questo:

<intent-filter ... >
   <action android:name="com.example.myapp.free.TRANSMOGRIFY" />
    ...
</intent-filter>

Per ulteriori informazioni, consulta Impostare l'ID applicazione.