क्या जावा में ग्रैडल में एक चर घोषित करना संभव है?


417

क्या जावा में ग्रैडल में एक चर घोषित करना संभव है? मूल रूप से मैं build.gradle में कुछ var घोषित करना चाहता हूं और फिर इसे (जाहिर है) बिल्ड समय पर प्राप्त करना चाहता हूं। 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 संसाधन उत्पन्न करें

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
नहीं, लेकिन आप संसाधनों को भी उत्पन्न कर सकते हैं। मैंने उस सहित अपना उत्तर अपडेट कर दिया है।
रस्कोवती

2
बहुत अच्छे धन्यवाद। मैंने जो कुछ खोजा है वह अच्छी तरह से है कि आप डिबग और रिलीज़ बिल्ड के लिए वैकल्पिक निर्देशिका निर्दिष्ट कर सकते हैं। में <project>/src/, यदि आप फ़ाइल बनाने debug/res/values/strings.xmlऔर एक अन्य फ़ाइल release/res/values/strings.xml, आप डिबग के लिए संसाधनों सेट कर सकते हैं और रिहाई एक से थोड़ा क्लीनर ढंग से बनाता है के रूप में अच्छी तरह से।
अभिजात वर्ग

6
@rciovati क्या androidप्लगइन के बिना समान हासिल करना संभव है ? बस का उपयोग कर apply plugin java? धन्यवाद!
ज़ेनिचीमारो

2
मैं विभिन्न बिल्ड फ्लेवर और निर्माण प्रकारों के लिए स्थिरांक कैसे बना सकता हूं?
जैकब एरिकसन

3
क्या यह संभव है कि खेतों में से एक को चालू वर्ष के रूप में सेट किया जाए, और इस पर भी कोई फर्क नहीं पड़ता कि किस प्रकार का निर्माण चुना गया है (रिलीज, डिबग, ...)?
एंड्रॉयड डेवलपर

102

एक Android एप्लिकेशन (जावा और एक्सएमएल) में एप ऐप कुंजी के उपयोग का एक उदाहरण

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
जसवंत मणिगुंडन

1
प्रत्येक बिल्ड प्रकार के लिए समान संपत्ति की घोषणा करने के लिए आप defaultConfigब्लॉक का उपयोग कर सकते हैं : stackoverflow.com/a/51521146/321354
rciovati

क्या आपके पास XML भाग का एक कार्यशील उदाहरण है? एक गितुब भंडार या जिस्ट में। यह मेरे लिए काम नहीं कर रहा है, मैं संदर्भ नहीं दे सकता@string/APP_KEY_2
voghDev

32

उदाहरण के लिए, सिस्टम गुणों का उपयोग करके, build.gradle में सेट, जावा एप्लिकेशन से पढ़ा गया (टिप्पणियों में प्रश्न से ऊपर):

मूल रूप से, testकार्य का उपयोग करते हुए build.gradle, टेस्ट टास्क विधि के साथ 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

मैंने पाया है कि मुश्किल हिस्सा वास्तव में ग्रेडल से आउटपुट प्राप्त कर रहा है ... इसलिए, लॉगिंग को यहां (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..." (जो, 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'जावा कोड के माध्यम से प्राप्त कर सकता हूं ?
201 बजे नोमफैन

SystemProperty केवल ग्रेड टेस्ट टेस्ट में उपलब्ध है :( किसी को भी लाइब्रेरी के जावा कोड में
ग्रेडल

systemPropertyवास्तव में केवल परीक्षण के लिए समझ में आता है, इसलिए मैं देखता हूं कि उन्होंने इसे इस तरह क्यों किया (यह कोई निरीक्षण नहीं है), लेकिन साथ ही, मैंने उन चीजों के लिए भी ढाल का उपयोग करने की कोशिश की है जो इसके लिए अभिप्रेत नहीं थीं (जैसे कि एक आवेदन डीएसएल ) इसलिए मैं पहचान सकता हूं। एक विकल्प के रूप में, मैं एक संपत्ति फ़ाइल (या कॉन्फ़िगर सेवा, आदि) से सिर्फ संपत्तियों को लोड करने की सलाह दूंगा, क्योंकि अगर यह "परीक्षण" मोड में नहीं है, तो यह "उत्पादन" मोड है और आवेदन तर्क की आवश्यकता है। (यही सिद्धांत है, वैसे भी।)
माइकल

14

आप निर्माण के दौरान सिस्टम वातावरण चर के माध्यम से निर्माण क्षेत्र को अचूक बना सकते हैं:

फ़ॉलबैक का उपयोग विकास करते समय किया जाता है, लेकिन जब आप जेनकिन्स या किसी अन्य टूल पर बिल्ड चलाते हैं तो आप चर को ओवरराइड कर सकते हैं।

अपने ऐप में 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
इस उत्तर के लिए धन्यवाद! मैं एक एंड्रॉइड .java फ़ाइल के भीतर से दिखाई देने वाला पर्यावरण चर प्राप्त करने का तरीका जानने की कोशिश कर रहा हूं, और यह बहुत अच्छा काम कर रहा है!
वेन पाइकर्स्की

यदि आप बूलियन चर को परिभाषित करना चाहते हैं, तो आपको buildConfigField "बूलियन", "CI_BUILD", "$ {isCi}" या buildConfigField "बूलियन", "CI_BUILD", "Boolean.parseBoolean (" + '' '' '' '' cC +)) का उपयोग करना चाहिए। " '+") "अगर आप फाहा चेक (बचना चाहते stackoverflow.com/questions/29889098/... )
android_dev

5

rciovati का जवाब पूरी तरह से सही है मैं सिर्फ एक और tidbit जोड़ना चाहता था कि आप अपने build.gradle के डिफ़ॉल्ट config हिस्से के भीतर प्रत्येक बिल्ड प्रकार के लिए चर भी बना सकते हैं। यह इस तरह दिखेगा:

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

}


यह अच्छा होगा यदि आप निर्दिष्ट करते हैं कि आपने क्या संशोधित किया है और इसका क्या प्रभाव पड़ा है, जिसके परिणामस्वरूप आपका कार्य समाधान हो सकता है।
बैगी

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


0

उपर्युक्त उत्तरों में से किसी ने भी मुझे कोई दिशानिर्देश नहीं दिया, इसलिए मुझे ग्रूवी विधियों के बारे में जानने में दो घंटे बिताने पड़े।

मैं उत्पादन, सैंडबॉक्स और स्थानीय वातावरण के खिलाफ जाने में सक्षम होना चाहता था। क्योंकि मैं आलसी हूँ, मैं केवल एक ही स्थान पर 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}ग्रूवी विधियों में दोहरे उद्धरण चिह्नों के साथ उपयोग कर सकते हैं ।

    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सीधे संदर्भ का उपयोग नहीं कर सका , जो कि मैं पहले स्थान पर करना चाहता था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.