Zarządzaj plikami manifestu

Na tej stronie opisujemy, jak działa scalanie plików manifestu i jak możesz stosować ustawienia scalania, aby rozwiązywać konflikty. Wprowadzenie do pliku manifestu aplikacji znajdziesz w omówieniu pliku manifestu aplikacji.

Łączenie wielu plików manifestu

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

Narzędzie łączące pliki manifestu łączy wszystkie elementy XML z każdego pliku, stosując heurystykę scalania i przestrzegając preferencji scalania zdefiniowanych za pomocą specjalnych atrybutów XML.

Priorytety scalania

Narzędzie łączące łączy wszystkie pliki manifestu w jeden plik, sekwencyjnie, na podstawie priorytetu każdego pliku manifestu. Jeśli na przykład masz 3 pliki manifestu, plik o najniższym priorytecie jest scalany z plikiem o następnym najwyższym priorytecie, a następnie jest scalany z plikiem o najwyższym priorytecie, jak pokazano na ilustracji 1.

Rysunek 1. Proces scalania 3 plików manifestu, od najniższego do najwyższego priorytetu.

Istnieją 3 podstawowe typy plików manifestu, które można ze sobą scalać. Ich priorytety scalania są następujące (od najwyższego):

  1. Plik manifestu wariantu kompilacji

    Jeśli masz kilka 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 rodzajów, priorytety pliku manifestu odpowiadają kolejności, w jakiej każdy wymiar jest wymieniony we właściwości flavorDimensions (pierwszy ma najwyższy priorytet).

  2. Główny plik manifestu modułu aplikacji

  3. Plik manifestu z dołączonej biblioteki

    Jeśli masz kilka bibliotek, priorytety ich plików manifestu odpowiadają kolejności, w jakiej pojawiają się w bloku Gradle dependencies.

Na przykład plik manifestu biblioteki jest scalany z głównym plikiem manifestu, a następnie główny plik manifestu jest scalany z plikiem manifestu wariantu kompilacji. Pamiętaj, że są to te same priorytety scalania dla wszystkich zbiorów źródeł, które opisano w artykule Kompilowanie ze zbiorami źródeł.

Heurystyka konfliktów scalania

Narzędzie łączące może logicznie dopasować każdy element XML z jednego pliku manifestu do odpowiedniego elementu w innym pliku manifestu. Szczegółowe informacje o tym, jak działa dopasowywanie, znajdziesz w sekcji Priorytety scalania powyżej.

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 pliku manifestu łączonego. Jeśli jednak znajdzie pasujący element, narzędzie łączące spróbuje połączyć wszystkie atrybuty z każdego z nich w ten sam element. Jeśli narzędzie wykryje, że oba pliki manifestu zawierają ten sam atrybut z różnymi wartościami, wystąpi konflikt scalania.

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

Tabela 1. Domyślne działanie scalania wartości atrybutów

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

Istnieje jednak kilka sytuacji, w których narzędzie łączące zachowuje się inaczej, aby uniknąć konfliktów podczas scalania:

  • Atrybuty w elemencie <manifest> nigdy nie są scalane. Używane są tylko atrybuty z pliku manifestu o najwyższym priorytecie.
  • Atrybut android:required w elementach <uses-feature> i <uses-library> używa scalania OR. W przypadku konfliktu stosowana jest wartość "true", a funkcja lub biblioteka wymagana przez jeden z manifestów 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 plik manifestu o niższym priorytecie ma wyższą wartość minSdk, wystąpi błąd, chyba że zastosujesz regułę scalania overrideLibrary.
    • Gdy plik manifestu o niższym priorytecie ma niższą wartość targetSdkVersion, narzędzie łączące używa wartości z pliku manifestu o wyższym priorytecie i dodaje uprawnienia systemowe niezbędne do prawidłowego działania zaimportowanej biblioteki (w przypadkach, gdy wyższa wersja Androida ma bardziej rygorystyczne uprawnienia). 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 manifeście łączonym.

