Zarządzaj plikami manifestu

Na tej stronie opisujemy, jak działa scalanie plików manifestu i jak można zastosować ustawienia scalania do rozwiązywania konfliktów. Wprowadzenie do pliku manifestu aplikacji znajdziesz w omówieniu pliku manifestu aplikacji.

Scalanie 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 pochodzących z głównego zbioru źródłowego, wariantów kompilacji i zaimportowanych bibliotek. Podczas tworzenia aplikacji kompilacja Gradle scala wszystkie pliki manifestu w jeden plik spakowany do aplikacji.

Narzędzie do łączenia plików manifestu łączy wszystkie elementy XML z każdego pliku, stosując metody heurystyczne i stosując się do zdefiniowanych przez Ciebie preferencji scalania ze specjalnymi atrybutami XML.

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

Scal priorytety

Narzędzie do scalania łączy kolejno wszystkie pliki manifestu w jeden plik, zgodnie z priorytetem każdego z nich. Jeśli np. masz 3 pliki manifestu, plik manifestu o najniższym priorytecie jest scalony z plikiem manifestu o najwyższym priorytecie, a potem scalony z plikiem manifestu o najwyższym priorytecie, jak widać na ilustracji 1.

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

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

  1. Plik manifestu dla wariantu kompilacji

    Jeśli wariant ma wiele zbiorów źródeł, ich priorytety w pliku manifestu są takie:

    • Utwórz plik manifestu wariantu (np. src/demoDebug/)
    • Plik manifestu typu kompilacji (np. src/debug/)
    • Plik manifestu rodzaju produktu (np. src/demo/)

      Jeśli używasz wymiarów zestawienia, priorytety w pliku manifestu odpowiadają kolejności, w jakiej każdy wymiar jest wymieniony we właściwości flavorDimensions (pierwszy jest najwyższy).

  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 są zgodne z kolejnością w bloku dependencies Gradle.

Na przykład plik manifestu biblioteki zostanie scalony z głównym plikiem manifestu, a potem główny plik manifestu zostanie scalony z plikiem manifestu wariantu kompilacji. Pamiętaj, że są to te same priorytety scalania dla wszystkich zbiorów źródeł, co zostało opisane w sekcji Tworzenie z użyciem zbiorów źródłowych.

Ważne: konfiguracje kompilacji z pliku build.gradle zastępują wszystkie odpowiadające im atrybuty w scalonym pliku manifestu. Na przykład atrybut minSdk z pliku build.gradle lub build.gradle.kts zastępuje pasują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 o konfigurowaniu kompilacji.

Heurystyka konfliktu w scalaniu

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

Jeśli element z pliku manifestu o niższym priorytecie nie pasuje do żadnych elementów w pliku manifestu o wyższym priorytecie, zostaje dodany do scalonego pliku manifestu. Jeśli jednak istnieje pasujący element, narzędzie do scalenia spróbuje połączyć wszystkie atrybuty z każdego w ten sam element. Jeśli narzędzie wykryje, że oba pliki manifestu zawierają ten sam atrybut o różnych wartościach, wystąpi konflikt dotyczący scalania.

Tabela 1 przedstawia możliwe wyniki uzyskane w przypadku próby połączenia wszystkich atrybutów w jednym elemencie przez narzędzie do scalania.

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

Atrybut o wysokim priorytecie Atrybut o niskim priorytecie Wynik scalony 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.

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

  • Atrybuty w elemencie <manifest> nigdy nie są ze sobą scalane. Używane są tylko atrybuty z pliku manifestu o najwyższym priorytecie.
  • Atrybut android:required w elementach <uses-feature> i <uses-library> korzysta z scalania OR. W przypadku konfliktu stosowany jest "true", a funkcja lub biblioteka wymagana przez jeden plik manifestu jest zawsze uwzględniana.
  • Atrybuty w elemencie <uses-sdk> zawsze używają wartości z pliku manifestu o wyższym priorytecie. Wyjątkiem są te sytuacje:
    • Gdy w pliku manifestu o niższym priorytecie wartość minSdk jest większa, wystąpi błąd, chyba że zastosujesz regułę scalania overrideLibrary.
    • Gdy w pliku manifestu o niższym priorytecie wartość targetSdkVersion jest niższa, narzędzie do łączenia używa wartości z pliku manifestu o wyższym priorytecie i dodaje też wszelkie uprawnienia systemowe, które są niezbędne do zapewnienia prawidłowego działania zaimportowanej biblioteki (w przypadkach, gdy wyższa wersja Androida ma wyższe ograniczenia uprawnień). Więcej informacji o tym zachowaniu znajdziesz w sekcji na temat niejawnych uprawnień systemowych.
  • Element <intent-filter> nigdy nie jest dopasowywany w plikach manifestu. Każdy element jest traktowany jako unikalny i dodawany do wspólnego elementu nadrzędnego w scalonym pliku manifestu.

