如何在AndroidManifest.xml文件中访问BuildConfig值?


137

是否可以从AndroidManifest.xml访问BuildConfig值?

在我的build.gradle文件中,我有:

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 在我的gradle.properties文件中定义:

# Facebook identifier (app ID)
FACEBOOK_APP_ID=XXXXXXXXXX

要在我的应用程序中使用Facebook connect,我必须将此行添加到我的AndroidManifest.xml中:

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

我想用gradle中定义@string/applicationId的BuildConfig字段FACEBOOK_APP_ID代替,像这样:

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

使用BuildConfig可以吗?如果没有,我该如何实现?

Answers:


190

更换

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

然后重建您的项目(Android Studio->构建->重建项目)。

在项目构建期间,这两个命令都产生生成的值-第一种情况由Java常量组成,第二种情况由Android资源组成-但是第二种方法将生成string可使用@string/FACEBOOK_APP_ID语法访问的资源值。这意味着它既可以在清单中也可以在代码中使用。


1
这是我正在使用的确切代码,但我遇到了一个问题:由于某些原因,Facebook SDK将字符串读取为整数,然后抛出ClassCastException,因为无法将Integer强制转换为String。有人遇到过这个问题吗?
WKS 2015年

@WKS如果查看生成的资源文件,资源类型是否与您期望的(字符串)匹配?
2015年

它是字符串:<item name="facebook_app_id" type="string">15233522...</item>
WKS

13
确保您编写的是resValue“ string”而非NOT resValue“ String”
keybee

1
如果要使用布尔值,请确保键入resValue“ bool”而不是“ boolean”-> tanelikorri.com/tutorial/android/set-variables-in-build-gradle
reavcn

85

从AndroidManifest.xml访问Gradle Build Config值的另一种方法是通过类似这样的占位符:

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

然后在您的清单中:

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

在此处查看更多详细信息:https : //developer.android.com/studio/build/manifest-build-variables.html

(仅用于参考的旧链接:http : //tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger


2
这是一个很好的解决方案。
BinaryShrub

2
是的,这是仅用于清单的字符串注入的好方法!
stkent '16

2
您如何从Java中的manifestPlaceholders获取值?这对于在Java代码和清单中使用的常量很有用。
路易CAD

@LouisCAD我想您可以尝试在构建文件中定义一个变量,然后使用它来定义占位符和(另外)BuildConfig字段,以便可以在代码中使用它。
GregoryK '16

1
@LouisCAD我没有尝试过,但是您可以尝试以下操作:var placeholder ='您的占位符'(换行)buildConfigField“ String”,“ PLACEHOLDER_NAME”,占位符(换行)manifestPlaceholders = [placeholderName:placholder](新线)会很高兴知道它是否适合你
GregoryK

40

注意:使用resValue该值时,字符串资源文件可能会意外覆盖该值(例如,另一种语言)

要获得可以在清单和Java代码中使用的真实常量值,请同时使用manifestPlaceholdersbuildConfigField:例如

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

        addConstant("FACEBOOK_APP_ID", "xxxxx")
    }

在清单文件中访问:

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

从Java:

BuildConfig.FACEBOOK_APP_ID

如果常量值必须是特定于buildType的,则addConstant需要调整助手(以使用常规闭包语义),例如,

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")
    }

1
它不起作用,它从清单中显示无效的应用程序ID,但是从Java设置后它起作用了
Brajendra Pandey

我认为如果您尝试添加多个常量,这将行不通!
格雷格·恩尼斯

1
@GregEnnis还有更多的常量对我也可以:例如,我只打了addConstant()两次(constantNames当然不同)。你得到什么错误?
TmTron

1
@TmTron不会出错,但是每次调用它时都重新分配整个'manifestPlaceholders'数组,只存储最后使用的值。
格雷格·恩尼斯

@GregEnnis,你绝对是严厉的!我的测试项目中有不同的代码。我已经更新了我的答案:我们只需要使用这样的+=运算符manifestPlaceholders += [...]
TmTron

6

如下例所示,访问清单中的build.gradle属性:

例如,在build.gradle中有一个属性“ applicationId”,并且您想在AndroidManifest中访问它:

在此处输入图片说明

在AndroidManifest中访问“ applicationId”:

<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>

同样,我们可以为其他常量创建字符串资源,并在代码文件中访问它们,就像这样简单:

context.getString(R.string.GCM_SENDER_ID);

我可以在.properties文件中定义facebookAppId:“ anotherId ...”,以保存我的商店密码和所有密码。然后,我访问那些manifestplaceholders中的内容,这些内容将在AndroidManifest.xml中间接访问。我可以这样做吗?
阿曼·维尔玛

3

@stkent很好,但是忘了补充一下,之后需要重建项目

更换

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

然后

Android Studio -> Build -> Rebuild Project

这将允许android生成可通过访问的字符串资源

R.string.FACEBOOK_APP_ID

无法获取ProductFlavor_ ...的未知属性'FACEBOOK_APP_ID'–
f.trajkovski

2

另一个选择:使用其他字符串资源文件替换所有与Flavor相关的值:

步骤1:在“ src”文件夹中创建一个新文件夹,其名称为您的名字,在我的情况下为“ stage”

步骤2:为所有依赖于风味的文件创建资源文件,例如:

在此处输入图片说明

步骤3:我还使用了不同的图标,因此您也会看到mipmap文件夹。对于此问题,仅“ strings.xml”很重要。现在,您可以覆盖所有重要的字符串资源。您只需要包括要覆盖的内容,所有其他内容都将在主“ strings.xml”中使用,它将在Android Studio中显示,如下所示:

在此处输入图片说明

步骤4:在项目中使用字符串资源并放松:

在此处输入图片说明


一个很好的选择,特别是如果您有许多其他字符串,则需要设置每个变量。
2015年

我可以在.properties文件中定义facebookAppId:“ anotherId ...”,以保存我的商店密码和所有密码。然后,我访问那些manifestplaceholders中的内容,这些内容将在AndroidManifest.xml中间接访问。我可以这样做吗?
阿曼·维尔玛

0

您可以使用如下的long值

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.