W przypadku wszystkich innych konfliktów między atrybutami występuje błąd i musisz poinstruować narzędzie łączące, jak go rozwiązać, dodając specjalny atrybut w pliku manifestu o wyższym priorytecie. Zobacz sekcję dotyczącą znaczników reguł scalania poniżej.

Znaczniki reguł scalania

Znacznik reguły scalania to atrybut XML, którego możesz użyć, aby określić swoje preferencje dotyczące rozwiązywania konfliktów scalania lub usuwania niechcianych elementów i atrybutów. Możesz zastosować znacznik do całego elementu lub tylko do jego określonych atrybutów.

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

Wszystkie znaczniki należą do przestrzeni nazw Androida 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łę scalania do całego elementu XML (do wszystkich atrybutów w danym elemencie pliku manifestu i wszystkich jego tagów podrzędnych), użyj tych atrybutów:

tools:node="merge"
Scal wszystkie atrybuty w tym tagu i wszystkie elementy zagnieżdżone, jeśli nie ma konfliktów, korzystając z heurystyki konfliktów scalania. Jest to działanie domyślne elementów.

Plik manifestu 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>

Plik manifestu o wysokim priorytecie:

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

Wynik manifestu łączonego:

<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"
Scal atrybuty tylko w tym tagu; nie scalaj elementów zagnieżdżonych.

Plik manifestu 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>

Plik manifestu o wysokim priorytecie:

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

Wynik manifestu łączonego:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
</activity>
tools:node="remove"
Usuń ten element z manifestu łączonego. Używany, gdy w pliku manifestu łączonego znajdziesz niepotrzebny element, który został dostarczony przez plik manifestu o niższym priorytecie, nad którym nie masz kontroli (np. zaimportowaną bibliotekę).

Plik manifestu 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>

Plik manifestu o wysokim priorytecie:

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

Wynik manifestu łączonego:

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

Plik manifestu 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>

Plik manifestu o wysokim priorytecie:

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

Wynik manifestu łączonego:

<activity-alias android:name="com.example.alias">
</activity-alias>
tools:node="replace"
Zastąp całkowicie element o niższym priorytecie. Oznacza to, że jeśli w pliku manifestu o niższym priorytecie znajduje się pasujący element, należy go zignorować i użyć tego elementu dokładnie w takiej postaci, w jakiej występuje w tym pliku manifestu.

Plik manifestu 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>

Plik manifestu 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 manifestu łączonego:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="fox"
      android:value="@string/dingeringeding"/>
</activity-alias>
tools:node="strict"
Generuje błąd kompilacji, gdy ten element w pliku manifestu o niższym priorytecie nie pasuje dokładnie do elementu w pliku manifestu o wyższym priorytecie (chyba że zostanie to rozwiązane przez inne znaczniki reguł scalania). Zastępuje to heurystykę konfliktów scalania. Jeśli na przykład plik manifestu o niższym priorytecie zawiera dodatkowy atrybut, kompilacja się nie powiedzie (podczas gdy działanie domyślne dodaje dodatkowy atrybut do manifestu łączonego).

Plik manifestu 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>

Plik manifestu 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 rozbieżności, musisz zastosować inne znaczniki reguł scalania. (Bez tools:node="strict" te 2 pliki można scalić bez błędów, jak pokazano w przykładzie dla tools:node="merge").

Znaczniki atrybutów

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

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

Plik manifestu o niskim priorytecie:

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

Plik manifestu o wysokim priorytecie:

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

Wynik manifestu łączonego:

<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 manifestu. Innymi słowy, zawsze zachowuj wartości z pliku manifestu o wyższym priorytecie.

Plik manifestu o niskim priorytecie:

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

