7

I'm looking to dynamically name the APK on every build with a date/time (yyMMddHHmm). I have completed this and gradle builds and names the APK correctly, however Android Studio will not pickup the right name to attempt to push to device.

There is a question on this topic with some good info, confirming the issue and that a manual sync is required before each build. Android Studio uploads sterile APK to device when Gradle has custom logic changing APK names

For the full picture here is my build.gradle

android {
   compileSdkVersion 22
   buildToolsVersion "22.0.1"

   // grab the date/time to use for versionCode and file naming
   def date = new Date();
   def clientBuildDate = date.format('yyMMddHHmm')

   // for all client files, set the APK name
   applicationVariants.all { variant ->
    variant.outputs.each { output ->
        output.outputFile = new File(output.outputFile.parent, "myapp-" + versionName.replace(".","_") + "-" + clientBuildDate + ".apk")
    }
   }
   ....
   defaultConfig{...}
   buildTypes{...}
   compileOptions{...}
   signingConfigs{...}
  }

The above will generate output like:

myapp-1_0_0-1507021343.apk
myapp-1_0_0-1507021501.apk
myapp-1_0_0-1507021722.apk

but Android studio will always try to load the 1st version to a phone because it is out of sync and not aware of the name change after each build.

Are there any suggestion on how to force a sync on each build/run of Android studio? Manually doing a sync before a build is a show stopper, and would require me to just go back to the default APK naming scheme.

Using: AS 1.2.1.1 & 'com.android.tools.build:gradle:1.2.3'

Community
  • 1
  • 1
Ryan Wick
  • 183
  • 1
  • 7
  • Have you tried playing with `archivesBaseName` property? I think AS should recognize the change in APK file name if its defined in the `defaultConfig` block, instead of a script to manually rename the files. See http://stackoverflow.com/a/28992851/937715 for an example. – Sean Barbeau Jul 08 '15 at 21:34
  • @SeanBarbeau thank you for the suggestion. The approach to use `archivesBaseName` in will not work for dynamic naming, in that example the name is built using static strings, so by nature of changing those strings you force a gradle sync which gets AS/gradle aligned, in my case i'm not looking to manually edit the values which are concat'd but have them calculated at build, this is where i run into issues because that approach does not kick off a sync. – Ryan Wick Jul 09 '15 at 02:47
  • Have you tried using `gradle flavors`? I don't know how well they work with dynamic names that change with each new build, but here's a [question](http://stackoverflow.com/questions/23226722/use-different-resources-graphics-and-strings-for-different-application-flavors) I asked in the past on the topic on setup. – craned Jul 16 '15 at 21:36
  • 3
    I have almost the same requirement, but went a slightly different route: Instead of renaming the outputfile, I just added a Copy task on assembleDebug (or whatever compile task you use), which copied and renamed the built apk using the current timestamp. So I did not run into any sync issues, since Android Studio picked up the original apk for pushing on device, and the timestamped apk is created aside (and I have it moved at a different folder, btw.). Maybe this is a solution for you, if your problem is still valid. I can provide a code example if needed. – Steffen Funke Aug 26 '15 at 08:23
  • @SteffenFunke I think that's a really clean solution, if you post it as an answer I can guarantee you one upvote – Xiao Oct 16 '15 at 05:33

1 Answers1

3

Another option would be to have your externally released builds be provided by a CI server (which they should be anyway) and then add the following to your build.gradle

apply plugin: 'com.android.application'
...
def isCIBuild() {
    return System.getenv('CI_BUILD') != null || hasProperty('CI_BUILD');
}
...
android {
...

    if(isCIBuild()){
        def clientBuildDate = new Date().format('yyMMddHHmm')
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = new File(output.outputFile.parent, "myapp-" + versionName.replace(".","_") + "-" + clientBuildDate + ".apk")
            }
        }
    }
...
}

You then can setup the global environment variable CI_BUILD on the CI Server which will trigger the APK rename, yet Android Studio would use an APK named as it normally would be.

If you want to run a local build and have the APK renamed then build via command line and add -PCI_BUILD=true

./gradlew clean assemble -PCI_BUILD=true

Tom Bollwitt
  • 10,849
  • 1
  • 17
  • 11
  • I ran into one issue. Depending on where the hasProperty() call is invoked (I had mine in an ext block), it may not be in the project context and return null. To be perfectly safe, use "project.hasProperty('CI_BUILD')" and it should work anywhere in the script. – Walt Armour Jan 11 '16 at 15:57