Gradle에서 변수를 선언하여 Java에서 사용할 수 있습니까?


417

Java에서 사용할 수있는 Gradle에서 변수를 선언 할 수 있습니까? 기본적으로 나는 build.gradle에 몇 가지 변수를 선언하고 빌드 할 때 (분명히) 얻고 싶습니다. C / C ++의 전 처리기 매크로처럼 ...

선언의 예는 다음과 같습니다.

android {
    debug {
        A_VAR_RETRIEVABLE_IN_JAVA = 42
    }
    release {
        A_VAR_RETRIEVABLE_IN_JAVA = 42+52
    }
}

그런 식으로 할 수있는 방법이 있습니까?

답변:


796

자바 상수 생성

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


4
아니요,하지만 리소스를 생성 할 수도 있습니다. 나는 그것을 포함하여 내 대답을 업데이트했습니다.
rciovati

2
정말 고마워 내가 발견 한 것은 디버그 및 릴리스 빌드를위한 대체 디렉토리를 지정할 수 있다는 것입니다. 에서 <project>/src/이 파일 만들 경우, debug/res/values/strings.xml다른 파일을 release/res/values/strings.xml, 당신은 디버깅을위한 자원을 설정할 수 있습니다 및 릴리스는 약간 클리너 방식으로 구축뿐만 아니라.
elimirks

6
@rciovati는 android플러그인 없이도 동일한 결과를 얻을 수 있습니까? 즉 apply plugin java? 감사!
Zennichimaro

2
다양한 빌드 플레이버 및 빌드 유형에 대한 상수를 만들려면 어떻게해야합니까?
야콥 에릭손

3
현재 연도로 필드 중 하나를 설정할 수 있으며 선택한 빌드 유형 (릴리스, 디버그 등)에 관계없이 도달 할 수 있습니까?
안드로이드 개발자

102

Android 애플리케이션 (Java 및 XML)에서 Api 앱 키 사용 예

gradle.properties

AppKey="XXXX-XXXX"

build.gradle

buildTypes {
//...
    buildTypes.each {
        it.buildConfigField 'String', 'APP_KEY_1', AppKey
        it.resValue 'string', 'APP_KEY_2', AppKey
    }
}

자바 코드에서의 사용법

Log.d("UserActivity", "onCreate, APP_KEY: " + getString(R.string.APP_KEY_2));

BuildConfig.APP_KEY_1

XML 코드에서의 사용법

<data android:scheme="@string/APP_KEY_2" />

1
추가하면이 변수를 런타임에 전달할 수도 있습니다. 다른 구성으로 테스트를 실행할 때 주로 유용합니다. 사용./gradlew -PAppKey="1234" testdebug
Jaswanth Manigundan

1
각 빌드 유형에 대해 동일한 속성을 선언하기 위해 defaultConfig블록을 사용할 수도 있습니다 . stackoverflow.com/a/51521146/321354
rciovati

XML 부분에 대한 실제 예가 있습니까? Github 리포지토리 또는 Gist. 그것은 나를 위해 작동하지 않습니다, 나는 참조 할 수 없습니다@string/APP_KEY_2
voghDev

32

build.gradle에 설정된 시스템 속성을 사용하는 예제는 Java 응용 프로그램에서 읽습니다 (의견에서 질문에 이어).

기본적으로 테스트 태스크 메소드를 사용하여의 test태스크를 사용하여 런타임시 전달되는 시스템 특성을 설정하십시오.build.gradlesystemProperty

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; stdout을 얻는 속성도 있습니다) 콘솔, 그러나 당신은 알고 있습니다)) :

$ 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..."(btw, test작업 에서만 작동) 을 주석 처리 한 경우 :

example.HelloWorldTest > testEnv FAILED
    org.junit.ComparisonFailure at HelloWorldTest.java:14

