J'ai configuré Gradle pour ajouter le suffixe de nom de package à mon application de débogage afin que je puisse avoir la version de sortie que j'utilise et la version de débogage sur un téléphone. Je faisais référence à ceci: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types
Mon fichier build.gradle ressemble à ceci:
...
android
{
...
buildTypes
{
debug
{
packageNameSuffix ".debug"
versionNameSuffix " debug"
}
}
}
Tout fonctionne bien jusqu'à ce que je commence à utiliser un ContentProvider dans mon application. Je reçois:
Failure [INSTALL_FAILED_CONFLICTING_PROVIDER]
Je comprends que cela se produit parce que deux applications (version et débogage) enregistrent la même autorité ContentProvider.
Je vois une possibilité de résoudre ce problème. Si je comprends bien, vous devriez pouvoir spécifier différents fichiers à utiliser lors de la construction. Ensuite, je devrais être en mesure de mettre différentes autorités dans différents fichiers de ressources (et à partir de l'autorité de jeu Manifest en tant que ressource de chaîne) et dire à Gradle d'utiliser une ressource différente pour la construction de débogage. Est-ce possible? Si oui, tout indice sur la façon d'y parvenir serait génial!
Ou peut-être est-il possible de modifier directement le manifeste à l'aide de Gradle? Toute autre solution sur la façon d'exécuter la même application avec ContentProvider sur un appareil est toujours la bienvenue.
Réponses:
Aucune des réponses existantes ne m'a satisfait, cependant Liberty était proche. Alors voilà comment je fais. Tout d'abord en ce moment je travaille avec:
Mon objectif est d'exécuter la
Debug
version avec laRelease
version sur le même appareil en utilisant le mêmeContentProvider
.Dans build.gradle de votre suffixe de jeu d'application pour la build Debug:
Dans le jeu de fichiers AndroidManifest.xml ,
android:authorities
propriété de votreContentProvider
:Dans votre propriété de jeu de codes
AUTHORITY
qui peut être utilisée partout où cela est nécessaire dans votre implémentation:Conseil: avant
BuildConfig.PACKAGE_NAME
C'est tout! Cela fonctionnera comme un charme. Continuez à lire si vous utilisez SyncAdapter!
Mise à jour pour SyncAdapter (14.11.2014)
Encore une fois, je vais commencer avec ma configuration actuelle:
Fondamentalement, si vous devez personnaliser certaines valeurs pour différentes versions, vous pouvez le faire à partir du fichier build.gradle:
BuildConfig.java
classeComme alternative aux ressources, vous pouvez créer des répertoires buildType ou flavour distincts et remplacer les XML ou les valeurs qu'ils contiennent. Cependant, je ne vais pas l'utiliser dans l'exemple ci-dessous.
Exemple
Dans le fichier build.gradle , ajoutez ce qui suit:
Vous verrez les résultats dans la classe BuildConfig.java
et dans build / generated / res / generated / debug / values / generated.xml
Dans votre authentificateur.xml, utilisez la ressource spécifiée dans le fichier build.gradle
Dans votre syncadapter.xml, utilisez à nouveau la même ressource et @ string / autorité aussi
Astuce: la saisie semi - automatique (Ctrl + Espace) ne fonctionne pas pour ces ressources générées, vous devez donc les saisir manuellement
la source
Nouvelle astuce pour le système de build Android: Renommer l'autorité ContentProvider
Je suppose que vous avez tous entendu parler du nouveau système de construction basé sur Android Gradle. Soyons honnêtes, ce nouveau système de construction est un énorme pas en avant par rapport au précédent. Ce n'est pas encore définitif (au moment d'écrire ces lignes, la dernière version est la 0.4.2) mais vous pouvez déjà l'utiliser en toute sécurité dans la plupart de vos projets.
J'ai personnellement basculé la plupart de mon projet vers ce nouveau système de construction et j'ai eu quelques problèmes à cause du manque de support dans certaines situations particulières. L'un d'eux est la prise en charge du changement de nom d'autorité ContentProvider
Le nouveau système Android intégré vous permet de gérer différents types de votre application en modifiant simplement le nom du package au moment de la construction. L'un des principaux avantages de cette amélioration est que vous pouvez désormais avoir deux versions différentes de votre application installées sur le même appareil en même temps. Par exemple:
En utilisant une telle configuration Gradle, vous pouvez assembler deux APK différents:
• Un APK de débogage avec le nom de package com.cyrilmottier.android.app.debug • Un APK de version avec le nom de package com.cyrilmottier.android.app
Le seul problème avec cela est que vous ne pourrez pas installer les deux APK en même temps s'ils exposent tous les deux un ContentProvider avec les mêmes autorités. Assez logiquement, nous devons renommer l'autorité en fonction du type de build actuel ... mais cela n'est pas supporté par le système de build Gradle (encore? ... Je suis sûr que cela sera corrigé bientôt). Alors, voici une voie à suivre:
Nous devons d'abord déplacer la déclaration ContentProvider du manifeste Android du fournisseur vers le type de construction approprié. Pour ce faire, nous aurons simplement:
src / debug / AndroidManifest.xml
src / release / AndroidManifest.xml
Assurez-vous de supprimer la déclaration ContentProvider du fichier AndroidManifest.xml dans src / main / car Gradle ne sait pas comment fusionner des ContentProviders ayant le même nom mais une autorité différente.
Enfin, nous pouvons avoir besoin d'accéder à l'autorité dans le code. Cela peut être fait assez facilement en utilisant le fichier BuildConfig et la méthode buildConfig:
Grâce à cette solution de contournement, vous pourrez utiliser BuildConfig.PROVIDER_AUTHORITY dans votre ProviderContract et installer deux versions différentes de votre application en même temps.
À l'origine sur Google+: https://plus.google.com/u/0/118417777153109946393/posts/EATUmhntaCQ
la source
Bien que l'exemple de Cyril fonctionne très bien si vous n'avez que quelques types de build, cela se complique rapidement si vous avez de nombreux types de build et / ou saveurs de produits car vous devez gérer de nombreux AndroidManifest.xml différents.
Notre projet se compose de 3 types de build différents et de 6 saveurs totalisant 18 variantes de build, nous avons donc ajouté la prise en charge de ".res-auto" dans les autorités ContentProvider, qui s'étendent au nom du pack actuel et suppriment le besoin de maintenir différents AndroidManifest.xml
Un exemple de code peut être trouvé ici: https://gist.github.com/cmelchior/6988275
la source
Depuis la version 0.8.3 du plugin (en fait 0.8.1 mais cela ne fonctionnait pas correctement), vous pouvez définir des ressources dans le fichier de construction afin que cela puisse être une solution plus propre car vous n'avez pas besoin de créer de fichiers de chaînes ni de débogage / version supplémentaire Dossiers.
build.gradle
AndroidManifest.xml
la source
Je ne sais pas si quelqu'un en a parlé. En fait, après le plugin android gradle 0.10+, la fusion du manifeste fournira le support officiel de cette fonction: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger
Dans AndroidManifest.xml, vous pouvez utiliser $ {packageName} comme ceci:
Et dans votre build.gradle, vous pouvez avoir:
Voir l'exemple complet ici: https://code.google.com/p/anymemo/source/browse/AndroidManifest.xml#152
et ici: https://code.google.com/p/anymemo/source/browse/build.gradle#41
la source
Utilisez des
${applicationId}
espaces réservés dans xml etBuildConfig.APPLICATION_ID
dans le code.Vous devrez étendre le script de génération pour activer les espaces réservés dans les fichiers xml autres que le manifeste. Vous pouvez utiliser un répertoire source par variante de construction pour fournir différentes versions des fichiers xml, mais la maintenance deviendra très vite fastidieuse.
AndroidManifest.xml
Vous pouvez utiliser l'espace réservé applicationId prêt à l'emploi dans le manifeste. Déclarez votre fournisseur comme ceci:
Notez le
${applicationId}
bit. Celui-ci est remplacé au moment de la construction par l'ID d'application réel pour la variante de construction en cours de construction.Dans du code
Votre ContentProvider doit construire la chaîne d'autorité dans le code. Il peut utiliser la classe BuildConfig.
Notez le
BuildConfig.APPLICATION_ID
bit. Il s'agit d'une classe générée avec l'identifiant d'application réel pour la variante de construction en cours de construction.res / xml / files, par exemple syncadapter.xml, accountauthenticator.xml
Si vous souhaitez utiliser un adaptateur de synchronisation, vous devrez fournir des métadonnées pour ContentProvider et AccountManager dans des fichiers xml dans le répertoire res / xml /. L'espace réservé applicationId n'est pas pris en charge ici. Mais vous pouvez étendre le script de construction vous-même pour le pirater.
Encore une fois, notez le
${applicationId}
. Cela ne fonctionne que si vous ajoutez le script gradle ci-dessous à la racine de votre module et que vous l'appliquez depuis build.gradle.build.gradle
Appliquez le script de construction supplémentaire à partir du script build.gradle du module. Un bon endroit est sous le plugin Android Gradle.
build-processApplicationId.gradle
Vous trouverez ci-dessous la source de travail d'un script de construction res / xml / placeholder. Une version mieux documentée est disponible sur github . Les améliorations et extensions sont les bienvenues.
Strings.xml
À mon avis, il n'est pas nécessaire d'ajouter un support d'espace réservé pour les chaînes de ressources. Pour le cas d'utilisation ci-dessus, au moins, ce n'est pas nécessaire. Cependant, vous pouvez facilement modifier le script pour remplacer non seulement les espaces réservés dans le répertoire res / xml /, mais également dans le répertoire res / values /.
la source
Je préférerais plutôt un mélange entre Cyril et rciovati. Je pense que c'est plus simple, vous n'avez que deux modifications.
Le
build.gradle
ressemble à:Et le
AndroidManifest.xml
:la source
gradle.build
authentificateur.xml
sync_adapter.xml
AndroidManifest.xml
Code:
la source
Sur la base de l'exemple de @ChristianMelchior, voici ma solution, qui corrige deux problèmes dans les solutions précédentes:
les solutions qui modifient values.xml dans le répertoire de construction provoquent une reconstruction complète des ressources (y compris une adaptation de tous les drawables)
pour une raison inconnue, IntelliJ (et probablement Android Studio) ne traite pas les ressources de manière fiable, ce qui fait que la compilation contient des
.res-auto
autorités de fournisseur non remplacéesCette nouvelle solution fait plus les choses à la manière Gradle en créant une nouvelle tâche et permet des constructions incrémentielles en définissant des fichiers d'entrée et de sortie.
créer un fichier (dans l'exemple, je l'ai mis dans un
variants
répertoire), formaté comme un fichier xml de ressources, qui contient des ressources de chaîne. Ceux-ci seront fusionnés dans les ressources de l'application, et toute occurrence de.res-auto
dans les valeurs sera remplacée par le nom du package de la variante, par exemple<string name="search_provider">.res-auto.MySearchProvider</string>
ajoutez le
build_extras.gradle
fichier de cet élément essentiel à votre projet et référencez-le à partir du fichier principalbuild.gradle
en ajoutantapply from: './build_extras.gradle'
quelque part au-dessus duandroid
blocassurez-vous de définir un nom de package par défaut en l'ajoutant au
android.defaultConfig
bloc debuild.gradle
dans
AndroidManifest.xml
et d'autres fichiers de configuration (commexml/searchable.xml
pour les fournisseurs de recherche de saisie semi-automatique), référencez le fournisseur (par exemple@string/search_provider
)si vous avez besoin du même nom, vous pouvez utiliser la
BuildConfig.PACKAGE_NAME
variable, par exempleBuildConfig.PACKAGE_NAME + ".MySearchProvider"
https://gist.github.com/paour/9189462
Mise à jour: cette méthode ne fonctionne que sur Android 2.2.1 et versions ultérieures. Pour les plates-formes antérieures, voyez cette réponse , qui a son propre ensemble de problèmes, car la nouvelle fusion manifeste est encore très difficile sur les bords ...
la source
variants/res-auto-values.xml
rapport à/Applications/Android Studio.app/bin/
. c'est-à-dire que je n'obtiens aucune FileNotFoundException pour/Applications/Android Studio.app/bin/variants/res-auto-values.xml
. Je cours sur un mac. C'est une excellente solution, mais j'aimerais qu'elle fonctionne dans l'EDI pour les autres membres de l'équipe.System.getProperty("user.dir")
, qui renvoie un résultat différent lorsqu'il est appelé par la version Android Studio. La solution consiste à utiliser le chemin relatif au répertoire du projet, qui est retourné avecgradle.startParameter.getProjectDir()
. Voir également mon commentaire dans l'essentiel lié de Paour.J'ai écrit un article de blog avec un exemple de projet Github qui aborde ce problème (et d'autres problèmes similaires) d'une manière légèrement différente de celle de Cyril.
http://brad-android.blogspot.com/2013/08/android-gradle-building-unique-build.html
la source
Malheureusement, la version actuelle (0.4.1) du plugin Android ne semble pas fournir une bonne solution pour cela. Je ne l' ai pas eu le temps d'essayer encore, mais une solution possible à ce problème serait d'utiliser une ressource de chaîne
@string/provider_authority
, et l' utilisation que dans le manifeste:android:authority="@string/provider_authority"
. Vous avez alors unres/values/provider.xml
dans le dossier res de chaque type de construction qui devrait remplacer l'autorité, dans votre cas, ce seraitsrc/debug/res
J'ai cherché à générer le fichier xml à la volée, mais encore une fois, il ne semble pas y avoir de bons hooks pour cela dans la version actuelle du plugin. Je recommanderais cependant de faire une demande de fonctionnalité, je peux imaginer que plus de personnes rencontreront ce même problème.
la source
La réponse dans ce post fonctionne pour moi.
http://www.kevinrschultz.com/blog/2014/03/23/using-android-content-providers-with-multiple-package-names/
J'utilise 3 saveurs différentes, je crée donc 3 manifestes avec un fournisseur de contenu dans chaque saveur, comme l'a dit kevinrschultz:
Votre manifeste principal n'inclut pas les fournisseurs:
Et votre manifeste dans chaque saveur, y compris le fournisseur.
Libre:
Payé:
Autre:
la source
Pourquoi ne pas simplement ajouter ceci?
la source
Ma solution consiste à utiliser le remplacement d'espace réservé dans
AndroidManifest.xml
. Il gère également lespackageNameSuffix
attributs afin que vous puissiez avoirdebug
etrelease
ainsi que toute autre version personnalisée sur le même appareil.Je l'ai sur un
gist
aussi si vous voulez voir si cela évolue plus tard.J'ai trouvé une approche plus élégante que les multiples ressources et les approches d'analyse XML.
la source