Zarządzaj plikami manifestu

Na tej stronie opisujemy, jak działa scalanie pliku manifestu i jak możesz zastosować preferencje scalania, aby rozwiązać konflikty scalania. Więcej informacji o pliku manifestu aplikacji znajdziesz w artykule Omówienie pliku manifestu aplikacji.

Scalanie wielu plików manifestu

Plik APK lub pakiet Android App Bundle może zawierać tylko jeden plik AndroidManifest.xml, ale projekt w Android Studio może zawierać kilka plików MANIFEST dostarczonych przez główny zestaw źródeł, warianty kompilacji i zaimportowane biblioteki. Podczas kompilowania aplikacji kompilacja Gradle łączy wszystkie pliki manifestu w jeden plik manifestu, który jest pakowany do aplikacji.

Narzędzie do łączenia plików manifestu łączy wszystkie elementy XML z każdego pliku, stosując heurystyki łączenia i przestrzegając preferencji zdefiniowanych za pomocą specjalnych atrybutów XML.

Wskazówka: aby wyświetlić podgląd wyników z połączonego pliku manifestu i znaleźć błędy związane z konfliktami, użyj widoku Połączony plik manifestu opisanego w następującej sekcji.

scalanie priorytetów,

Narzędzie do łączenia łączy wszystkie pliki manifestu w jeden plik, sekwencyjnie, na podstawie priorytetu każdego pliku manifestu. Jeśli na przykład masz 3 pliki manifestu, manifest o najniższym priorytecie jest scalany z manifesem o drugim najwyższym priorytecie, a ten z manifesem o najwyższym priorytecie, jak pokazano na rysunku 1.

Rysunek 1. Proces łączenia 3 plików pliku manifestu, od najniższego do najwyższego priorytetu.

Istnieją 3 podstawowe typy plików manifestu, które można łączyć ze sobą. Priorytety łączenia są następujące (najpierw najwyższy priorytet):

  1. Plik manifestu dla wariantu kompilacji

    Jeśli masz wiele zbiorów źródeł dla danego wariantu, ich priorytety w pliku manifestu są następujące:

    • Plik manifestu wariantu kompilacji (np. src/demoDebug/)
    • Plik manifestu typu kompilacji (np. src/debug/)
    • Plik manifestu wariantu usługi (np. src/demo/)

      Jeśli używasz wymiarów smaków, priorytety w pliku manifestu odpowiadają kolejności, w jakiej poszczególne wymiary są wymienione w właściwości flavorDimensions (pierwszy ma najwyższy priorytet).

  2. Główny plik manifestu modułu aplikacji
  3. Plik manifestu z uwzględnionej biblioteki

    Jeśli masz wiele bibliotek, ich priorytety w pliku manifestu odpowiadają kolejności, w jakiej występują w bloku Gradle dependencies.

Na przykład manifest biblioteki jest scalany z głównym plikiem manifestu, a główny plik manifestu jest scalany z pliku manifestu wariantu kompilacji. Pamiętaj, że są to te same priorytety scalania dla wszystkich zbiorów źródeł, jak opisano w artykule Tworzenie zasobów z użyciem zbiorów źródeł.

Ważne: konfiguracje kompilacji z pliku build.gradle zastępują wszystkie odpowiadające im atrybuty w pliku scalonego pliku manifestu. Na przykład atrybut minSdk z pliku build.gradle lub build.gradle.kts zastępuje odpowiadający atrybut w elemencie manifestu <uses-sdk>. Aby uniknąć nieporozumień, pomiń element <uses-sdk> i zdefiniuj te właściwości tylko w pliku build.gradle. Więcej informacji znajdziesz w artykule Konfigurowanie kompilacji.

Heurystyka konfliktów scalania

Narzędzie do łączenia może logicznie dopasować każdy element XML z jednego pliku manifestu do odpowiadającego mu elementu w drugim pliku manifestu. Szczegółowe informacje o tym, jak działa dopasowywanie, znajdziesz w sekcji Priorytety scalania.

