Wie kann ich auf einen BuildConfig-Wert in meiner AndroidManifest.xml-Datei zugreifen?

137

Ist es möglich, über AndroidManifest.xml auf einen BuildConfig-Wert zuzugreifen?

In meiner build.gradle-Datei habe ich:

defaultConfig {
    applicationId "com.compagny.product"
    minSdkVersion 16
    targetSdkVersion 21
    versionCode 1
    versionName "1.0"

    // Facebook app id
    buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID
}

FACEBOOK_APP_ID ist in meinen gradle.properties-Dateien definiert:

# Facebook identifier (app ID)
FACEBOOK_APP_ID=XXXXXXXXXX

Um Facebook Connect in meiner App verwenden zu können, muss ich diese Zeile zu meiner AndroidManifest.xml hinzufügen:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/applicationId"/> 

Ich möchte @string/applicationIddurch das in gradle FACEBOOK_APP_IDdefinierte BuildConfig-Feld wie folgt ersetzen :

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="FACEBOOK_APP_ID"/> 

Ist das mit BuildConfig möglich? Wenn nicht, wie kann ich das erreichen?

Anthony
quelle

Antworten:

190

Ersetzen

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

mit

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

Erstellen Sie dann Ihr Projekt neu (Android Studio -> Erstellen -> Projekt neu erstellen).

Die beiden Befehle erzeugen während der Projekterstellung generierte Werte - im ersten Fall bestehend aus Java-Konstanten und im zweiten Fall Android-Ressourcen. Die zweite Methode generiert jedoch einen stringRessourcenwert, auf den über die @string/FACEBOOK_APP_IDSyntax zugegriffen werden kann . Dies bedeutet, dass es sowohl im Manifest als auch im Code verwendet werden kann.

stkent
quelle
1
Dies ist der genaue Code, den ich verwende, aber ich habe ein Problem: Das Facebook SDK liest den String aus irgendeinem Grund als Ganzzahl und löst dann eine ClassCastException aus, da Integer nicht in String umgewandelt werden kann. Hat sich jemand diesem Problem gestellt?
WKS
@WKS Wenn Sie sich die generierte Ressourcendatei ansehen, stimmt der Ressourcentyp mit dem überein, was Sie dort erwarten (Zeichenfolge)?
stkent
es ist Zeichenfolge:<item name="facebook_app_id" type="string">15233522...</item>
WKS
13
Stellen Sie sicher, dass Sie resValue "string" und NICHT resValue "String"
schreiben
1
Wenn Sie einen booleschen Wert verwenden möchten, stellen Sie sicher, dass Sie resValue "bool" anstelle von "boolean" eingeben
reavcn
85

Eine andere Möglichkeit, über Ihre AndroidManifest.xml auf Gradle Build Config-Werte zuzugreifen, sind Platzhalter wie die folgenden:

android {
    defaultConfig {
        manifestPlaceholders = [ facebookAppId:"someId..."]
    }
    productFlavors {
        flavor1 {
        }
        flavor2 {
            manifestPlaceholders = [ facebookAppId:"anotherId..." ]
        }
    }
}

und dann in Ihrem Manifest:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="${facebookAppId}"/> 

Weitere Details finden Sie hier: https://developer.android.com/studio/build/manifest-build-variables.html

(Alter Link nur als Referenz: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger )

GregoryK
quelle
2
Dies ist eine großartige Lösung.
BinaryShrub
2
Ja, dies ist eine nette Methode für die reine String-Injektion nur für Manifeste!
stkent
2
Wie würden Sie einen Wert von manifestPlaceholders in Java erhalten? Dies wäre nützlich für Konstanten, die sowohl im Java-Code als auch im Manifest verwendet werden.
Louis CAD
@LouisCAD Ich nehme an, Sie können versuchen, eine Variable in Ihrer Build-Datei zu definieren und dann Ihren Platzhalter und (zusätzlich) das BuildConfig-Feld zu definieren, damit Sie sie in Ihrem Code verwenden können.
GregoryK
1
@ LouisCAD Das habe ich nicht versucht, aber Sie können Folgendes versuchen: var placeholder = 'Ihr Platzhalter' (neue Zeile) buildConfigField "String", "PLACEHOLDER_NAME", Platzhalter (neue Zeile) manifestPlaceholders = [placeholderName: placholder] (neu line) Würde mich freuen zu wissen, ob es für Sie funktioniert
GregoryK
40

Hinweis: Wenn Sie verwenden resValue den Wert verwenden, kann er versehentlich von der String-Ressourcendatei überschrieben werden (z. B. für eine andere Sprache).

Um einen echten konstanten Wert zu erhalten, den Sie im Manifest und im Java-Code verwenden können, verwenden Sie beide manifestPlaceholdersund buildConfigField: z

