Questa pagina descrive come funziona l'unione dei manifest e come applicare le preferenze di unione per risolvere i conflitti di unione. Per un'introduzione al file manifest dell'app, consulta la panoramica del manifest dell'app.
Unisci più file manifest
Il 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 risorse principale, dalle varianti di compilazione e dalle librerie importate. Durante la creazione dell'app, la build Gradle unisce tutti i file manifest in un unico file manifest che viene pacchettizzato nell'app.
Lo strumento di unione dei manifest combina tutti gli elementi XML di ogni file seguendo le euristiche di unione e rispettando le preferenze di unione che hai definito con attributi XML speciali.
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, il manifest con la priorità più bassa viene unito al manifest con la priorità più alta successiva, che a sua volta viene unito al manifest con la priorità più alta, come illustrato nella figura 1.
Esistono tre tipi di file manifest di base che possono essere uniti tra loro e le loro priorità di unione sono le seguenti (dalla priorità più alta alla più bassa):
File manifest per la tua variante di compilazione
Se hai più set di risorse per la tua variante, le priorità dei manifest sono le seguenti:
- Manifest della variante di compilazione (ad esempio
src/demoDebug/) - Manifest del tipo di build (ad esempio
src/debug/) Manifest della versione prodotto (ad esempio
src/demo/)Se utilizzi le dimensioni versioni, le priorità del manifest corrispondono all'ordine in cui ogni dimensione è elencata nella proprietà
flavorDimensions(la prima ha la priorità più alta).
- Manifest della variante di compilazione (ad esempio
File manifest principale per il modulo dell'app
File manifest di una libreria inclusa
Se hai più librerie, le priorità dei relativi manifest corrispondono all'ordine in cui vengono visualizzate nel blocco Gradle
dependencies.
Ad esempio, un manifest della libreria viene unito al manifest principale, che a sua volta viene unito al manifest della variante di compilazione. Tieni presente che queste sono le stesse priorità di unione per tutti i set di risorse, come descritto in Crea con i set di risorse.
Euristica dei conflitti di unione
Lo strumento di unione può abbinare logicamente ogni elemento XML di un manifest a un elemento corrispondente in un altro manifest. Per informazioni dettagliate sul funzionamento della corrispondenza, consulta le priorità di unione nella sezione precedente.
Se un elemento del manifest con priorità più bassa non corrisponde ad alcun elemento del 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 ciascun elemento nello stesso elemento. Se lo strumento rileva che entrambi i 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 unione tenta di combinare tutti gli attributi nello stesso elemento.
Tabella 1. Comportamento di unione predefinito per i valori degli attributi
| Attributo ad alta priorità | Attributo con priorità bassa | Risultato unito dell'attributo |
|---|---|---|
| Nessun valore | Nessun valore | Nessun valore (utilizza il valore predefinito) |
| Valore B | Valore B | |
| Valore A | Nessun valore | Valore A |
| Valore A | Valore A | |
| Valore B | Errore di conflitto: devi aggiungere un indicatore della regola 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; vengono utilizzati solo gli attributi del manifest con la priorità più alta. - L'attributo
android:requirednegli 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 manifest viene sempre inclusa. - Gli attributi nell'elemento
<uses-sdk>utilizzano sempre il valore del manifest con priorità più alta, tranne nelle seguenti situazioni:- Quando il manifest con priorità inferiore ha un valore
minSdkpiù alto, si verifica un errore, a meno che non applichi la regola di unioneoverrideLibrary. - Quando il manifest con priorità inferiore ha un valore
targetSdkVersioninferiore, lo strumento di unione utilizza il valore del manifest con priorità superiore e aggiunge anche le autorizzazioni di sistema necessarie per garantire che la libreria importata continui a funzionare correttamente (per i casi in cui la versione di Android superiore ha aumentato le limitazioni delle autorizzazioni). Per saperne di più su questo comportamento, consulta la sezione relativa alle autorizzazioni di sistema implicite.
- Quando il manifest con priorità inferiore ha un valore
- L'elemento
<intent-filter>non viene mai abbinato tra i manifest. Ognuno viene trattato come 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 sezione seguente sugli indicatori delle regole di unione.
Unisci i marcatori delle regole
Un indicatore della regola 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 unisce 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 Android tools, quindi devi prima dichiarare questo spazio dei nomi nell'elemento <manifest>, come mostrato di seguito:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" xmlns:tools="http://schemas.android.com/tools">
Indicatori dei nodi
Per applicare una regola di unione a un intero elemento XML (a tutti gli attributi in un determinato elemento manifest e a tutti i relativi tag secondari), utilizza i seguenti attributi:
tools:node="merge"- Unisci tutti gli attributi in questo tag e tutti gli elementi nidificati quando non ci sono conflitti utilizzando le euristiche di conflitto di unione. Questo è il comportamento predefinito per gli elementi.
Manifest a bassa priorità:
<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 ad alta priorità:
<activity android:name="com.example.ActivityOne" android:screenOrientation="portrait" tools:node="merge"> </activity>
Risultato del 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="mergeOnlyAttributes"- Unisci gli attributi solo in questo tag; non unire gli elementi nidificati.
Manifest a bassa priorità:
<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 ad alta priorità:
<activity android:name="com.example.ActivityOne" android:screenOrientation="portrait" tools:node="mergeOnlyAttributes"> </activity>
Risultato del manifest unito:
<activity android:name="com.example.ActivityOne" android:screenOrientation="portrait" android:windowSoftInputMode="stateUnchanged"> </activity>
tools:node="remove"- Rimuovi questo elemento dal manifest unito. Utilizzato quando
scopri un elemento nel manifest unito che non ti serve e che è stato fornito da un file manifest con priorità inferiore che non è sotto il tuo controllo
(ad esempio una libreria importata).
Manifest a bassa priorità:
<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 ad alta priorità:
<activity-alias android:name="com.example.alias"> <meta-data android:name="cow" tools:node="remove"/> </activity-alias>
Risultato del 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 corrispondenti a questo tipo di elemento (all'interno dello stesso elemento principale).Manifest a bassa priorità:
<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 ad alta priorità:
<activity-alias android:name="com.example.alias"> <meta-data tools:node="removeAll"/> </activity-alias>
Risultato del 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 manifest con priorità inferiore, ignoralo e utilizza questo elemento esattamente come appare in questo manifest.
Manifest a bassa priorità:
<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 ad alta priorità:
<activity-alias android:name="com.example.alias" tools:node="replace"> <meta-data android:name="fox" android:value="@string/dingeringeding"/> </activity-alias>
Risultato del 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 manifest con priorità più bassa non corrisponde esattamente all'elemento nel manifest con priorità più alta (a meno che non venga risolto da altri indicatori delle regole di unione). In questo modo, l'euristica dei conflitti di unione viene ignorata. Ad esempio, se il manifest con priorità inferiore include un attributo aggiuntivo, la build non va a buon fine (mentre il comportamento predefinito aggiunge l'attributo aggiuntivo al manifest unito).
Manifest a bassa priorità:
<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 ad alta priorità:
<activity android:name="com.example.ActivityOne" android:screenOrientation="portrait" tools:node="strict"> </activity>
In questo modo si verifica un errore di unione del manifest. I due elementi del manifest non possono differire in alcun modo in modalità StrictMode. Per risolvere queste differenze, devi applicare altri indicatori delle regole di unione. (Senza
tools:node="strict", questi due file possono essere uniti senza errori, come mostrato nell'esempio pertools:node="merge".)
Indicatori di attribuzione
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à più bassa include questi attributi e vuoi assicurarti che non vengano inseriti nel manifest unito.
Manifest a bassa priorità:
<activity android:name="com.example.ActivityOne" android:windowSoftInputMode="stateUnchanged">
Manifest ad alta priorità:
<activity android:name="com.example.ActivityOne" android:screenOrientation="portrait" tools:remove="android:windowSoftInputMode">
Risultato del 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 a bassa priorità:
<activity android:name="com.example.ActivityOne" android:theme="@oldtheme" android:exported="false" android:windowSoftInputMode="stateUnchanged">
Manifest ad alta priorità:
<activity android:name="com.example.ActivityOne" android:theme="@newtheme" android:exported="true" android:screenOrientation="portrait" tools:replace="android:theme,android:exported">
Risultato del 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à più bassa 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 nelle euristiche dei conflitti di unione.
Manifest a bassa priorità:
<activity android:name="com.example.ActivityOne" android:screenOrientation="landscape"> </activity>
Manifest ad alta priorità:
<activity android:name="com.example.ActivityOne" android:screenOrientation="portrait" tools:strict="android:screenOrientation"> </activity>
In questo modo si verifica un errore di unione del manifest. Per risolvere il conflitto, devi applicare altri indicatori delle regole di unione. Questo è il comportamento predefinito, quindi si ottiene lo stesso risultato aggiungendo esplicitamente
tools:strict="screenOrientation".
Puoi anche applicare più indicatori a un elemento, come mostrato nell'esempio seguente:
Manifest a bassa priorità:
<activity android:name="com.example.ActivityOne" android:theme="@oldtheme" android:exported="false" android:allowTaskReparenting="true" android:windowSoftInputMode="stateUnchanged">
Manifest ad alta priorità:
<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 manifest unito:
<activity android:name="com.example.ActivityOne" android:theme="@newtheme" android:exported="true" android:allowTaskReparenting="true" android:screenOrientation="portrait">
Selettore di indicatori
Se vuoi applicare gli indicatori delle regole di unione solo a una libreria importata specifica, aggiungi l'attributo tools:selector con il nome del pacchetto della libreria.
Ad esempio, con il seguente manifest, la regola di unione remove viene applicata solo quando il file manifest con priorità inferiore proviene dalla 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.
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 importi la libreria mantenendo il valore minSdk inferiore della tua app, aggiungi l'attributo overrideLibrary al tag <uses-sdk>.
Il valore dell'attributo può essere uno o più nomi di pacchetti di librerie (separati da virgole), che indicano le librerie che possono eseguire l'override di minSdk del manifest principale.
Ad esempio, se il file manifest principale dell'app applica overrideLibrary
in questo modo:
<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"/> ...
In questo modo, il manifest seguente può essere unito senza errori relativi al tag <uses-sdk> e il manifest unito mantiene minSdk="2" dal 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 Android che un tempo erano liberamente accessibili dalle app sono state limitate dalle autorizzazioni di sistema nelle versioni recenti di Android.
Per evitare di interrompere le app che prevedono l'accesso a queste API, le versioni recenti di Android consentono alle app di continuare ad accedere alle API senza l'autorizzazione se targetSdkVersion è impostato su un valore inferiore rispetto alla versione in cui è stata aggiunta la limitazione. Questo comportamento concede all'app un'autorizzazione implicita per consentire l'accesso alle API. I manifest uniti che hanno valori diversi per targetSdkVersion possono essere interessati.
Se il file manifest con priorità inferiore ha un valore inferiore per targetSdkVersion che fornisce un'autorizzazione implicita e il manifest con priorità superiore non ha la stessa autorizzazione implicita (perché il relativo 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 la tua app imposta targetSdkVersion su 4 o un valore superiore e importa una
libreria con targetSdkVersion impostato su 3 o 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 delle autorizzazioni che lo strumento di unione potrebbe aggiungere al manifest unito
| Dichiarazioni del manifest con priorità più bassa | 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 |
Ispeziona il manifest unito e trova i conflitti
Ancor prima di creare l'app, puoi visualizzare un'anteprima del manifest unito. Per visualizzare un'anteprima:
- In Android Studio, apri il file
AndroidManifest.xml. - Fai clic sulla scheda Merged Manifest (Manifest unito) nella parte inferiore dell'editor.
La visualizzazione Manifest unito mostra i risultati del manifest unito a sinistra e le informazioni su ogni file manifest unito a destra, come mostrato nella figura 2.
Gli elementi uniti da file manifest con priorità inferiore sono evidenziati in colori diversi a sinistra. La legenda di ogni colore è specificata in Origini manifest.
I file manifest che facevano parte della build, ma che non hanno contribuito con elementi o attributi, sono elencati in Altri file manifest.
Per visualizzare le informazioni sull'origine di un elemento, fai clic sull'elemento nel riquadro a sinistra. I dettagli vengono visualizzati in Log di unione.
Se si verificano conflitti, questi vengono visualizzati in Errori di unione con un suggerimento su come risolverli utilizzando gli indicatori delle regole di unione.
Gli errori vengono anche stampati nella finestra Log eventi. Per visualizzarli, seleziona Visualizza > Finestre degli strumenti > Log eventi.
Per visualizzare un log completo dell'albero decisionale di unione, puoi trovare il file di log nella directory build/outputs/logs/ del modulo, denominato manifest-merger-buildVariant-report.txt.
Unisci policy
Lo strumento di unione dei manifest può abbinare 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, un valore dell'attributo univoco (ad esempio 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 alla rispettiva policy di unione. Se alcuni attributi sono in conflitto tra loro, uniscili con gli indicatori delle regole di unione.
- Unisci solo elementi secondari
- Non combinare o unire gli attributi (mantieni solo gli attributi forniti dal file manifest con la priorità più alta) e unisci gli elementi secondari in base alla relativa policy di unione.
- Keep
- Lascia l'elemento così com'è e aggiungilo all'elemento principale comune nel file unito. Questo attributo viene utilizzato solo quando è accettabile che esistano più dichiarazioni dello stesso elemento.
La Tabella 3 elenca ogni tipo di elemento, il tipo di policy di unione utilizzato e la chiave utilizzata per determinare una corrispondenza di elementi tra due manifest:
Tabella 3. Policy di unione degli elementi del manifest e chiavi di corrispondenza
| Elemento | Policy di unione | Chiave di corrispondenza |
|---|---|---|
<action>
|
Unisci | Attributo android:name
|
<activity>
|
Unisci | Attributo android:name
|
<application>
|
Unisci | Esiste un solo <manifest>.
|
<category>
|
Unisci | Attributo android:name
|
<data>
|
Unisci | Esiste un solo <intent-filter>.
|
<grant-uri-permission>
|
Unisci | Esiste un solo <provider>.
|
<instrumentation>
|
Unisci | Attributo android:name
|
<intent-filter>
|
Keep | Nessuna corrispondenza; sono consentite più dichiarazioni all'interno dell'elemento principale. |
<manifest>
|
Unisci solo elementi secondari | Esiste un solo elemento per file. |
<meta-data>
|
Unisci | Attributo android:name
|
<path-permission>
|
Unisci | Esiste un solo <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 | Esiste un solo <manifest>.
|
<uses-configuration>
|
Unisci | Esiste un solo <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 | Esiste un solo <manifest>.
|
| Elementi personalizzati | Unisci | Nessuna corrispondenza: questi elementi sono sconosciuti allo strumento di unione e vengono sempre inclusi 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:
Alla moda
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 build forniscono anche l'ID applicazione della tua app nel segnaposto ${applicationId}. Il valore corrisponde sempre all'ID applicazione finale per la build corrente, incluse le modifiche apportate dalle varianti di compilazione.
Questo è utile quando vuoi utilizzare uno spazio dei nomi univoco per gli identificatori, come un'azione intent, anche tra le varianti di compilazione.
Ad esempio, se il file build.gradle ha il seguente aspetto:
Alla moda
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 puoi inserire l'ID applicazione nel manifest in questo modo:
<intent-filter ... >
<action android:name="${applicationId}.TRANSMOGRIFY" />
...
</intent-filter>
Il risultato del manifest quando crei la versione prodotto "free" è il seguente:
<intent-filter ... >
<action android:name="com.example.myapp.free.TRANSMOGRIFY" />
...
</intent-filter>
Per saperne di più, consulta Imposta l'ID applicazione.