Jeśli element z pliku manifestu o niższym priorytecie nie pasuje do żadnego elementu w pliku manifestu o wyższym priorytecie, jest dodawany do scalonego pliku manifestu. Jeśli jednak znajdzie się element pasujący do innych, narzędzie do łączenia próbuje połączyć wszystkie atrybuty z każdego z nich w jednym elemencie. Jeśli narzędzie wykryje, że oba manifesty zawierają ten sam atrybut z różnymi wartościami, wystąpi konflikt scalania.

Tabela 1 przedstawia możliwe wyniki, gdy narzędzie do łączenia próbuje połączyć wszystkie atrybuty w tym samym elemencie.

Tabela 1. Domyślne zachowanie podczas łączenia wartości atrybutów

Atrybut o wysokim priorytecie Atrybut o niskim priorytecie Wynik po scaleniu atrybutu
Nieistotna Nieistotna Brak wartości (użyj wartości domyślnej)
Wartość B Wartość B
Wartość A Nieistotna Wartość A
Wartość A Wartość A
Wartość B Błąd konfliktu – musisz dodać znacznik reguły scalania.

Są jednak sytuacje, w których narzędzie do łączenia zachowuje się inaczej, aby uniknąć konfliktów podczas łączenia:

  • Atrybuty w elemencie <manifest> nigdy nie są łączone; używane są tylko atrybuty z manifesztu o najwyższym priorytecie.
  • Atrybut android:required w elementach <uses-feature> i <uses-library> korzysta z operacji OR. Jeśli wystąpi konflikt, zostanie zastosowana funkcja "true", a funkcja lub biblioteka wymagana przez jeden manifest jest zawsze uwzględniana.
  • Atrybuty w elemencie <uses-sdk> zawsze używają wartości z pliku manifestu o wyższym priorytecie, z wyjątkiem tych sytuacji:
    • Jeśli manifest o niższym priorytecie ma wyższą wartość minSdk, wystąpi błąd, chyba że zastosujesz regułę łączenia overrideLibrary.
    • Jeśli plik manifestu o niższym priorytecie ma niższą wartość parametru targetSdkVersion, narzędzie do łączenia używa wartości z pliku manifestu o wyższym priorytecie. Dodaje też uprawnienia systemowe, które są niezbędne, aby zaimportowana biblioteka nadal działała prawidłowo (w przypadku, gdy nowsza wersja Androida ma zwiększone ograniczenia dotyczące uprawnień). Więcej informacji o tym zachowaniu znajdziesz w sekcji dotyczącej domyślnych uprawnień systemowych.
  • Element <intent-filter> nigdy nie jest dopasowywany między plikami manifestu. Każdy z nich jest traktowany jako unikalny i dodawany do wspólnego elementu nadrzędnego w scalonym pliku manifestu.

W przypadku wszystkich innych konfliktów między atrybutami pojawi się błąd. Musisz wtedy przekazać narzędziu do łączenia instrukcje dotyczące jego rozwiązania, dodając specjalny atrybut w pliku manifestu o wyższym priorytecie. Zapoznaj się z następną sekcją dotyczącą znaczników reguł scalania.

Nie polegaj na wartościach domyślnych atrybutów. Wszystkie unikalne atrybuty są łączone w tym samym elemencie, co może powodować nieoczekiwane wyniki, jeśli manifest o wyższym priorytecie zależy od domyślnej wartości atrybutu bez jego zadeklarowania. Jeśli na przykład plik manifestu o wyższym priorytecie nie deklaruje atrybutu android:launchMode, używa wartości domyślnej "standard". Jeśli jednak plik manifestu o niższym priorytecie deklaruje ten atrybut z inną wartością, ta wartość jest stosowana w złączonym pliku manifestu, co zastępuje wartość domyślną. Należy wyraźnie zdefiniować każdy atrybut. Wartości domyślne każdego atrybutu są opisane w dokumentacji pliku manifestu.

znaczniki reguł scalania,