android {
    defaultConfig {
        def addConstant = {constantName, constantValue ->
            manifestPlaceholders += [ (constantName):constantValue]
            buildConfigField "String", "${constantName}", "\"${constantValue}\""
        }

        addConstant("FACEBOOK_APP_ID", "xxxxx")
    }

Zugriff in der Manifestdatei:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="${FACEBOOK_APP_ID}"/>

von Java:

BuildConfig.FACEBOOK_APP_ID

Wenn der konstante Wert buildType-spezifisch sein muss, muss der Helfer addConstantoptimiert werden (um mit der Groovy-Closure-Semantik zu arbeiten), z.

buildTypes {
    def addConstantTo = {target, constantName, constantValue ->
        target.manifestPlaceholders += [ (constantName):constantValue]
        target.buildConfigField "String", "${constantName}", "\"${constantValue}\""
    }
    debug {
        addConstantTo(owner,"FACEBOOK_APP_ID", "xxxxx-debug")
    }
    release {
        addConstantTo(owner,"FACEBOOK_APP_ID", "xxxxx-release")
    }
TmTron
quelle
1
Nicht funktioniert es zeigt ungültige App-ID, aus Manifest, aber wenn von Java gesetzt, dann funktioniert es
Brajendra Pandey
Ich denke, das wird nicht funktionieren, wenn Sie versuchen, mehr als eine Konstante hinzuzufügen!
Greg Ennis
1
@GregEnnis Auch mehr Konstanten funktionieren gut für mich: zB rufe ich nur addConstant()zweimal auf ( constantNamesnatürlich anders ). Welchen Fehler bekommen Sie?
TmTron
1
@TmTron Sie erhalten keine Fehlermeldung, weisen jedoch bei jedem Aufruf das gesamte Array 'manifestPlaceholders' neu zu und speichern nur den zuletzt verwendeten Wert.
Greg Ennis
@ GregEnnis du bist absolut richtig! Ich hatte einen anderen Code in meinem Testprojekt. Ich habe meine Antwort bereits aktualisiert: Wir müssen nur den +=Operator wie manifestPlaceholders += [...]
folgt verwenden
6

Greifen Sie wie im folgenden Beispiel auf build.gradle-Eigenschaften in Ihrem Manifest zu:

Zum Beispiel haben Sie eine Eigenschaft "applicationId" in Ihrem build.gradle und möchten darauf in Ihrem AndroidManifest zugreifen:

Geben Sie hier die Bildbeschreibung ein

Zugriff auf "applicationId" in AndroidManifest:

<receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="${applicationId}" />
        </intent-filter>
    </receiver>

Ebenso können wir Zeichenfolgenressourcen für andere Konstanten erstellen und in Codedateien darauf zugreifen, so einfach wie:

context.getString(R.string.GCM_SENDER_ID);
Vinay
quelle
Kann ich die facebookAppId definieren: "anotherId ..." in der .properties-Datei, in der ich mein Store-Passwort und alles speichern würde. Dann greife ich auf diejenigen in Manifestplatzhaltern zu, auf die indirekt in AndroidManifest.xml zugegriffen wird. Kann ich das machen?
Aman Verma
3

@stkent ist gut, vergisst jedoch hinzuzufügen, dass Sie Ihr Projekt anschließend neu erstellen müssen

Ersetzen

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

mit

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

dann

Android Studio -> Build -> Rebuild Project

Dadurch kann Android die Zeichenfolgenressource generieren, auf die über zugegriffen werden kann

R.string.FACEBOOK_APP_ID
FOO
quelle
Unbekannte Eigenschaft 'FACEBOOK_APP_ID' für ProductFlavor_ ...
f.trajkovski
2

Eine weitere Option: Verwenden Sie eine andere String-Ressourcendatei, um alle geschmacksabhängigen Werte zu ersetzen:

Schritt 1: Erstellen Sie einen neuen Ordner im Ordner "src" mit dem Namen Ihres Geschmacks, in meinem Fall "Bühne"

Schritt 2: Erstellen Sie Ressourcendateien für alle Dateien, die von der Variante abhängig sind, zum Beispiel:

Geben Sie hier die Bildbeschreibung ein

Schritt 3: Ich verwende auch verschiedene Symbole, sodass Sie auch die Mipmap-Ordner sehen. Für diese Löschung ist nur die "strings.xml" wichtig. Jetzt können Sie alle wichtigen Zeichenfolgenressourcen überschreiben. Sie müssen nur diejenigen einschließen, die Sie überschreiben möchten. Alle anderen werden aus der Hauptdatei "strings.xml" verwendet. Sie wird in Android Studio folgendermaßen angezeigt:

Geben Sie hier die Bildbeschreibung ein

Schritt 4: Verwenden Sie die Zeichenfolgenressourcen in Ihrem Projekt und entspannen Sie sich:

Geben Sie hier die Bildbeschreibung ein

Björn Kechel
quelle
Eine gute Alternative, insbesondere wenn Sie viele andere Zeichenfolgen haben, die Sie pro Variante festlegen müssen.
Stkent
Kann ich die facebookAppId definieren: "anotherId ..." in der .properties-Datei, in der ich mein Store-Passwort und alles speichern würde. Dann greife ich auf diejenigen in Manifestplatzhaltern zu, auf die indirekt in AndroidManifest.xml zugegriffen wird. Kann ich das machen?
Aman Verma
0

Sie können den folgenden langen Wert verwenden

buildConfigField 'long', 'FLAVOR_LONG', '11500L'

Keyur Thumar
quelle