Plik manifestu 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 manifestu łączonego:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
tools:strict="attr, ..."
Generuj błąd kompilacji za każdym razem, gdy te atrybuty w pliku manifestu o niższym priorytecie nie pasują dokładnie do atrybutów w pliku manifestu o wyższym priorytecie. Jest to działanie domyślne w przypadku wszystkich atrybutów z wyjątkiem tych, które mają specjalne zachowania opisane w sekcji Heurystyka konfliktów scalania.

Plik manifestu o niskim priorytecie:

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

Plik manifestu 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ł scalania. Jest to działanie domyślne, więc ten sam wynik uzyskasz, dodając jawnie tools:strict="screenOrientation".

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

Plik manifestu o niskim priorytecie:

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

Plik manifestu 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 manifestu łączonego:

<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 konkretnej zaimportowanej biblioteki, dodaj atrybut tools:selector z nazwą pakietu biblioteki.

Na przykład w przypadku poniższego pliku manifestu reguła scalania 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 plik manifestu o niższym priorytecie pochodzi z innego źródła, reguła scalania remove jest ignorowana.

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

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

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

Jeśli na przykład główny plik manifestu aplikacji stosuje overrideLibrary w 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"/>
...

Wtedy ten manifest można scalić bez błędu dotyczącego tagu <uses-sdk>, a scalony manifest zachowa minSdk="2" z manifestu aplikacji.

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

Niejawne uprawnienia systemowe

Niektóre interfejsy API Androida, które kiedyś były swobodnie dostępne dla aplikacji, w nowszych wersjach Androida zostały ograniczone przez uprawnienia systemowe.

Aby uniknąć awarii aplikacji, które oczekują 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 ustawiona na niższą niż wersja, w której dodano ograniczenie. To zachowanie przyznaje aplikacji domyślne uprawnienia dostępu do interfejsów API. Może to mieć wpływ na pliki manifestu łączonego, które mają różne wartości targetSdkVersion.

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

Jeśli na przykład w aplikacji ustawisz targetSdkVersion na 4 lub więcej i zaimportujesz bibliotekę z targetSdkVersion ustawionym na 3 lub mniej, narzędzie łączące doda do manifestu łączonego uprawnienie WRITE_EXTERNAL_STORAGE.

Tabela 2 zawiera listę wszystkich możliwych uprawnień, które można dodać do manifestu łączonego:

Tabela 2. Lista uprawnień, które narzędzie łączące może dodać do manifestu łączonego

Deklaracje pliku manifestu o niższym priorytecie Uprawnienia dodane do manifestu łączonego
targetSdkVersion wynosi 3 lub mniej WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
targetSdkVersion ma wersję 15 lub starszą i używa modułu READ_CONTACTS READ_CALL_LOG
targetSdkVersion ma wersję 15 lub starszą i używa modułu WRITE_CONTACTS WRITE_CALL_LOG

Sprawdzanie manifestu łączonego i znajdowanie konfliktów

Zanim utworzysz aplikację, możesz wyświetlić podgląd manifestu łączonego. Aby wyświetlić podgląd:

  1. W Android Studio otwórz plik AndroidManifest.xml.
  2. Kliknij kartę Merged Manifest (Manifest łączony) u dołu edytora.

Widok manifestu łączonego pokazuje wyniki manifestu łączonego po lewej stronie i informacje o każdym pliku manifestu łączonego po prawej stronie, jak pokazano na rysunku 2.

Elementy scalone z plików manifestu o niższym priorytecie są wyróżnione po lewej stronie różnymi kolorami. Legenda dla każdego koloru jest podana w sekcji Źródła pliku manifestu.

Widok manifestu łączonego
Rysunek 2. Widok manifestu łączonego.

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 tym, skąd pochodzi dany element, kliknij go w lewym panelu. Szczegóły pojawią się w sekcji Dziennik scalania.

Jeśli wystąpią konflikty, pojawią się one w sekcji Błędy scalania wraz z zaleceniem, jak rozwiązać konflikt za pomocą znaczników reguł scalania.