Znak znacznika reguły scalania to atrybut XML, za pomocą którego możesz określić preferowany sposób rozwiązywania konfliktów podczas scalania lub usuwania niechcianych elementów i atrybutów. Możesz zastosować znacznik do całego elementu lub tylko do określonych atrybutów w elemencie.

Podczas łączenia 2 plików pliku manifestu narzędzie do łączenia szuka tych znaczników w pliku manifestu o wyższym priorytecie.

Wszystkie znaczniki należą do przestrzeni nazw Android tools, więc musisz najpierw zadeklarować tę przestrzeń nazw w elemencie <manifest>, jak pokazano poniżej:

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

znaczniki węzłów,

Aby zastosować regułę łączenia do całego elementu XML (do wszystkich atrybutów w danym elemencie pliku manifestu i do wszystkich jego tagów podrzędnych), użyj tych atrybutów:

tools:node="merge"
Połącz wszystkie atrybuty w tym tagu i wszystkie elementy zagnieżdżone, jeśli nie ma konfliktów, używając heurystyki łączenia konfliktów. Jest to domyślne zachowanie elementów.

Manifest o niskim priorytecie:

<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 o wysokim priorytecie:

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

Wynik po scaleniu pliku manifestu:

<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"
Połącz atrybuty tylko w tym tagu; nie łącz elementów zagnieżdżonych.

Manifest o niskim priorytecie:

<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 o wysokim priorytecie:

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

Wynik po scaleniu pliku manifestu:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
</activity>
tools:node="remove"
Usuń ten element z pliku manifestu. Używany, gdy w złączonym pliku manifestu znajdziesz element, którego nie potrzebujesz i który został dostarczony przez plik manifestu o niższym priorytecie, na który nie masz wpływu (np. zaimportowana biblioteka).

Manifest o niskim priorytecie:

<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 o wysokim priorytecie:

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

Wynik po scaleniu pliku manifestu:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>
tools:node="removeAll"
Podobna do tools:node="remove", ale usuwa wszystkie elementy pasujące do tego typu elementu (w tym samym elemencie nadrzędnym).

Manifest o niskim priorytecie:

<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 o wysokim priorytecie:

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

Wynik po scaleniu pliku manifestu:

<activity-alias android:name="com.example.alias">
</activity-alias>
tools:node="replace"
Całkowicie zastąp element o niższym priorytecie. Oznacza to, że jeśli w pliku manifestu o niższym priorytecie znajduje się element pasujący do elementu w pliku manifestu o wyższym priorytecie, zignoruj ten pierwszy i użyj tego drugiego dokładnie tak, jak jest on zapisany w pliku manifestu.

Manifest o niskim priorytecie:

<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 o wysokim priorytecie:

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

Wynik po scaleniu pliku manifestu:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="fox"
      android:value="@string/dingeringeding"/>
</activity-alias>
tools:node="strict"
Wygeneruj błąd kompilacji, gdy element w pliku manifestu o niższym priorytecie nie jest identyczny z elementem w pliku manifestu o wyższym priorytecie (chyba że został rozwiązany przez inne znaczniki reguły scalania). Zastąpi to heurystyki konfliktów scalania. Jeśli na przykład manifest o niższym priorytecie zawiera dodatkowy atrybut, kompilacja zakończy się niepowodzeniem (gdyż zachowanie domyślne spowoduje dodanie tego atrybutu do scalonego pliku manifestu).

Manifest o niskim priorytecie:

<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 o wysokim priorytecie:

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

Spowoduje to błąd scalania pliku manifestu. W trybie ścisłym te 2 elementy pliku manifestu nie mogą się w ogóle różnić. Aby rozwiązać te różnice, musisz zastosować inne znaczniki reguły scalania. (bez tools:node="strict" te 2 pliki można scalić bez błędów, jak w przypadku pliku tools:node="merge").

znaczniki atrybutów,

Aby zamiast tego zastosować regułę scalania tylko do określonych atrybutów w tagu manifestu, użyj tych atrybutów. Każdy atrybut może zawierać co najmniej 1 nazwę atrybutu (w tym jego przestrzeń nazw) oddzieloną przecinkami.

