[英]Is it possible to declare a variable in Gradle usable in Java?
是否可以在 Gradle 中聲明一個可在 Java 中使用的變量? 基本上我想在 build.gradle 中聲明一些變量,然后在構建時(顯然)得到它。 就像 C/C++ 中的預處理器宏...
聲明的一個例子是這樣的......:
android {
debug {
A_VAR_RETRIEVABLE_IN_JAVA = 42
}
release {
A_VAR_RETRIEVABLE_IN_JAVA = 42+52
}
}
有沒有辦法做這樣的事情?
以下是從 Gradle 傳遞值以在 Java 中使用的兩種方法;
android {
buildTypes {
debug {
buildConfigField "int", "FOO", "42"
buildConfigField "String", "FOO_STRING", "\"foo\""
buildConfigField "boolean", "LOG", "true"
}
release {
buildConfigField "int", "FOO", "52"
buildConfigField "String", "FOO_STRING", "\"bar\""
buildConfigField "boolean", "LOG", "false"
}
}
}
您可以使用BuildConfig.FOO
訪問它們
android {
buildTypes {
debug{
resValue "string", "app_name", "My App Name Debug"
}
release {
resValue "string", "app_name", "My App Name"
}
}
}
您可以使用@string/app_name
或R.string.app_name
以通常的方式訪問它們
gradle.properties
AppKey="XXXX-XXXX"
構建.gradle
buildTypes {
//...
buildTypes.each {
it.buildConfigField 'String', 'APP_KEY_1', AppKey
it.resValue 'string', 'APP_KEY_2', AppKey
}
}
java代碼中的用法
Log.d("UserActivity", "onCreate, APP_KEY: " + getString(R.string.APP_KEY_2));
BuildConfig.APP_KEY_1
在 xml 代碼中的使用
<data android:scheme="@string/APP_KEY_2" />
使用系統屬性的示例,在 build.gradle 中設置,從 Java 應用程序讀取(從評論中的問題跟進):
基本上,使用build.gradle
的test
任務,測試任務方法systemProperty
設置在運行時傳遞的系統屬性:
apply plugin: 'java'
group = 'example'
version = '0.0.1-SNAPSHOT'
repositories {
mavenCentral()
// mavenLocal()
// maven { url 'http://localhost/nexus/content/groups/public'; }
}
dependencies {
testCompile 'junit:junit:4.8.2'
compile 'ch.qos.logback:logback-classic:1.1.2'
}
test {
logger.info '==test=='
systemProperty 'MY-VAR1', 'VALUE-TEST'
}
這是示例代碼的其余部分(您可能會推斷出,但無論如何都包含在此處):它獲取系統屬性MY-VAR1
,預計在運行時設置為VALUE-TEST
:
package example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
static final Logger log=LoggerFactory.getLogger(HelloWorld.class);
public static void main(String args[]) {
log.info("entering main...");
final String val = System.getProperty("MY-VAR1", "UNSET (MAIN)");
System.out.println("(main.out) hello, world: " + val);
log.info("main.log) MY-VAR1=" + val);
}
}
測試用例:如果未設置MY-VAR
,則測試應失敗:
package example;
...
public class HelloWorldTest {
static final Logger log=LoggerFactory.getLogger(HelloWorldTest.class);
@Test public void testEnv() {
HelloWorld.main(new String[]{});
final String val = System.getProperty("MY-VAR1", "UNSET (TEST)");
System.out.println("(test.out) var1=" + val);
log.info("(test.log) MY-VAR1=" + val);
assertEquals("env MY-VAR1 set.", "VALUE-TEST", val);
}
}
運行(注意:測試通過):
$ gradle cleanTest test
:cleanTest
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test
BUILD SUCCESSFUL
我發現棘手的部分實際上是從 gradle 獲取輸出......所以,這里配置了日志記錄(slf4j+logback),並且日志文件顯示了結果(或者,運行gradle --info cleanTest test
;有還有將標准輸出發送到控制台的屬性,但是,你知道,為什么):
$ cat app.log
INFO Test worker example.HelloWorld - entering main...
INFO Test worker example.HelloWorld - main.log) MY-VAR1=VALUE-TEST
INFO Test worker example.HelloWorldTest - (test.log) MY-VAR1=VALUE-TEST
如果您注釋掉“ systemProperty...
”(順便說一句,僅適用於test
任務),則:
example.HelloWorldTest > testEnv FAILED
org.junit.ComparisonFailure at HelloWorldTest.java:14
為了完整起見,這里是 logback 配置( src/test/resources/logback-test.xml
):
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>app.log</file>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d %p %t %c - %m%n</pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="FILE"/>
</root>
</configuration>
文件:
build.gradle
src/main/java/example/HelloWorld.java
src/test/java/example/HelloWorldTest.java
src/test/resources/logback-test.xml
您可以在構建期間通過系統環境變量創建可覆蓋的構建配置字段:
開發時使用回退,但您可以在 Jenkins 或其他工具上運行構建時覆蓋該變量。
在您的應用build.gradle 中:
buildTypes {
def serverUrl = '\"' + (System.getenv("SERVER_URL")?: "http://default.fallback.url.com")+'\"'
debug{
buildConfigField "String", "SERVER_URL", serverUrl
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "String", "SERVER_URL", serverUrl
}
}
該變量將作為BuildConfig.SERVER_URL
可用。
rciovati 的回答完全正確,我只是想再添加一個花絮,您還可以在 build.gradle 的默認配置部分中為每種構建類型創建變量。 這看起來像這樣:
android {
defaultConfig {
buildConfigField "String", "APP_NAME", "\"APP_NAME\""
}
}
這將允許您訪問
BuildConfig.App_NAME
如果您想要一個通用配置,也只是想記下這個場景。
我正在使用此代碼並且工作得很好。
def baseUrl = '\"http://patelwala.com/myapi/"'
def googleServerKey = '\"87171841097-opu71rk2ps35ibv96ud57g3ktto6ioio.apps.googleusercontent.com"'
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField 'String', 'BASE_URL', baseUrl
buildConfigField 'String', 'web_client_id', googleServerKey
}
releasedebug {
initWith debug
buildConfigField 'String', 'BASE_URL', baseUrl
buildConfigField 'String', 'web_client_id' ,googleServerKey
}
debug {
buildConfigField 'String', 'BASE_URL', baseUrl
buildConfigField 'String', 'web_client_id', googleServerKey
}
}
}
}
我在用着
buildTypes.each {
it.buildConfigField 'String', 'GoogleMapsApiKey', "\"$System.env.GoogleMapsApiKey\""
}
它基於丹尼斯的回答,但從環境變量中獲取。
如何將函數的字符串結果插入到 buildConfigField 中
以下是人類可讀格式集的構建日期示例:
def getDate() {
return new SimpleDateFormat("dd MMMM yyyy", new Locale("ru")).format(new Date())
}
def buildDate = getDate()
defaultConfig {
buildConfigField "String", "BUILD_DATE", "\"$buildDate\""
}
https://stackoverflow.com/a/17201265/12021422 @rciovati 的回答有效
我花了 30 分鍾試圖找出無法訪問新屬性變量的原因。
以上答案都沒有給我任何指導,所以我不得不花兩個小時學習 Groovy 方法。
我希望能夠對抗生產、沙箱和本地環境。 因為我很懶,所以只想在一個地方改個網址。 這是我想出的:
flavorDimensions 'environment'
productFlavors {
production {
def SERVER_HOST = "evil-company.com"
buildConfigField 'String', 'API_HOST', "\"${SERVER_HOST}\""
buildConfigField 'String', 'API_URL', "\"https://${SERVER_HOST}/api/v1/\""
buildConfigField 'String', 'WEB_URL', "\"https://${SERVER_HOST}/\""
dimension 'environment'
}
rickard {
def LOCAL_HOST = "192.168.1.107"
buildConfigField 'String', 'API_HOST', "\"${LOCAL_HOST}\""
buildConfigField 'String', 'API_URL', "\"https://${LOCAL_HOST}/api/v1/\""
buildConfigField 'String', 'WEB_URL', "\"https://${LOCAL_HOST}/\""
applicationIdSuffix ".dev"
}
}
替代語法,因為您只能在 Groovy 方法中使用帶雙引號的${variable}
。
rickard {
def LOCAL_HOST = "192.168.1.107"
buildConfigField 'String', 'API_HOST', '"' + LOCAL_HOST + '"'
buildConfigField 'String', 'API_URL', '"https://' + LOCAL_HOST + '/api/v1/"'
buildConfigField 'String', 'WEB_URL', '"https://' + LOCAL_HOST + '"'
applicationIdSuffix ".dev"
}
我很難理解的是,需要將字符串聲明為用引號括起來的字符串。 由於這個限制,我不能直接使用引用API_HOST
,這是我首先想做的。
這適用於可在 Java 和 Kotlin 中使用的 Kotlin DSL (build.gradle.kts):
buildTypes {
getByName("debug") {
buildConfigField("Boolean", "isHappy", "true")
buildConfigField("String", "favoriteSong", """"Black Forest"""")
resValue("string", "myName", "Lind")
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.