Błędy są też wyświetlane w oknie Dziennik zdarzeń. Aby je wyświetlić, wybierz View > Tool Windows > Event Log (Widok > Okna narzędzi > Dziennik zdarzeń).

Pełny dziennik drzewa decyzyjnego scalania znajdziesz w pliku dziennika o nazwie manifest-merger-buildVariant-report.txt w katalogu build/outputs/logs/ modułu.

Zasady scalania

Narzędzie łączące pliki manifestu może logicznie dopasować każdy element XML z jednego pliku manifestu do odpowiedniego elementu w innym pliku. Narzędzie do scalania dopasowuje każdy element za pomocą klucza dopasowania, który jest 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 je, używając jednej z 3 zasad scalania:

Scal
Połącz wszystkie niekonfliktowe atrybuty w tym samym tagu i scal elementy podrzędne zgodnie z odpowiednimi zasadami scalania. Jeśli jakieś atrybuty są ze sobą sprzeczne, scal je za pomocą znaczników reguł scalania.
Scal tylko elementy podrzędne
Nie łącz atrybutów (zachowaj tylko atrybuty podane w pliku manifestu o najwyższym priorytecie) i scal elementy podrzędne zgodnie z ich zasadami scalania.
Keep
Pozostaw element bez zmian i dodaj go do wspólnego elementu nadrzędnego w scalanym pliku. Używa się go tylko wtedy, gdy dopuszczalne jest kilka deklaracji tego samego elementu.

Tabela 3 zawiera listę typów elementów, typów używanych zasad scalania i kluczy używanych do określania dopasowania elementów między 2 plikami manifestu:

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

Element Zasada scalania Klucz dopasowania
<action> Scal Atrybut android:name
<activity> Scal Atrybut android:name
<application> Scal Możesz mieć tylko 1 taką kartę na <manifest>.
<category> Scal Atrybut android:name
<data> Scal Możesz mieć tylko 1 taką kartę na <intent-filter>.
<grant-uri-permission> Scal Możesz mieć tylko 1 taką kartę na <provider>.
<instrumentation> Scal Atrybut android:name
<intent-filter> Keep Brak dopasowania; dozwolonych jest kilka deklaracji w elemencie nadrzędnym.
<manifest> Scal tylko elementy podrzędne W każdym pliku może być tylko jeden taki wiersz.
<meta-data> Scal Atrybut android:name
<path-permission> Scal Możesz mieć tylko 1 taką kartę na <provider>.
<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 Możesz mieć tylko 1 taką kartę na <manifest>.
<uses-configuration> Scal Możesz mieć tylko 1 taką kartę na <manifest>.
<uses-feature> Scal Atrybut android:name (jeśli nie jest obecny, atrybut android:glEsVersion)
<uses-library> Scal Atrybut android:name
<uses-permission> Scal Atrybut android:name
<uses-sdk> Scal Możesz mieć tylko 1 taką kartę na <manifest>.
Elementy niestandardowe Scal Brak dopasowania – te elementy są nieznane narzędziu łączącemu i są zawsze uwzględniane w manifeście łączonym.

Wstrzykiwanie zmiennych kompilacji do pliku manifestu

Jeśli musisz 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 tutaj:

Dynamiczny

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

Kotlin

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

Następnie możesz wstawić jeden z obiektów 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 obiekcie zastępczym ${applicationId}. Wartość zawsze odpowiada ostatecznemu identyfikatorowi aplikacji dla bieżącej kompilacji, w tym zmianom wprowadzonym przez warianty kompilacji. Jest to przydatne, gdy chcesz używać unikalnej przestrzeni nazw dla identyfikatorów, takich jak działanie intencji, nawet między wariantami kompilacji.

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

Dynamiczny

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 do pliku manifestu w ten sposób:

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

Wynikowy plik manifestu po utworzeniu wariantu usługi „free” wygląda tak:

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

Więcej informacji znajdziesz w artykule Ustawianie identyfikatora aplikacji.