tools:remove="attr, ..."
Usuń określone atrybuty z pliku manifestu po scalerowaniu. Używany, gdy plik manifestu o niższym priorytecie zawiera te atrybuty i chcesz mieć pewność, że nie zostaną one uwzględnione w złączonym pliku manifestu.

Manifest o niskim priorytecie:

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

Manifest o wysokim priorytecie:

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

Wynik po scaleniu pliku manifestu:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait">
tools:replace="attr, ..."
Zastąp określone atrybuty w pliku manifestu o niższym priorytecie atrybutami z tego pliku. Innymi słowy, zawsze zachowuj wartości z pliku manifestu o wyższym priorytecie.

Manifest o niskim priorytecie:

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

Manifest o wysokim priorytecie:

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

Wynik po scaleniu pliku manifestu:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
tools:strict="attr, ..."
W każdym przypadku, gdy te atrybuty w pliku manifestu o niższym priorytecie nie pasują dokładnie do atrybutów w pliku manifestu o wyższym priorytecie, generuj błąd kompilacji. Jest to domyślne zachowanie we wszystkich atrybutach z wyjątkiem tych, które mają specjalne zachowania opisane w heurystychach dotyczących konfliktów podczas łączenia.

Manifest o niskim priorytecie:

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

Manifest o wysokim priorytecie:

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

Spowoduje to błąd scalania pliku manifestu. Aby rozwiązać konflikt, musisz zastosować inne znaczniki reguły łączenia. Jest to działanie domyślne, więc ten sam wynik można uzyskać, dodając tools:strict="screenOrientation".

Możesz też zastosować wiele znaczników do jednego elementu, jak w tym przykładzie:

Manifest o niskim priorytecie:

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

Manifest o wysokim priorytecie:

<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">

Wynik po scaleniu pliku manifestu:

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

Selektor znaczników

Jeśli chcesz zastosować znaczniki reguły scalania tylko do określonej zaimportowanej biblioteki, dodaj atrybut tools:selector z nazwą pakietu biblioteki.

Na przykład w przypadku tego pliku manifestu reguła łączenia remove jest stosowana tylko wtedy, gdy plik manifestu o niższym priorytecie pochodzi z biblioteki com.example.lib1:

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

Jeśli manifest o niższym priorytecie pochodzi z dowolnego innego źródła, reguła scalania remove zostanie zignorowana.

Uwaga: jeśli użyjesz tego w przypadku jednego z atrybutów, będzie ono dotyczyć wszystkich atrybutów określonych w tym atrybucie.

Zastępowanie atrybutu <uses-sdk> w przypadku zaimportowanych bibliotek

Domyślnie podczas importowania biblioteki z wartością minSdk większą niż w głównym pliku manifestu występuje błąd i biblioteki nie można zaimportować.

Aby narzędzie do łączenia zignorowało ten konflikt i zaimportowało bibliotekę, zachowując przy tym niższą wartość atrybutu minSdk w aplikacji, dodaj atrybut overrideLibrary do tagu <uses-sdk>. Wartością atrybutu może być co najmniej 1 nazwa pakietu biblioteki (rozdzielona przecinkami), wskazująca biblioteki, które mogą zastąpić minSdk w głównym pliku manifestu.

Jeśli na przykład główny plik manifestu aplikacji stosuje się do overrideLibraryw ten sposób:

<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"/>
...

Następnie można scalić ten plik manifestu bez błędów dotyczących tagu <uses-sdk>. Scalony plik manifestu zachowa tag minSdk="2" z pliku manifestu aplikacji.

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

Domyślne uprawnienia systemowe

Niektóre interfejsy API Androida, które kiedyś były swobodnie dostępne dla aplikacji, zostały w ostatnich wersjach Androida objęte uprawnieniami systemowymi.

Aby uniknąć problemów z aplikacjami, które wymagają dostępu do tych interfejsów API, najnowsze wersje Androida umożliwiają aplikacjom dalszy dostęp do tych interfejsów API bez uprawnień, jeśli wartość targetSdkVersion jest niższa niż wersja, w której dodano ograniczenie. Takie zachowanie przyznaje aplikacji domyślne uprawnienie do uzyskiwania dostępu do interfejsów API. Może to mieć wpływ na złączone manifesty, które mają różne wartości dla targetSdkVersion.

