Gradleでアプリのバージョン番号を一律に扱う方法

お題

お題としては、何らかのアプリを作成しているとし、このアプリにバージョン番号をつけたいとする。このバージョン番号はビルド時のjarファイルの名前としても使い、アプリ実行時の画面にも表示したいとする。例えば、

  • Gradleのビルドするjarファイルをfoo-1.2.3.jarという名前にしたい
  • アプリが実行された場合に、「Ver. 1.2.3」という文字列をどこかに表示したい

とする。この場合、通常なら例えばVersion.javaに”1.2.3″と書き込み、かつgradleのversion変数にも’1.2.3’と書き込まねばならない。しかし、これはもちろん忘れてしまう可能性もある。どちらか一方を変更するだけで両方に反映されないものか?

Java側に書き込む方法

Java側のVersion.javaにのみ書き込み、それをgradle側で読み出し、gradleのjarビルド時にそれを使うという方法論はもちろんある。しかしこれは、Javaのソースファイルなり、あるいはコンパイル後の.classファイルなりを読み込んでバージョン番号を取得することを意味する。できないことは無いが、かなり面倒だ。

gradle側に書き込む方法

ここではgradle側に書き込む方法を考えてみる。まずは、build.gradleに以下を書く。

version = '1.2.3'

gradle側としては、これをjarファイルの名前を作り出せばよい。問題は、この文字列をJava側のVersion.javaファイルに書き込まなければならないことだが、前項の方法よりもかなり易しい。以下のようにする。

Version.javaのテンプレートを用意する。

Versionクラスのパッケージがfoo.barの場合、以下のファイルをテンプレートとして用意する。

package foo.bar;
public class Version {
  public static String version = "$version";
}

このファイルは、javaソースフォルダに置くのではなく、別のところに置いておく。build.gradleと同じフォルダでよい。

gradle側の操作

そして、gradle側には次のように書く。

※Javaソースフォルダはsrcであるとする。

def VERSION_JAVA_FOLDER = 'src/foo/bar'
def VERSION_JAVA_FILE = VERSION_JAVA_FOLDER + '/Version.java'

task versionSet(type: Copy) { 
  doFirst {
    delete VERSION_JAVA_FILE
  }
  from 'Version.java'
  into VERSION_JAVA_FOLDER
  expand(version: version) 
}

compileJava.dependsOn(['versionSet'])

こうすれば、Javaコンパイルの前にversionSetタスクが実行され、ただしいバージョン番号の設定されたVersion.javaがソース・ファイルツリーに置かれることになる。

jarの作成

jarファイルの作成は次のようにでもすればよい。

task rel(type: Jar, dependsOn:jar) {
  destinationDir = file('.')
  archiveName = 'foo' + '-' + version + '.jar'
  ...