W przypadku wszystkich pozostałych konfliktów między atrybutami pojawia się błąd i musisz poinstruować narzędzie do scalania, jak rozwiązać ten problem, dodając atrybut specjalny w pliku manifestu o wyższym priorytecie. Zapoznaj się z sekcją o znacznikach reguł scalania.

Nie zależą od domyślnych wartości atrybutów. Wszystkie unikalne atrybuty są łączone w ten sam element, więc może to spowodować nieoczekiwane wyniki, jeśli plik manifestu o wyższym priorytecie zależy od wartości domyślnej atrybutu bez jej 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 zadeklaruje ten atrybut z inną wartością, zostanie ona zastosowana do scalonego pliku manifestu, co zastąpi wartość domyślną. Każdy atrybut musisz wyraźnie zdefiniować. Domyślne wartości każdego atrybutu są opisane w dokumentacji manifestu.

Scal znaczniki reguł

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

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

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

<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 manifestu i do wszystkich jego tagów podrzędnych), użyj tych atrybutów:

tools:node="merge"
Jeśli nie ma konfliktów, połącz wszystkie atrybuty w tym tagu i wszystkie zagnieżdżone elementy, korzystając z heurystyki scalania konfliktów. Jest to domyślne działanie 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>

Scalony wynik 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"
Scal atrybuty tylko w tym tagu. Nie scalaj zagnieżdżonych 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" />
        <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="merge-only-attributes">
</activity>

Scalony wynik pliku manifestu:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
</activity>
tools:node="remove"
Usuń ten element ze scalonego pliku manifestu. Ta opcja jest używana, gdy w scalonym pliku manifestu znajdziesz element, który nie jest Ci potrzebny. Został on udostępniony w pliku manifestu o niższym priorytecie, nad którym nie masz kontroli (np. zaimportowana biblioteka).

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>

Scalony wynik pliku manifestu:

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

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>

Scalony wynik 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ę pasujący element, zignoruj go i użyj go dokładnie w takiej formie, 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>

Scalony wynik 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 za każdym razem, gdy ten element w pliku manifestu o niższym priorytecie nie będzie dokładnie zgodny z elementem w pliku manifestu o wyższym priorytecie (chyba że zostaną rozwiązane przez inne znaczniki reguł scalania). Powoduje to zastąpienie heurystyki scalania konfliktów. Jeśli na przykład plik manifestu o niższym priorytecie zawiera dodatkowy atrybut, kompilacja nie powiedzie się (podczas gdy działanie domyślne powoduje dodanie dodatkowego atrybutu do scalonego pliku manifestu).

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 manifestu nie mogą się różnić. Aby złagodzić te różnice, musisz zastosować inne znaczniki reguł scalania. (Bez parametru tools:node="strict" te 2 pliki mogą się scalić bez błędów, jak widać w przykładzie dla pliku tools:node="merge").

Znaczniki atrybutów

Aby zamiast tego zastosować regułę scalania tylko do określonych atrybutów w tagu manifestu, użyj podanych niżej atrybutów. Każdy atrybut może mieć co najmniej 1 nazwę atrybutu (łącznie z przestrzenią nazw atrybutów) rozdzielonych przecinkami.

tools:remove="attr, ..."
Usuń określone atrybuty ze scalonego pliku manifestu. Tej opcji należy używać, gdy plik manifestu o niższym priorytecie zawiera te atrybuty i nie chcesz, aby zostały one umieszczone w scalonym pliku manifestu.

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