Jeśli plik manifestu o niższym priorytecie ma niższą wartość parametru targetSdkVersion, która zapewnia mu domyślne uprawnienia, a plik manifestu o wyższym priorytecie nie ma tych samych domyślnych uprawnień (ponieważ wartość parametru targetSdkVersion jest równa lub wyższa niż w wersji, w której dodano ograniczenie), narzędzie do łączenia wyraźnie dodaje uprawnienia systemowe do scalonego pliku manifestu.

Jeśli na przykład Twoja aplikacja ma wartość targetSdkVersion równą 4 lub większą, a importowana biblioteka ma wartość targetSdkVersion równą 3 lub mniejszą, narzędzie do łączenia dodaje uprawnienie WRITE_EXTERNAL_STORAGE do scalonego pliku manifestu.

Tabela 2 zawiera wszystkie możliwe uprawnienia, które można dodać do scalonego pliku manifestu:

Tabela 2. Lista uprawnień, które narzędzie do łączenia może dodać do scalonego pliku manifestu

Deklaracje w pliku manifestu o niższym priorytecie uprawnienia dodane do scalonego pliku manifestu;
targetSdkVersion to 3 lub mniej WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
targetSdkVersion ma wartość 15 lub mniejszą i korzysta z READ_CONTACTS READ_CALL_LOG
targetSdkVersion ma wartość 15 lub mniejszą i korzysta z WRITE_CONTACTS WRITE_CALL_LOG

Sprawdzanie scalonego pliku manifestu i znajdowanie konfliktów

Jeszcze przed utworzeniem aplikacji możesz wyświetlić podgląd scalonego pliku manifestu. Aby wyświetlić podgląd:

  1. W Android Studio otwórz plik AndroidManifest.xml.
  2. U dołu edytora kliknij kartę Skompilowany plik manifestu.

Widok scalonego pliku manifestu zawiera po lewej stronie wyniki scalonego pliku manifestu, a po prawej informacje o każdym scalonym pliku manifestu (patrz rys. 2).

Elementy scalone z plików pliku manifestu o niższym priorytecie są wyróżnione na żółto po lewej stronie. Klucz każdego koloru jest określony w sekcji Źródła pliku manifestu.

Rysunek 2. Widok „Manifest łączony”.

Pliki manifestu, które były częścią kompilacji, ale nie zawierały elementów ani atrybutów, są wymienione w sekcji Inne pliki manifestu.

Aby zobaczyć informacje o pochodzeniu elementu, kliknij go w panelu po lewej stronie. Szczegóły pojawią się w sekcji Log łączenia.

Jeśli wystąpią jakieś konflikty, pojawią się one w sekcji Błędy podczas łączenia wraz z rekomendacją dotyczącą sposobu ich rozwiązania za pomocą znaczników reguły łączenia.

Błędy są też wyświetlane w oknie Dziennik zdarzeń. Aby je wyświetlić, wybierz Widok > Okna narzędzia > Dziennik zdarzeń.

Aby zobaczyć pełny dziennik drzewa decyzji dotyczącego łączenia, otwórz plik dziennika o nazwie manifest-merger-buildVariant-report.txt w katalogu build/outputs/logs/ w module.

Scalanie zasad

Narzędzie do łączenia plików manifestu może logicznie dopasować każdy element XML z jednego pliku manifestu do odpowiadającego elementu w innym pliku. Zbiorca dopasowuje każdy element za pomocą klucza dopasowania, który może być unikalną wartością atrybutu (np. android:name) lub naturalną unikalnością samego tagu (np. może istnieć tylko jeden element <supports-screen>).

Jeśli 2 pliki manifestu mają ten sam element XML, narzędzie scala te elementy, stosując jedną z 3 zasad scalania:

