¿Cómo puedo acceder a un valor BuildConfig en mi archivo AndroidManifest.xml?

137

¿Es posible acceder a un valor BuildConfig desde AndroidManifest.xml?

En mi archivo build.gradle, tengo:

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 se define en mis archivos gradle.properties:

# Facebook identifier (app ID)
FACEBOOK_APP_ID=XXXXXXXXXX

Para usar Facebook connect en mi aplicación, debo agregar esta línea a mi AndroidManifest.xml:

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

Quiero reemplazar @string/applicationIdpor el campo BuildConfig FACEBOOK_APP_IDdefinido en gradle, como este:

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

¿Es eso posible usando BuildConfig? Si no, ¿cómo puedo lograr esto?

Antonio
fuente

Respuestas:

190

Reemplazar

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

con

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

luego reconstruya su proyecto (Android Studio -> Build -> Rebuild Project).

Los dos comandos producen valores generados, que consisten en constantes de Java en el primer caso y recursos de Android en el segundo, durante las compilaciones del proyecto, pero el segundo método generará un stringvalor de recurso al que se puede acceder utilizando la @string/FACEBOOK_APP_IDsintaxis. Esto significa que se puede usar tanto en el manifiesto como en el código.

stkent
fuente
1
Este es el código exacto que estoy usando pero tengo un problema: Facebook SDK lee la cadena como un entero por algún motivo y luego arroja una ClassCastException porque Integer no se puede convertir en String. ¿Alguien ha enfrentado este problema?
WKS
@WKS Si observa el archivo de recursos generados, ¿coincide el tipo de recurso con lo que espera (cadena) allí?
2015
es cadena:<item name="facebook_app_id" type="string">15233522...</item>
WKS
13
asegúrese de escribir resValue "string" y NOT resValue "String"
keybee
1
Si desea utilizar un valor booleano, asegúrese de escribir resValue "bool" en lugar de "boolean" -> tanelikorri.com/tutorial/android/set-variables-in-build-gradle
reavcn
85

Otra forma de acceder a los valores de configuración de Gradle Build desde su AndroidManifest.xml es a través de marcadores de posición como este:

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

y luego en tu manifiesto:

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

Ver más detalles aquí: https://developer.android.com/studio/build/manifest-build-variables.html

(Enlace anterior solo como referencia: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger )

GregoryK
fuente
2
Esta es una gran solución.
BinaryShrub
2
Sí, este es un buen método para la inyección de cadenas de manifiesto solamente.
stkent
2
¿Cómo obtendría un valor de manifestPlaceholders en java? Esto sería útil para las constantes utilizadas tanto en código Java como en manifiesto.
Louis CAD
@LouisCAD Supongo que puede intentar definir una variable en su archivo de compilación, luego usarlo para definir su marcador de posición y (además) el campo BuildConfig, para que pueda usarlo en su código.
GregoryK
1
@LouisCAD No lo intenté, pero puedes probar lo siguiente: var placeholder = 'your placeholder' (nueva línea) buildConfigField "String", "PLACEHOLDER_NAME", placeholder (nueva línea) manifestPlaceholders = [placeholderName: placholder] (new línea)
Estaría
40

nota: cuando usa resValueel valor, el archivo de recursos de cadenas puede anularlo accidentalmente (por ejemplo, para otro idioma)

Para obtener un verdadero valor constante que pueda usar en el manifiesto y en el código java, use ambos manifestPlaceholdersy buildConfigField: por ejemplo

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

        addConstant("FACEBOOK_APP_ID", "xxxxx")
    }

acceso en el archivo de manifiesto:

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

de java:

BuildConfig.FACEBOOK_APP_ID

Si el valor constante debe ser específico de buildType, el asistente addConstantdebe modificarse (para trabajar con una semántica de cierre excelente), por ejemplo,

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
fuente
1
No funciona, muestra una identificación de aplicación no válida, desde el manifiesto, pero cuando se configura desde Java, entonces funciona
Brajendra Pandey
¡Creo que esto no funcionará si intentas agregar más de una constante!
Greg Ennis
1
@GregEnnis También más constantes funcionan bien para mí: por ejemplo, solo llamo addConstant()dos veces (con diferente, constantNamespor supuesto). ¿Qué error obtienes?
TmTron
1
@TmTron no recibe un error, pero reasigna toda la matriz 'manifestPlaceholders' cada vez que se llama, solo almacenando el último valor utilizado.
Greg Ennis
@GregEnnis tienes toda la razón! He tenido un código diferente en mi proyecto de prueba. Ya actualicé mi respuesta: solo necesitamos usar el +=operador de esta maneramanifestPlaceholders += [...]
TmTron
6

Acceda a las propiedades build.gradle en su manifiesto como en el siguiente ejemplo:

Por ejemplo, tiene una propiedad "applicationId" en su build.gradle y desea acceder a ella en su AndroidManifest:

ingrese la descripción de la imagen aquí

Acceda a "applicationId" en 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>

Del mismo modo, podemos crear recursos de cadena para otras constantes y acceder a ellos en archivos de código tan simples como:

context.getString(R.string.GCM_SENDER_ID);
Vinay
fuente
¿Puedo definir el facebookAppId: "anotherId ..." en el archivo .properties donde estaría guardando la contraseña de mi tienda y todo. Luego accedo a aquellos en marcadores de lugar de manifiesto a los que se accedería indirectamente en AndroidManifest.xml. ¿Puedo hacer eso?
Aman Verma
3

@stkent es bueno pero olvida agregar que necesita reconstruir su proyecto después

Reemplazar

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

con

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

luego

Android Studio -> Build -> Rebuild Project

Esto permitirá que Android genere el recurso de cadena accesible a través de

R.string.FACEBOOK_APP_ID
FOO
fuente
No se pudo obtener la propiedad desconocida 'FACEBOOK_APP_ID' para ProductFlavor_ ...
f.trajkovski
2

Otra opción: usar un archivo de recursos de cadena diferente para reemplazar todos los valores dependientes de Flavor:

Paso 1: Crea una nueva carpeta en la carpeta "src" con el nombre de tu sabor, en mi caso, "etapa"

Paso 2: cree archivos de recursos para todos los archivos que dependen del sabor, por ejemplo:

ingrese la descripción de la imagen aquí

Paso 3: También estoy usando diferentes íconos, así que también puedes ver las carpetas de mipmap. Para esta consulta, solo es importante el "strings.xml". Ahora puede sobrescribir todos los recursos de cadena importantes. Solo necesita incluir los que desea anular, todos los demás se utilizarán desde el "strings.xml" principal, se mostrará en Android Studio de esta manera:

ingrese la descripción de la imagen aquí

Paso 4: usa los recursos de cadena en tu proyecto y relájate:

ingrese la descripción de la imagen aquí

Björn Kechel
fuente
Una buena alternativa, especialmente si tiene muchas otras cadenas que necesita establecer por variante.
stkent
¿Puedo definir el facebookAppId: "anotherId ..." en el archivo .properties donde estaría guardando la contraseña de mi tienda y todo. Luego accedo a aquellos en marcadores de lugar de manifiesto a los que se accedería indirectamente en AndroidManifest.xml. ¿Puedo hacer eso?
Aman Verma
0

Puede usar el valor largo como se muestra a continuación

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

Keyur Thumar
fuente