Scalony wynik 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 tymi 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">

Scalony wynik pliku manifestu:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
tools:strict="attr, ..."
Za każdym razem, gdy atrybuty w pliku manifestu o niższym priorytecie nie będą dokładnie zgodne z atrybutami w pliku manifestu o wyższym priorytecie, spowoduje to błąd kompilacji. Jest to domyślne działanie w przypadku wszystkich atrybutów oprócz tych z zachowaniami specjalnymi, jak opisano w sekcji scalanie heurystyki konfliktów.

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 taki sam efekt może mieć jawne dodanie parametru tools:strict="screenOrientation".

Do jednego elementu możesz też zastosować wiele znaczników, 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">

Scalony wynik 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ł scalania tylko do określonej zaimportowanej biblioteki, dodaj atrybut tools:selector z nazwą pakietu biblioteki.

Na przykład w tym 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.

Uwaga: jeśli używasz tego atrybutu z jednym ze znaczników atrybutów, będzie on obowiązywał do wszystkich atrybutów wskazanych w znaczniku.

Zastąp <uses-sdk> zaimportowanych bibliotek

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

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

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

Potem ten plik manifestu można połączyć bez błędów dotyczących tagu <uses-sdk>, a scalony plik manifestu zatrzymuje 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" />
...

Pośrednie uprawnienia systemowe

W ostatnich wersjach Androida niektóre interfejsy API Androida, które były wcześniej bezpłatnie dostępne, 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 dalsze korzystanie z tych interfejsów bez uprawnień, jeśli targetSdkVersion ma wartość niższą niż wersja, w której dodano ograniczenie. Takie zachowanie powoduje przyznanie aplikacji niejawnych uprawnień zezwalających na dostęp do interfejsów API. Może to mieć wpływ na scalone pliki manifestu, które mają różne wartości parametru targetSdkVersion.

Jeśli plik manifestu o niższym priorytecie ma mniejszą wartość w polu targetSdkVersion, która daje mu niejawne uprawnienia, a plik manifestu o wyższym priorytecie nie ma tego samego uprawnienia pośredniego (ponieważ jego targetSdkVersion jest równy lub wyższy niż wersja, w której dodano ograniczenie), narzędzie do scalania wyraźnie dodaje uprawnienia systemowe do scalonego pliku manifestu.

Jeśli na przykład aplikacja ustawia targetSdkVersion na 4 lub więcej i zaimportuje bibliotekę z atrybutem targetSdkVersion ustawionym na 3 lub mniej, narzędzie do scalania doda do scalonego pliku manifestu uprawnienie WRITE_EXTERNAL_STORAGE.

W tabeli 2 znajdziesz listę wszystkich możliwych uprawnień, które można dodać do scalonego pliku manifestu:

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

Deklarowany plik manifestu o niższym priorytecie Uprawnienia dodane do scalonego pliku manifestu
targetSdkVersion to 3 lub mniej WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
targetSdkVersion ma 15 lub mniej lat i korzysta z READ_CONTACTS READ_CALL_LOG
targetSdkVersion ma 15 lub mniej lat i korzysta z WRITE_CONTACTS WRITE_CALL_LOG

Sprawdź scalony plik manifestu i znajdź konflikty

Zanim utworzysz aplikację, możesz zobaczyć podgląd scalonego pliku manifestu. Aby wyświetlić podgląd:

  1. W Android Studio otwórz plik AndroidManifest.xml.
  2. Kliknij kartę Plik manifestu scalonego pliku u dołu edytora.

W widoku scalonego pliku manifestu po lewej stronie są widoczne wyniki scalonego pliku manifestu, a po prawej – informacje o każdym scalonym pliku manifestu, jak widać na ilustracji 2.

Elementy, które zostały scalone z plików manifestu o niższym priorytecie, są podświetlone innymi kolorami po lewej stronie. Klucz każdego koloru jest określony w sekcji Źródła pliku manifestu.

Rysunek 2. Widok pliku manifestu scalonego pliku.

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

Aby zobaczyć, skąd pochodzi element, kliknij go w panelu po lewej stronie. Szczegóły pojawią się w sekcji Dziennik łączenia.