Scal
Połącz wszystkie atrybuty, które nie powodują konfliktów, w tym samym tagu, a także scal elementy podrzędne zgodnie z odpowiednimi zasadami scalania. Jeśli jakieś atrybuty są ze sobą sprzeczne, scal je za pomocą znaczników reguły scalania.
Scal tylko elementy podrzędne
Nie łącz ani nie scalaj atrybutów (zachowaj tylko atrybuty podane przez plik manifestu o najwyższym priorytecie) i scalaj elementy podrzędne zgodnie z zasadami scalania.
Keep
Zostaw element bez zmian i dodaj go do wspólnego elementu nadrzędnego w scalonym pliku. Jest to używane tylko wtedy, gdy dopuszczalne jest występowanie kilku deklaracji tego samego elementu.

Tabela 3 zawiera listę typów elementów, typ zasad scalania i klucz używany do określania dopasowania elementów w 2 plikach manifestu:

Tabela 3. Zasady scalania elementów pliku manifestu i klucze dopasowania

Żywioły Scalanie zasad Klucz dopasowania
<action> Scal Atrybut android:name
<activity> Scal Atrybut android:name
<application> Scal Każda <manifest> może mieć tylko 1 kartę.
<category> Scal Atrybut android:name
<data> Scal Każda <intent-filter> może mieć tylko 1 kartę.
<grant-uri-permission> Scal Każda <provider> może mieć tylko 1 kartę.
<instrumentation> Scal Atrybut android:name
<intent-filter> Keep Brak dopasowania; w elemencie nadrzędnym można umieścić kilka deklaracji.
<manifest> Scal tylko elementy podrzędne Każdy plik może zawierać tylko jedną.
<meta-data> Scal Atrybut android:name
<path-permission> Scal Każda <provider> może mieć tylko 1 kartę.
<permission-group> Scal Atrybut android:name
<permission> Scal Atrybut android:name
<permission-tree> Scal Atrybut android:name
<provider> Scal Atrybut android:name
<receiver> Scal Atrybut android:name
<screen> Scal Atrybut android:screenSize
<service> Scal Atrybut android:name
<supports-gl-texture> Scal Atrybut android:name
<supports-screen> Scal Każda <manifest> może mieć tylko 1 kartę.
<uses-configuration> Scal Każda <manifest> może mieć tylko 1 kartę.
<uses-feature> Scal atrybut android:name (jeśli go nie ma, to atrybut android:glEsVersion);
<uses-library> Scal Atrybut android:name
<uses-permission> Scal Atrybut android:name
<uses-sdk> Scal Każda <manifest> może mieć tylko 1 kartę.
Elementy niestandardowe Scal Brak dopasowania; są one nieznane dla narzędzia do scalania i zawsze są uwzględniane w scalonym pliku manifestu.

Wstrzykiwanie zmiennych kompilacji do pliku manifestu

Jeśli chcesz wstawić do pliku AndroidManifest.xml zmienne zdefiniowane w pliku build.gradle, możesz to zrobić za pomocą właściwości manifestPlaceholders. Ta właściwość przyjmuje mapę par klucz-wartość, jak pokazano poniżej:

Groovy

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

Kotlin

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

Następnie możesz wstawić jeden z symboli zastępczych do pliku manifestu jako wartość atrybutu:

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

Domyślnie narzędzia do kompilacji podają też identyfikator aplikacji w miejscu zarezerwowanym dla ${applicationId}. Wartość zawsze odpowiada ostatecznemu identyfikatorowi aplikacji dla bieżącej wersji, w tym zmianom w wersjach wariantów. Jest to przydatne, gdy chcesz używać unikalnej przestrzeni nazw dla identyfikatorów, takich jak działanie związane z zamiarem, nawet w przypadku wariantów kompilacji.

Jeśli na przykład plik build.gradle wygląda tak:

Groovy

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"
        }
    }
}

Następnie możesz wstawić identyfikator aplikacji w pliku manifestu w ten sposób:

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

Gdy skompilujesz wersję „free” manifestu, otrzymasz ten wynik:

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

Więcej informacji znajdziesz w artykule Ustawianie identyfikatora aplikacji.