0

I'm in a weird problem here.

Here's the part of the gradle script that actually needs fixing

def getVersion() {

def Calendar cal = Calendar.getInstance();
//def SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss");
def SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
def int releaseNumberOfTheDay = 1;
def char versionLtr = ext.vLetter; //line 136, the error line

def StringBuilder sb = new StringBuilder();
//sb.append("RC4 ");
sb.append("2.1");
sb.append(" (");
sb.append(dateFormat.format(cal.getTimeInMillis()));
//sb.append(versionLtr);
sb.append(releaseNumberOfTheDay);
sb.append(")");
//sb.append("a");
return sb.toString();

}

What I'm trying to do here is assign a version letter based on the used flavor. I have added the vLetter to extensions ext and that one works fine. What I'm really having a problem with is, referencing extension and plain gradle members/fields from within gradle.

I have three flavours, DEV, STAGE and LIVE. and this getVersion() function is referenced by

defaultConfig {
    minSdkVersion 15
    targetSdkVersion 22
    versionCode 50  // hockeyapp
    versionName getVersion()
}

the client wants a letter in the version name so he can tell them apart.

I tried this, an extension member to hold the letter for me:

productFlavors {
    SOAP_DEV_ {
        applicationId "com.my.name"
        resValue "string", fbMeta, "DEV_"
        ext.fbMeta = 'DEV_'
        ext.vLetter = 'D'
    }
    SOAP_STAGE_ {
        applicationId "com.my.name"
        resValue 'string', fbMeta, "STAGE_"
        ext.fbMeta = 'STAGE_'
        ext.vLetter = 'S'
    }
    SOAP_LIVE_ {
        applicationId "de.real.name"
        resValue 'string', fbMeta, "LIVE_"
        ext.fbMeta = 'LIVE_'
        ext.vLetter = 'L'
    }
}

But the letter is invisible in the getVersion() declaration. It's as if that function is compiled (or ran?) before the rest of the file, as the error I'm getting is

Error:(136, 0) Cannot get property 'vLetter' on extra properties extension as it does not exist

Soo... please guys (and gals ofc), how do I fix this? I really need to get that letter into the version number somehow.

EDIT: The problem is actually this, no task actually start running. So I'm not sure if the doFirst trick will help me. But i'm open for suggestions. It really doesn't even have to be in the extensions, I just thought of that first. If there is a way for me to "pass" variables from gradle code to the getVersion() function, I'm fine with that. I'm using the ext.vLetter here as a carrier really. I don't need it visible in java or at runtime.

10:29:47 AM Gradle sync started

10:29:54 AM Gradle sync failed: Cannot get property 'vLetter' on extra properties extension as it does not exist Consult IDE log for more details (Help | Show Log)

Shark
  • 6,513
  • 3
  • 28
  • 50
  • First: you forgot the " at the and of your package name in SOAP_STAGE_ {...} Second: Did you tried project.ext.vLetter ? – Hillkorn Apr 19 '16 at 15:54
  • 1) You're right, i made a typo, it worked fine for months, the `versionLetter` is a today's change. I didn't upload my whole build.gradle for a reason. 2) Yes I did, same thing. Then I read [this](https://docs.gradle.org/current/userguide/writing_build_scripts.html) and [this](https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html) and a few other links before deciding to ask here. I'm planning on assigning some bounty on this question for popularity, so even if you do answer it before the 2 day limit is out, i'll honor you and award you bounty in 2 days. – Shark Apr 19 '16 at 16:11
  • Your getVersion() function is declared in the build.gradle file? – Hillkorn Apr 19 '16 at 16:24
  • Yes. I also tried `dev versionLetter` and changing it in the `buildConfig` / `productFlavors` part, but the problem is - I can't access the `ext` extenson in the `getVersion()` function because it somehow doesn't exist yet. it exists only after the gradle pass (like BuildConfig class/file) – Shark Apr 19 '16 at 16:25
  • Try project.ext.vLetter = 'S' – Hillkorn Apr 19 '16 at 16:31
  • Changing `ext.vLetter` to `project.ext.vLetter` doesn't change anything, it's still not visible and non-existant in the `getVersion()` function. I have tried all that before posting this question, the error message is the same, can we please focus on **solving** the actual problem now? Which is "reading the variable set in any of those steps in my `getVersion()` function" – Shark Apr 20 '16 at 07:23
  • As i reproduced the error it got fixed by this. But i think it can't be really solved in the way you want. Cause on configuration time the task that will run your flavour config runs afterwards and you want it's changes for getVersion to configuration time. The only idea i would have at the moment is to try an doFirst atached to the task and set the version inside that closure. Then your flavour should be available cause it's executed to runtime. – Hillkorn Apr 20 '16 at 08:42
  • How do I attach the `doFirst()` to the task, since I'm using Android Studio? Sorry for doubting your solution, but you're right - I was also thinking it can't be solved in the way I want, and that's why I asked here. But I do need to put the build flavor letter in the version name. I'd like to automate it if possible, rather than keeping it as "change the hardcoded letter manually then run the build". – Shark Apr 20 '16 at 09:02
  • 1
    you need to know the taskname and should then be able to write something like taskname.doFirst( { project.defaultConfig.versionName getVersion() }) But it depends on how the plugin that uses the defaultConfig extension works. If it configures it's tasks with afterEvaluate it won't affect them because that is called after configurationtime. Then you could check if the properties in the tasks are directly assignable and set them in your doFirst. – Hillkorn Apr 21 '16 at 07:56
  • Thanks, I see that they have a similar example on [developer.android website](http://developer.android.com/tools/building/plugin-for-gradle.html) but no mention of task properties... I guess I'll have to look into that. – Shark Apr 21 '16 at 08:01
  • I found [this question](http://stackoverflow.com/questions/18532415/execute-task-before-android-gradle-build) and perhaps it can be helpful. Should I make a new task, e.g. `calculateVersionName` and make the build task depend on it? Or simply attach that task to `build.doFirst` ? Can it be done without a new task perhaps? – Shark Apr 21 '16 at 08:20

1 Answers1

1

Sorry, didn't see that it's for android.

should do the trick or?

def getVersion(versionLtr) {

  def Calendar cal = Calendar.getInstance();
  //def SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss");
  def SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
  def int releaseNumberOfTheDay = 1;
  //def char versionLtr = ext.vLetter; //line 136, the error line

  def StringBuilder sb = new StringBuilder();
  //sb.append("RC4 ");
  sb.append("2.1");
  sb.append(" (");
  sb.append(dateFormat.format(cal.getTimeInMillis()));
  //sb.append(versionLtr);
  sb.append(releaseNumberOfTheDay);
  sb.append(")");
  //sb.append("a");
  return sb.toString();

}

productFlavors {
  SOAP_DEV_ {
      applicationId "com.my.name"
      resValue "string", fbMeta, "DEV_"
      ext.fbMeta = 'DEV_'
      versionName = getVersion('D')
  }
  SOAP_STAGE_ {
      applicationId "com.my.name"
      resValue 'string', fbMeta, "STAGE_"
      ext.fbMeta = 'STAGE_'
      versionName = getVersion('S')
  }
  SOAP_LIVE_ {
      applicationId "de.real.name"
      resValue 'string', fbMeta, "LIVE_"
      ext.fbMeta = 'LIVE_'
      versionName = getVersion('L')
  }
}

A product flavour has all options like that the defaultConfig has

Hillkorn
  • 633
  • 4
  • 12