Jeśli wystąpią konflikty, pojawią się w sekcji Błędy scalania z rekomendacją sposobu rozwiązania konfliktu przy użyciu znaczników reguł scalania.

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

Pełny dziennik drzewa decyzji o scalaniu znajdziesz w katalogu build/outputs/logs/ modułu o nazwie manifest-merger-buildVariant-report.txt. Znajdziesz go w pliku logu.

Zasady scalania

Za pomocą tego narzędzia można logicznie dopasować każdy element XML z jednego pliku manifestu do odpowiedniego elementu w innym pliku. Scalanie dopasowuje każdy element za pomocą klucza dopasowania – unikalnej wartości atrybutu (np. android:name) lub naturalnej niepowtarzalności samego tagu (np. może istnieć tylko jeden element <supports-screen>).

Jeśli 2 pliki manifestu mają ten sam element XML, narzędzie łączy je za pomocą jednej z 3 zasad scalania:

Scal
Połącz wszystkie atrybuty niebędącego w konflikcie w ten sam tag i scal elementy podrzędne zgodnie z odpowiednimi zasadami scalania. Jeśli jakieś atrybuty są ze sobą sprzeczne, scal je ze znacznikami reguł scalania.
Scal tylko elementy podrzędne
Nie łącz ani nie scalaj atrybutów (zachowuj tylko atrybuty podane w pliku manifestu o najwyższym priorytecie) i nie scalaj elementów podrzędnych zgodnie z zasadami scalania.
Keep
Pozostaw element w niezmienionej formie i dodaj go do wspólnego elementu nadrzędnego w scalonym pliku. Jest ona używana tylko wtedy, gdy dopuszczalne jest posiadanie kilku deklaracji tego samego elementu.

W tabeli 3 znajdziesz listę poszczególnych typów elementów, typów użytych zasad scalania i klucza służącego do określania dopasowania elementów w 2 plikach manifestu:

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

Żywioły Zasada scalania Klucz dopasowania
<action> Scal Atrybut android:name
<activity> Scal Atrybut android:name
<application> Scal Na każde <manifest> przypada tylko jedno zamówienie.
<category> Scal Atrybut android:name
<data> Scal Na każde <intent-filter> przypada tylko jedno zamówienie.
<grant-uri-permission> Scal Na każde <provider> przypada tylko jedno zamówienie.
<instrumentation> Scal Atrybut android:name
<intent-filter> Keep Brak dopasowania. Dozwolonych jest kilka deklaracji w elemencie nadrzędnym.
<manifest> Scal tylko elementy podrzędne Dotyczy tylko jednego pliku.
<meta-data> Scal Atrybut android:name
<path-permission> Scal Na każde <provider> przypada tylko jedno zamówienie.
<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 Na każde <manifest> przypada tylko jedno zamówienie.
<uses-configuration> Scal Na każde <manifest> przypada tylko jedno zamówienie.
<uses-feature> Scal Atrybut android:name (jeśli go nie ma, użyj atrybutu android:glEsVersion)
<uses-library> Scal Atrybut android:name
<uses-permission> Scal Atrybut android:name
<uses-sdk> Scal Na każde <manifest> przypada tylko jedno zamówienie.
Elementy niestandardowe Scal Brak dopasowań; są one nieznane dla narzędzia do scalania i zawsze są uwzględniane w scalonym pliku manifestu.

Wstaw zmienne 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ść wykorzystuje mapę par klucz-wartość, tak jak na przykładzie poniżej:

Odlotowy

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

Kotlin

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

Następnie możesz wstawić do pliku manifestu jedną z tych zmiennych 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 w bieżącej kompilacji (obejmuje to zmiany według jej wariantów). Jest to przydatne, gdy chcesz używać unikalnej przestrzeni nazw na potrzeby identyfikatorów takich jak działanie intencji, nawet w różnych wariantach kompilacji.

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

Odlotowy

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>

Wynik po utworzeniu „bezpłatnego” rodzaju produktu w pliku manifestu będzie wyglądał tak:

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

Więcej informacji znajdziesz w artykule Ustawianie identyfikatora aplikacji.