Outils: remplacer sans remplacer dans le manifeste Android

147

J'utilise un projet gradle avec de nombreuses dépendances de bibliothèques différentes et j'utilise la nouvelle fusion manifeste. Dans mon <application />tag, je l'ai configuré comme tel:

<application tools:replace="android:icon, android:label, android:theme, android:name"
    android:name="com.example.myapp.MyApplcation"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/application_name"
    android:logo="@drawable/logo_ab"
    android:theme="@style/AppTheme"
    >
....
</application>

Pourtant, je reçois l'erreur:

/android/MyApp/app/src/main/AndroidManifest.xml:29:9        Error:
Attribute application@icon value=(@drawable/ic_launcher) from AndroidManifest.xml:29:9
is also present at {Library Name} value=(@drawable/app_icon)
Suggestion: add 'tools:replace="android:icon"' to <application> element at AndroidManifest.xml:26:5 to override

/android/MyApp/app/src/main/AndroidManifest.xml:30:9 Error:
Attribute application@label value=(@string/application_name) from AndroidManifest.xml:30:9
is also present at {Library Name} value=(@string/app_name)
Suggestion: add 'tools:replace="android:label"' to <application> element at AndroidManifest.xml:26:5 to override

/android/MyApp/app/src/main/AndroidManifest.xml:27:9 Error:
Attribute application@name value=(com.example.myapp.MyApplication) from AndroidManifest.xml:27:9
is also present at {Another Library}

Suggestion: add 'tools:replace="android:name"' to <application> element at AndroidManifest.xml:26:5 to override

/android/MyApp/app/src/main/AndroidManifest.xml:32:9 Error:
Attribute application@theme value=(@style/AppTheme) from AndroidManifest.xml:32:9
is also present at {Library Name} value=(@style/AppTheme)
Suggestion: add 'tools:replace="android:theme"' to <application> element at AndroidManifest.xml:26:5 to override
agrosner
la source
1
Voir ce post dans Meta sur la suppression et la re-publication de questions: meta.stackoverflow.com/questions/265233/… . Faire cela une fois ne vous nuira pas particulièrement, mais il ne serait pas bon d'en faire une pratique régulière.
Scott Barta
1
Je suppose qu'il y a une <application>balise répétée dans le projet. Veuillez vous assurer qu'il n'y en a qu'un <application>.
Panther
Il peut y avoir de nombreuses balises <application> dans un projet, en particulier si vous utilisez un nombre quelconque de sous-modules de bibliothèque.
agrosner
J'ai des exemples de cas où cela fonctionne très bien. Quelle version des outils de build Android utilisez-vous?
G. Blake Meike
avez-vous ajouté xmlns: tools = " schemas.android.com/tools " dans la balise manifest? tools.android.com/tech-docs/new-build-system/user-guide
TouchBoarder

Réponses:

233

Déclarez votre en-tête manifeste comme ceci

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

Ensuite, vous pouvez ajouter à votre balise d'application l'attribut suivant:

<application
    tools:replace="icon, label" ../>

Par exemple, je dois remplacer l'icône et l'étiquette. Bonne chance!

Andrus
la source
1
comment gérez-vous android: nom avec des méta-données? android: name = "com.orm.SugarApp"> <meta-data android: name = "DATABASE" android: value = "sv_logs.db" /> <meta-data android: name = "VERSION" android: value = " 3 "/> <meta-data android: name =" QUERY_LOG "android: value =" true "/> <meta-data android: name =" DOMAIN_PACKAGE_NAME "android: value =" com.example.app "/>
Alan
@Alan Remplacez simplement toute la balise de méta-données par tools:node="replace": <meta-data tools:node="replace" android:name="QUERY_LOG" android:value="true" />etc.
Blacklight
25
Je suis confus. N'est-ce pas exactement ce qu'il fait dans sa question?
Jason Robinson
J'ai ajouté tools:replaceà ma balise d'application qui devrait la remplacer et non la source qui devrait être remplacée. Les manifestes de mon application remplacent donc ce qui est défini dans ma bibliothèque. Vous dites "ce qui doit être remplacé" au lieu de "ce qui peut être remplacé". J'espère que cela clarifie les questions.
WarrenFaith
1
Si l'attribut remplacé est dans la balise manifest, le tools:replace="android:versionCode, android:versionName"doit être à l'intérieur de la <manifest >balise.
Ivan Chau
42