완성을 위해 다음은 로그 백 구성 ( 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

이 답변은 허용 된 답변의 의견에 대한 직접적인 응답이므로 원래 질문과 약간 다릅니다.
마이클

2
어떻게 든 version = '0.0.1-SNAPSHOT'Java 코드를 통해 얻을 수 있습니까 ?
Nom1fan

SystemProperty는 gradle 테스트 작업에서만 사용할 수 있습니다 : (. 누구나 라이브러리의 Java 코드에서 gradle 변수 값을 갖는 다른 방법을 알고 있습니까?
Stoycho Andreev

systemProperty실제로 테스트에 대해서만 의미가 있으므로, 그들이 왜 이런 식으로했는지 (감독이 아님) 알지만 동시에 의도하지 않은 것들 (응용 프로그램 DSL과 같은)에 gradle을 사용하려고했습니다. )를 식별 할 수 있습니다. 대안으로, 속성 파일 (또는 구성 서비스 등)에서 속성을로드하는 것이 좋습니다. "테스트"모드가 아닌 경우 "제작"모드이고 응용 프로그램 논리가 필요하기 때문입니다. (어쨌든 그것은 이론이다.)
michael

14

빌드하는 동안 시스템 환경 변수를 통해 대체 가능한 빌드 구성 필드를 작성할 수 있습니다.

폴백은 개발 중에 사용되지만 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.


1
이 답변에 감사드립니다! Android .java 파일에서 환경 변수를 표시하는 방법을 알아 내려고 노력했지만 훌륭하게 작동했습니다!
Wayne Piekarski

부울 변수를 정의하려면 buildConfigField "boolean", "CI_BUILD", "$ {isCi}"또는 buildConfigField "boolean", "CI_BUILD", "Boolean.parseBoolean ("+ ' "'+ isCi + '를 사용해야합니다. " '+") "당신은 보풀 검사 (탈출하려는 경우 stackoverflow.com/questions/29889098/... )
android_dev

5

rciovati의 대답은 완전히 정확합니다. 단지 하나의 tidbit를 추가하여 build.gradle의 기본 구성 부분 내에서 모든 빌드 유형에 대한 변수를 만들 수도 있습니다. 이것은 다음과 같습니다

android {
    defaultConfig {
        buildConfigField "String", "APP_NAME", "\"APP_NAME\""
    }
}

이것은 당신이 통해 액세스 할 수 있습니다

BuildConfig.App_NAME

공통 구성을 원할 경우이 시나리오를 기록하고 싶을뿐입니다.


3

이 코드를 사용하고 있으며 잘 작동합니다.

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

}


수정 한 내용과 그 영향을 지정하여 작업 솔루션을 만들면 좋을 것입니다.
Badgy 2018

2

함수의 문자열 결과를 buildConfigField에 삽입하는 방법

다음은 사람이 읽을 수있는 형식 세트의 빌드 날짜 예입니다.

def getDate() {
    return new SimpleDateFormat("dd MMMM yyyy", new Locale("ru")).format(new Date())
}

def buildDate = getDate()

defaultConfig {
    buildConfigField "String", "BUILD_DATE", "\"$buildDate\""
}

1

나는 사용하고있다

buildTypes.each {
    it.buildConfigField 'String', 'GoogleMapsApiKey', "\"$System.env.GoogleMapsApiKey\""
}

Dennis의 답변을 기반으로 하지만 환경 변수에서 가져옵니다.


0

위의 답변 중 어느 것도 나에게 지침을 제공하지 않았으므로 Groovy Methods에 대해 배우는 데 2 ​​시간을 소비해야했습니다.

프로덕션, 샌드 박스 및 로컬 환경에 맞서고 싶었습니다. 게으 르기 때문에 한 곳에서만 URL을 변경하고 싶었습니다. 다음은 내가 생각해 낸 것입니다.

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

${variable}Groovy Methods에서는 큰 따옴표 만 사용할 수 있으므로 대체 구문 .

    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직접 사용할 수 없었 습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.