Ich habe Gradle so eingerichtet, dass meiner Debug-App das Paketnamensuffix hinzugefügt wird, damit ich die von mir verwendete Release-Version und die Debug-Version auf einem Telefon haben kann. Ich habe darauf verwiesen: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types
Meine build.gradle-Datei sieht folgendermaßen aus:
...
android
{
...
buildTypes
{
debug
{
packageNameSuffix ".debug"
versionNameSuffix " debug"
}
}
}
Alles funktioniert einwandfrei, bis ich einen ContentProvider in meiner App verwende. Ich bekomme:
Failure [INSTALL_FAILED_CONFLICTING_PROVIDER]
Ich verstehe, dass dies geschieht, weil zwei Apps (Release und Debug) dieselbe ContentProvider-Berechtigung registrieren.
Ich sehe eine Möglichkeit, dies zu lösen. Wenn ich das richtig verstehe, sollten Sie in der Lage sein, verschiedene Dateien anzugeben, die beim Erstellen verwendet werden sollen. Dann sollte ich in der Lage sein, verschiedene Berechtigungen in verschiedene Ressourcendateien einzufügen (und von Manifest die Berechtigung als Zeichenfolgenressource festzulegen) und Gradle anzuweisen, unterschiedliche Ressourcen für die Debug-Erstellung zu verwenden. Ist das möglich? Wenn ja, dann wären alle Hinweise, wie man das erreicht, großartig!
Oder ist es möglich, Manifest mit Gradle direkt zu ändern? Jede andere Lösung zum Ausführen derselben App mit ContentProvider auf einem Gerät ist immer willkommen.
Antworten:
Keine der vorhandenen Antworten befriedigte mich, aber Liberty war nah dran. So mache ich das also. Zunächst arbeite ich im Moment mit:
Mein Ziel ist es, die
Debug
Version zusammen mit derRelease
Version auf demselben Gerät mit demselben auszuführenContentProvider
.In build.gradle Ihres App-Set-Suffixes für Debug-Build:
In AndroidManifest.xml Dateiset
android:authorities
Eigenschaft IhresContentProvider
:In Ihrer Code- Set-
AUTHORITY
Eigenschaft, die überall dort verwendet werden kann, wo sie in Ihrer Implementierung benötigt wird:Tipp: Vorher
BuildConfig.PACKAGE_NAME
Das ist es! Es wird wie ein Zauber wirken. Lesen Sie weiter, wenn Sie SyncAdapter verwenden!
Update für SyncAdapter (14.11.2014)
Ich werde noch einmal mit meinem aktuellen Setup beginnen:
Wenn Sie einige Werte für verschiedene Builds anpassen müssen, können Sie dies grundsätzlich über die Datei build.gradle tun:
BuildConfig.java
Klasse aus darauf zuzugreifenAls Alternative für Ressourcen können Sie separate BuildType- oder Flavour-Verzeichnisse erstellen und darin enthaltene XMLs oder Werte überschreiben. Ich werde es jedoch im folgenden Beispiel nicht verwenden.
Beispiel
In build.gradle Datei fügen Sie die folgende:
Sie sehen Ergebnisse in der BuildConfig.java- Klasse
und in build / generate / res / generate / debug / values / generate.xml
In Ihrer authenticator.xml Ressourcennutzung angegeben in build.gradle Datei
In Ihrem syncadapter.xml die gleiche Ressource wieder verwenden und @ Zeichenfolge / Behörden zu
Tipp: Die automatische Vervollständigung (Strg + Leertaste) funktioniert für diese generierten Ressourcen nicht. Sie müssen sie daher manuell eingeben
quelle
Neuer Tipp für das Android-Build-System: Umbenennen der ContentProvider-Berechtigung
Ich denke, Sie alle haben von dem neuen Android Gradle-basierten Build-System gehört. Seien wir ehrlich, dieses neue Build-System ist im Vergleich zum vorherigen ein großer Fortschritt. Es ist noch nicht endgültig (zum jetzigen Zeitpunkt ist die neueste Version 0.4.2), aber Sie können es bereits in den meisten Ihrer Projekte sicher verwenden.
Ich habe den größten Teil meines Projekts persönlich auf dieses neue Build-System umgestellt und hatte einige Probleme, da in bestimmten Situationen keine Unterstützung vorhanden war. Eine davon ist die Unterstützung für das Umbenennen von ContentProvider-Berechtigungen
Mit dem neuen Android-System können Sie mit verschiedenen Arten Ihrer App umgehen, indem Sie einfach den Paketnamen zum Zeitpunkt der Erstellung ändern. Einer der Hauptvorteile dieser Verbesserung besteht darin, dass Sie jetzt zwei verschiedene Versionen Ihrer App gleichzeitig auf demselben Gerät installieren können. Zum Beispiel:
Mit einer solchen Gradle-Konfiguration können Sie zwei verschiedene APKs zusammenstellen:
• Eine Debug-APK mit dem Paketnamen com.cyrilmottier.android.app.debug. • Eine Release-APK mit dem Paketnamen com.cyrilmottier.android.app
Das einzige Problem dabei ist, dass Sie die beiden APKs nicht gleichzeitig installieren können, wenn beide einen ContentProvider mit denselben Berechtigungen verfügbar machen. Ziemlich logisch müssen wir die Berechtigung abhängig vom aktuellen Build-Typ umbenennen ... aber dies wird vom Gradle-Build-System nicht unterstützt (noch? ... ich bin sicher, dass es bald behoben wird). Also hier ist ein Weg zu gehen:
Zuerst müssen wir die ContentProvider-Deklaration des Android-Manifests des Anbieters in den entsprechenden Build-Typ verschieben. Dazu haben wir einfach:
src / debug / AndroidManifest.xml
src / release / AndroidManifest.xml
Stellen Sie sicher, dass Sie die ContentProvider-Deklaration aus der AndroidManifest.xml in src / main / entfernen, da Gradle nicht weiß, wie ContentProvider mit demselben Namen, aber einer anderen Berechtigung zusammengeführt werden.
Schließlich müssen wir möglicherweise auf die Autorität im Code zugreifen. Dies kann ziemlich einfach mit der BuildConfig-Datei und der buildConfig-Methode durchgeführt werden:
Dank dieser Problemumgehung können Sie BuildConfig.PROVIDER_AUTHORITY in Ihrem ProviderContract verwenden und gleichzeitig zwei verschiedene Versionen Ihrer App installieren.
Ursprünglich auf Google+: https://plus.google.com/u/0/118417777153109946393/posts/EATUmhntaCQ
quelle
Während Cyrils Beispiel hervorragend funktioniert, wenn Sie nur wenige Build-Typen haben, wird es schnell kompliziert, wenn Sie viele Build-Typen und / oder Produktvarianten haben, da Sie viele verschiedene AndroidManifest.xml-Dateien verwalten müssen.
Unser Projekt besteht aus 3 verschiedenen Build-Typen und 6 Varianten mit insgesamt 18 Build-Varianten. Stattdessen haben wir die Unterstützung für ".res-auto" in den ContentProvider-Berechtigungen hinzugefügt, die auf den aktuellen Paketnamen erweitert werden und die Pflege verschiedener AndroidManifest.xml überflüssig machen
Beispielcode finden Sie hier: https://gist.github.com/cmelchior/6988275
quelle
Seit der Plugin-Version 0.8.3 (eigentlich 0.8.1, aber es funktionierte nicht richtig) können Sie Ressourcen in der Build-Datei definieren, sodass dies eine sauberere Lösung sein kann, da Sie weder Zeichenfolgendateien noch zusätzliches Debug / Release erstellen müssen Ordner.
build.gradle
AndroidManifest.xml
quelle
Ich weiß nicht, ob es jemand erwähnt. Nach dem Android Gradle Plugin 0.10+ bietet der Manifest Merger die offizielle Unterstützung für diese Funktion: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger
In AndroidManifest.xml können Sie $ {packageName} wie folgt verwenden:
Und in Ihrem build.gradle können Sie haben:
Das vollständige Beispiel finden Sie hier: https://code.google.com/p/anymemo/source/browse/AndroidManifest.xml#152
und hier: https://code.google.com/p/anymemo/source/browse/build.gradle#41
quelle
Verwenden Sie
${applicationId}
Platzhalter in XML undBuildConfig.APPLICATION_ID
im Code.Sie müssen das Build-Skript erweitern, um Platzhalter in anderen XML-Dateien als dem Manifest zu aktivieren. Sie können ein Quellverzeichnis pro Build-Variante verwenden, um verschiedene Versionen der XML-Dateien bereitzustellen, aber die Wartung wird sehr schnell umständlich.
AndroidManifest.xml
Sie können den Platzhalter applicationId standardmäßig im Manifest verwenden. Erklären Sie Ihren Provider folgendermaßen:
Beachten Sie das
${applicationId}
Bit. Dies wird zur Erstellungszeit durch die tatsächliche applicationId für die Erstellungsvariante ersetzt, die erstellt wird.In Code
Ihr ContentProvider muss die Berechtigungszeichenfolge im Code erstellen. Es kann die BuildConfig-Klasse verwenden.
Beachten Sie das
BuildConfig.APPLICATION_ID
Bit. Es ist eine generierte Klasse mit der tatsächlichen applicationId für die Build-Variante, die erstellt wird.res / xml / files, zB syncadapter.xml, accountauthenticator.xml
Wenn Sie einen Synchronisierungsadapter verwenden möchten, müssen Sie Metadaten für ContentProvider und AccountManager in XML-Dateien im Verzeichnis res / xml / bereitstellen. Der Platzhalter applicationId wird hier nicht unterstützt. Sie können das Build-Skript jedoch selbst erweitern, um es zu hacken.
Beachten Sie auch hier die
${applicationId}
. Dies funktioniert nur, wenn Sie das folgende Gradle-Skript zum Stammverzeichnis Ihres Moduls hinzufügen und es über build.gradle anwenden.build.gradle
Wenden Sie das zusätzliche Build-Skript aus dem Modul build.gradle an. Ein guter Platz ist unter dem Android Gradle Plugin.
build-processApplicationId.gradle
Unten finden Sie eine Arbeitsquelle für ein Build-Skript für res / xml / placeholder. Eine besser dokumentierte Version ist auf github verfügbar . Verbesserungen und Erweiterungen sind willkommen.
Strings.xml
Meiner Meinung nach muss keine Platzhalterunterstützung für Ressourcenzeichenfolgen hinzugefügt werden. Zumindest für den obigen Anwendungsfall wird es nicht benötigt. Sie können das Skript jedoch leicht ändern, um nicht nur Platzhalter im Verzeichnis res / xml /, sondern auch im Verzeichnis res / values / zu ersetzen.
quelle
Ich würde lieber eine Mischung zwischen Cyril und Rciovati bevorzugen. Ich denke ist einfacher, Sie haben nur zwei Modifikationen.
Das
build.gradle
sieht aus wie:Und die
AndroidManifest.xml
:quelle
gradle.build
authentator.xml
sync_adapter.xml
AndroidManifest.xml
Code:
quelle
Basierend auf dem Beispiel von @ChristianMelchior ist hier meine Lösung, die zwei Probleme in den vorherigen Lösungen behebt:
Lösungen, die die Datei values.xml im Build-Verzeichnis ändern, führen zu einer vollständigen Neuerstellung der Ressourcen (einschließlich der Anpassung aller Drawables).
Aus einem unbekannten Grund verarbeiten IntelliJ (und wahrscheinlich Android Studio) die Ressourcen nicht zuverlässig, was dazu führt, dass der Build nicht ersetzte
.res-auto
Anbieterberechtigungen enthältDiese neue Lösung erledigt die Aufgaben auf Gradle-Weise, indem sie eine neue Aufgabe erstellt, und ermöglicht inkrementelle Builds durch Definieren von Eingabe- und Ausgabedateien.
Erstellen Sie eine Datei (in dem Beispiel, in dem ich sie in ein
variants
Verzeichnis gestellt habe), die wie eine Ressourcen-XML-Datei formatiert ist und Zeichenfolgenressourcen enthält. Diese werden in die Ressourcen der App eingefügt, und jedes Auftreten.res-auto
in den Werten wird beispielsweise durch den Paketnamen der Variante ersetzt<string name="search_provider">.res-auto.MySearchProvider</string>
Fügen Sie die
build_extras.gradle
Datei aus diesem Kern zu Ihrem Projekt hinzu und referenzieren Sie sie von der Hauptdateibuild.gradle
aus, indem Sie sieapply from: './build_extras.gradle'
irgendwo über demandroid
Block hinzufügenStellen Sie sicher, dass Sie einen Standardpaketnamen festlegen, indem Sie ihn dem
android.defaultConfig
Block von hinzufügenbuild.gradle
Verweisen Sie in
AndroidManifest.xml
und anderen Konfigurationsdateien (z. B.xml/searchable.xml
für Anbieter mit automatischer Vervollständigung) auf den Anbieter (z. B.@string/search_provider
).Wenn Sie denselben Namen benötigen, können Sie
BuildConfig.PACKAGE_NAME
beispielsweise die Variable verwendenBuildConfig.PACKAGE_NAME + ".MySearchProvider"
https://gist.github.com/paour/9189462
Update: Diese Methode funktioniert nur unter Android 2.2.1 und höher. Für frühere Plattformen siehe diese Antwort , die ihre eigenen Probleme hat, da die neue offensichtliche Fusion an den Rändern immer noch sehr rau ist…
quelle
variants/res-auto-values.xml
relativ zu/Applications/Android Studio.app/bin/
. dh ich bekomme keine FileNotFoundException für/Applications/Android Studio.app/bin/variants/res-auto-values.xml
. Ich laufe auf einem Mac. Dies ist eine großartige Lösung, aber ich würde sie gerne in der IDE für die anderen Mitglieder des Teams zum Laufen bringen.System.getProperty("user.dir")
, was beim Aufrufen durch den Android Studio-Build ein anderes Ergebnis zurückgibt. Die Lösung besteht darin, den Pfad relativ zum Projektverzeichnis zu verwenden, mit dem zurückgegeben wirdgradle.startParameter.getProjectDir()
. Siehe meinen Kommentar auch in Paours verknüpftem Kern.Ich habe einen Blogpost mit einem Github-Beispielprojekt geschrieben, der dieses Problem (und andere ähnliche Probleme) auf eine etwas andere Weise als das von Cyril angeht.
http://brad-android.blogspot.com/2013/08/android-gradle-building-unique-build.html
quelle
Leider scheint die aktuelle Version (0.4.1) des Android-Plugins keine gute Lösung dafür zu bieten. Ich hatte noch keine Zeit, dies zu versuchen, aber eine mögliche Problemumgehung für dieses Problem wäre die Verwendung einer Zeichenfolgenressource
@string/provider_authority
und deren Verwendung im Manifest :android:authority="@string/provider_authority"
. Sie haben dann eineres/values/provider.xml
im res-Ordner jedes Build-Typs einen, der die Berechtigung überschreiben soll. In Ihrem Fall wäre dies der Fallsrc/debug/res
Ich habe versucht, die XML-Datei im laufenden Betrieb zu generieren, aber auch in der aktuellen Version des Plugins scheint es keine guten Hooks dafür zu geben. Ich würde jedoch empfehlen, eine Funktionsanfrage einzureichen. Ich kann mir vorstellen, dass mehr Menschen auf dasselbe Problem stoßen werden.
quelle
Die Antwort in diesem Beitrag funktioniert für mich.
http://www.kevinrschultz.com/blog/2014/03/23/using-android-content-providers-with-multiple-package-names/
Ich benutze 3 verschiedene Geschmacksrichtungen, also erstelle ich 3 Manifest mit Inhaltsanbieter in jeder Geschmacksrichtung, wie Kevinrschultz sagte:
Ihr Hauptmanifest enthält keine Anbieter:
Und Ihr Manifest in jedem Geschmack einschließlich Anbieter.
Frei:
Bezahlt:
Andere:
quelle
Warum nicht einfach hinzufügen?
quelle
Meine Lösung besteht darin, Platzhalterersatz in zu verwenden
AndroidManifest.xml
. Es auch GriffepackageNameSuffix
Attribute , so dass Sie haben könnendebug
undrelease
sowie jede andere benutzerdefinierte auf demselben Gerät baut.Ich habe es auf einem
gist
wenn Sie sehen wollen, ob es sich später entwickelt.Ich fand, dass dies ein eleganterer Ansatz ist als die Ansätze für mehrere Ressourcen und XML-Analyse.
quelle