J'ai résolu le même problème. Solution pour moi:

  1. ajouter la xmlns:tools="http://schemas.android.com/tools"ligne dans la balise manifeste
  2. ajouter tools:replace=..la balise manifeste
  3. déplacer android:label=...dans la balise manifeste

Exemple:

 <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
              tools:replace="allowBackup, label"
              android:allowBackup="false"
              android:label="@string/all_app_name"/>
Stefan K
la source
1
Merci pour cela, l'ajouter <manifest>directement au lieu de sous <application>était la seule chose qui a résolu mon problème.
A. Sokol
1
Je n'ai pas travaillé pour moi, je devrais mettre des outils: replace = "android: allowBackup, android: label" ni seulement des outils: replace = "allowBackup, label".
jmarkstar
1
Êtes-vous sûr que cela fonctionne? Parce que pour moi, on dirait que vous écrivez le allowBackup au mauvais endroit, et qu'après la fusion, ce que la bibliothèque a spécifié sur son manifeste prévaut. Vous n'avez pas de conflit après l'avoir déplacé sur le dessus, car vous le faites simplement mal ( developer.android.com/guide/topics/manifest/… ) AllowBackup appartient à l'élément Application.
Reinherd
2
[... continue d'en haut] CELA NE FONCTIONNE PAS. Vous écrivez le allowBackup au mauvais endroit, et qu'après la fusion, ce que la bibliothèque a spécifié sur son manifeste prévaut. Vous n'avez pas de conflit après l'avoir déplacé sur le dessus, car vous le faites simplement mal ( developer.android.com/guide/topics/manifest/… ) AllowBackup appartient à l'élément Application. Je l'ai testé en décompilant un APK, et le manifeste final avait la valeur TRUE au lieu de FALSE comme je l'ai spécifié comme vous l'avez suggéré
Reinherd
38

Essayez de réorganiser vos dépendances dans votre fichier gradle. J'ai dû déplacer la bibliothèque incriminée du bas de la liste vers le haut, puis cela a fonctionné.

Joie
la source
s'il vous plaît dites-moi une chose outils: remplacer dois-je ajouter cette balise d'application interne du manifeste de mon projet ou la balise d'application interne de ma bibliothèque s'il vous plaît dites-moi que ce sera vraiment utile pour moi ??
Sudhanshu Gaur
@SudhanshuGaur Il vous suffit de l'ajouter au fichier AndroidManifest.xml de votre projet.
Kyle Liu
74
Ça a marché. Mais de telles solutions peuvent retirer la foi de l'humanité.
Vinay Patil
8
#android gotchas comme ceux-ci rendent le développement pour Android assez ennuyeux
Taylor Halliday
1
Si vous avez plusieurs types de produits comme play et non play et que la dépendance est "playReleaseCompile ______", il se peut que le simple déplacement de l'instruction vers le haut ne fonctionne pas, vous devrez peut-être changer l'instruction en "compile ______", puis la déplacer vers le Haut. Cela devrait fonctionner alors.
Soham
33

Je viens de vivre le même comportement tools:replace=...que celui décrit par l'OP.

Il s'est avéré que la cause première de l' tools:replaceignorance de la fusion du manifeste est un bogue décrit ici . Cela signifie essentiellement que si vous avez une bibliothèque dans votre projet qui contient un manifeste avec un <application ...>nœud contenant un tools:ignore=...attribut, il peut arriver que l' tools:replace=...attribut dans le manifeste de votre module principal soit ignoré.

Le point délicat ici est que cela peut arriver, mais ce n'est pas obligatoire. Dans mon cas, j'avais deux bibliothèques, la bibliothèque A avec l' tools:ignore=...attribut, la bibliothèque B avec les attributs à remplacer dans les manifestes respectifs et l' tools:replace=...attribut dans le manifeste du module principal. Si le manifeste de B était fusionné dans le manifeste principal avant le manifeste de A, tout fonctionnait comme prévu. Dans l'ordre de fusion opposé, l'erreur est apparue.

L'ordre dans lequel ces fusions se produisent semble être quelque peu aléatoire. Dans mon cas, changer l'ordre dans la section dépendances de build.gradlen'a eu aucun effet, mais changer le nom de la saveur l'a fait.

Ainsi, la seule solution de contournement fiable semble être de décompresser la bibliothèque à l'origine du problème, de supprimer la tools:ignore=...balise (ce qui ne devrait pas poser de problème car il s'agit d'un indice pour les peluches uniquement) et de réemballer la bibliothèque.

Et votez pour que le bug soit corrigé, pour cause.

Nantoka
la source
Dans mon cas, j'ai dû supprimer des outils: ignorer de mon projet, pas d'une des bibliothèques
mohax
3
C'était aussi mon problème. Déplacement des outils: ignorer le <manifest>nœud du <application>nœud et cela a fonctionné.
Jacob Tabak
Je viens de rencontrer le même problème avec Bazel v2.0.0 a déposé un bogue ici github.com/bazelbuild/bazel/issues/10543
Nick Korostelev le
18

Solution de travail finale pour moi (mis en évidence les tages dans l'exemple de code):

  1. ajouter la xmlns:toolsligne dans la balise manifeste
  2. ajouter tools:replacela balise d'application

Exemple:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="pagination.yoga.com.tamiltv"
    **xmlns:tools="http://schemas.android.com/tools"**
    >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        **tools:replace="android:icon,android:theme"**
        >
Yogamurthy
la source
13

La pièce manquante pour moi était la suivante:

xmlns:tools="http://schemas.android.com/tools"

par exemple:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
    package="com.your.appid">
partizan
la source
Pouvez-vous partager votre code exactement comme vous l'avez dans le <manifest ...>?
partizan
8

Vous pouvez les remplacer dans votre balise d'application Manifest:

<application
    tools:replace="android:icon, android:label, android:theme, android:name,android:allowBackup"
android:allowBackup="false"...>

et travaillera pour vous.

Saurabh Gaddelpalliwar
la source
Cela ne fonctionne pas pour une raison quelconque .... J'essaie d'ajouter tools:replace="android:label"à l'application mais cela ne fonctionne pas
iKK
4

FIXE IL AVAIT L'ERREUR EXACTE, il suffit d'ajouter ces outils: replace = "android: icon, android: theme"

dans votre balise d' application dans votre manifeste, cela fonctionne très bien,

Ismael Ozil
la source
c'est normal. ce qui est sujet n'est pas un comportement normal qui se produit dans certains cas lorsque même des outils: remplacer sont ajoutés.
David
4

Vous pouvez les remplacer dans votre applicationbalise Manifest :

<application
    ...
    tools:replace="android:label, android:icon, android:theme"/>

et travaillera pour vous.

Explication

L'utilisation d'une telle dépendance / bibliothèque dans votre gradlefichier qui a ces étiquettes dans la balise d'application de son manifeste peut produire ce problème et les remplacer dans votre Manifestest la solution.

blueware
la source
1

Le hack suivant fonctionne:

  1. ajouter la xmlns:tools="http://schemas.android.com/tools"ligne dans la balise manifeste
  2. ajouter tools:replace="android:icon,android:theme,android:allowBackup,label" la balise d'application
Shoaib Ahmed
la source
1

Mon problème est un projet multi-modules avec un module de base, un module d'application et un module de fonctionnalités. Chaque module a son propre AndroidManifest, et j'ai implémenté une variante de construction pour le débogage et le main. Nous devons donc nous assurer que "android: name" vient d'être déclaré dans Manifest de debug et main uniquement, et ne le définissez dans aucun Manifest dans le module enfant. Ex: Manifeste en main:

 <application
        android:name=".App"/>

Manifeste dans le débogage:

<application
        tools:replace="android:name"
        android:name=".DebugApp"
        />

Ne définissez pas "android: nom" dans d'autres fichiers Manifest comme ceci:

<application android:name=".App">

Il suffit de définir dans le module de fonctionnalités comme celui-ci et il fusionnera bien

<application> 
Hoang Minh
la source
0

Je recevais une erreur similaire sur un projet que j'importais:

Plusieurs entrées avec la même clé: android: icon = REMPLACER et outils: icon = REMPLACER

Correction après avoir changé la ligne ci-dessous dans la balise d'application:

tools:replace="icon, label, theme"

à

tools:replace="android:icon, android:label, android:theme"
brybry
la source
0

J'ai également traversé ce problème et changé cela:

<application  android:debuggable="true" android:icon="@drawable/app_icon" android:label="@string/app_name" android:supportsRtl="true" android:allowBackup="false" android:fullBackupOnly="false" android:theme="@style/UnityThemeSelector">

à

 <application tools:replace="android:allowBackup" android:debuggable="true" android:icon="@drawable/app_icon" android:label="@string/app_name" android:supportsRtl="true" android:allowBackup="false" android:fullBackupOnly="false" android:theme="@style/UnityThemeSelector">
Saeed Aliakbari
la source
0
 tools:replace="android:supportsRtl,android:allowBackup,icon,label">
studio android
la source