Como acessar um valor BuildConfig no meu arquivo AndroidManifest.xml?

137

É possível acessar um valor BuildConfig no AndroidManifest.xml?

No meu arquivo build.gradle, tenho:

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 é definido nos meus arquivos gradle.properties:

# Facebook identifier (app ID)
FACEBOOK_APP_ID=XXXXXXXXXX

Para usar a conexão do Facebook no meu aplicativo, devo adicionar esta linha ao meu AndroidManifest.xml:

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

Eu quero substituir @string/applicationIdpelo campo BuildConfig FACEBOOK_APP_IDdefinido em gradle, assim:

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

Isso é possível usando o BuildConfig? Se não, como posso conseguir isso?

anthony
fonte

Respostas:

190

Substituir

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

com

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

em seguida, recrie seu projeto (Android Studio -> Build -> Rebuild Project).

Os dois comandos produzem valores gerados - consistindo em constantes Java no primeiro caso e recursos Android no segundo - durante a construção do projeto, mas o segundo método gera um stringvalor de recurso que pode ser acessado usando a @string/FACEBOOK_APP_IDsintaxe. Isso significa que pode ser usado no manifesto e no código.

stkent
fonte
1
Este é o código exato que estou usando, mas estou enfrentando um problema: o SDK do Facebook lê a sequência como um número inteiro por algum motivo e, em seguida, lança uma ClassCastException porque o Número Inteiro não pode ser convertido em String. Alguém já enfrentou esse problema?
WKS
@WKS Se você olhar para o arquivo de recursos gerado, o tipo de recurso corresponde ao que você espera (string) lá?
stkent
é string:<item name="facebook_app_id" type="string">15233522...</item>
WKS
13
certifique-se de escrever resValue "string" e não resValue "String"
keybee
1
Se você deseja usar um valor booleano, certifique-se de digitar resValue "bool" em vez de "boolean" -> tanelikorri.com/tutorial/android/set-variables-in-build-gradle
reavcn
85

Outra maneira de acessar os valores do Gradle Build Config no seu AndroidManifest.xml é através de espaços reservados como este:

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

e depois no seu manifesto:

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

Veja mais detalhes aqui: https://developer.android.com/studio/build/manifest-build-variables.html

(Link antigo apenas para referência: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger )

GregoryK
fonte
2
Esta é uma otima soluçao.
BinaryShrub 29/03
2
Sim, este é um bom método para injeção de cadeia apenas de manifesto!
stkent
2
Como você obteria um valor dos manifestPlaceholders em java? Isso seria útil para constantes usadas no código java e no manifesto.
Louis CAD
@LouisCAD Suponho que você possa tentar definir uma variável em seu arquivo de construção e usá-la para definir seu espaço reservado e (além) o campo BuildConfig, para que você possa usá-la em seu código.
GregoryK
1
@LouisCAD Eu não tentei isso, mas você pode tentar o seguinte: var espaço reservado = 'seu espaço reservado' (nova linha) buildConfigField "String", "PLACEHOLDER_NAME", espaço reservado (nova linha) manifestPlaceholders = [placeholderName: placholder] (new ) Ficaria feliz em saber se ele funciona para você #
GregoryK 13/12/16
40

nota: quando você usa resValueo valor, acidentalmente, pode ser substituído pelo arquivo de recursos de strings (por exemplo, para outro idioma)

Para obter um verdadeiro valor constante que você pode usar no manifesto e no código java, use ambos manifestPlaceholderse buildConfigField:

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

        addConstant("FACEBOOK_APP_ID", "xxxxx")
    }

acesso no arquivo de manifesto:

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

de java:

BuildConfig.FACEBOOK_APP_ID

Se o valor constante precisar ser específico do buildType, o auxiliar addConstantprecisará ser ajustado (para trabalhar com a semântica de fechamento de groovy), por exemplo,

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
fonte
1
Não funcionar ele mostra ID de aplicativo inválido, de manifesto, mas quando conjunto de java então trabalhar
Brajendra Pandey
Eu acho que isso não funcionará se você tentar adicionar mais de uma constante!
Greg Ennis
1
@GregEnnis Também mais constantes funcionam bem para mim: por exemplo, eu ligo apenas addConstant()duas vezes (com diferentes, é constantNamesclaro). Que erro você recebe?
TmTron
1
@TmTron, você não recebe um erro, mas atribui novamente toda a matriz 'manifestPlaceholders' toda vez que é chamada, armazenando apenas o último valor usado.
Greg Ennis
@GregEnnis você está absolutamente certo! Eu tive um código diferente no meu projeto de teste. Eu já atualizei a minha resposta: só precisamos de usar o +=operador como estemanifestPlaceholders += [...]
TmTron
6

Acesse as propriedades build.gradle no seu manifesto, como no exemplo a seguir:

Por exemplo, você tem uma propriedade "applicationId" em seu build.gradle e deseja acessá-la em seu AndroidManifest:

insira a descrição da imagem aqui

Acesse "applicationId" no 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>

Da mesma forma, podemos criar recursos de string para outras constantes e acessá-los em arquivos de código tão simples quanto:

context.getString(R.string.GCM_SENDER_ID);
Vinay
fonte
posso definir o facebookAppId: "anotherId ..." no arquivo .properties onde eu salvaria minha senha de loja e tudo. Então eu acesso aqueles em manifestplaceholders que indiretamente seriam acessados ​​no AndroidManifest.xml. Posso fazer isso?
Aman Verma
3

@stkent é bom, mas esquece de acrescentar que você precisa reconstruir seu projeto posteriormente

Substituir

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

com

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

então

Android Studio -> Build -> Rebuild Project

Isso permitirá que o Android gere o recurso de string acessível via

R.string.FACEBOOK_APP_ID
FOO
fonte
Não foi possível obter a propriedade desconhecida 'FACEBOOK_APP_ID' para ProductFlavor_ ...
f.trajkovski
2

Outra opção: use um arquivo de recurso de sequência diferente para substituir todos os valores dependentes do Flavor:

Etapa 1: crie uma nova pasta na pasta "src" com o nome do seu sabor, no meu caso "estágio"

Etapa 2: Crie arquivos de recursos para todos os arquivos que dependem do sabor, por exemplo:

insira a descrição da imagem aqui

Etapa 3: Também estou usando ícones diferentes, para que você também veja as pastas do mipmap. Para esta opção, apenas o "strings.xml" é importante. Agora você pode substituir todos os recursos importantes da string. Você só precisa incluir os que deseja substituir, todos os outros serão usados ​​a partir do "strings.xml" principal, ele será exibido no Android Studio assim:

insira a descrição da imagem aqui

Etapa 4: use os recursos de sequência no seu projeto e relaxe:

insira a descrição da imagem aqui

Björn Kechel
fonte
Uma boa alternativa, especialmente se você tiver muitas outras strings, precisará definir por variante.
Stkent
posso definir o facebookAppId: "anotherId ..." no arquivo .properties onde eu salvaria minha senha de loja e tudo. Então eu acesso aqueles em manifestplaceholders que indiretamente seriam acessados ​​no AndroidManifest.xml. Posso fazer isso?
Aman Verma
0

Você pode usar um valor longo como abaixo

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

Keyur Thumar
fonte