有些 Android app 除了顯示版本號碼之外,還會有該版本的 Git commit hash。如果有好幾部測試機做測試的話,可能會在開發時先後在不同的機安裝過不同版本的 app。但就沒有每次都更新版本號碼。加了 commit hash 就容易分辨 app 的實際版本。其實要顯示 commit hash 的做法不太難,不需要每次人手更改的。只需要改一下 appbuild.gradle 就可以了。

import java.util.regex.Pattern

apply plugin: 'com.android.application'

/**
 * Extract Git commit hash of HEAD with number of changed files
 */
def getGitHashVersionName = {
    try {
        def hashOutput = new ByteArrayOutputStream()
        def changeOutput = new ByteArrayOutputStream()
        def gitVersionName
        exec {
            commandLine 'git', 'rev-list', '--max-count=1', 'HEAD'
            standardOutput = hashOutput
        }
        exec {
            commandLine 'git', 'diff-index', '--shortstat', 'HEAD'
            standardOutput = changeOutput
        }
        gitVersionName = hashOutput.toString().trim().substring(0, 7);
        if (!changeOutput.toString().trim().empty) {
            def pattern = Pattern.compile("\\d+");
            def matcher = pattern.matcher(changeOutput.toString().trim())
            if (matcher.find()) {
                gitVersionName += "-" + matcher.group()
            }
        }
        return gitVersionName
    } catch (ignored) {
        return "UNKNOWN";
    }
}

android {
    // Skip the other items...

    buildTypes {
        debug {
            debuggable true
            minifyEnabled false
            signingConfig signingConfigs.debug
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            applicationIdSuffix debug_application_id_suffex
            buildConfigField "String", "GIT_VERSION_NAME", "\"${getGitHashVersionName()}\""
        }
        release {
            minifyEnabled true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField "String", "GIT_VERSION_NAME", "\"${getGitHashVersionName()}\""
        }
    }
}

上面的 getGitHashVersionName function 就是用 git getGitHashVersionNamegit diff-index 取得 commit hash 和未 commit 的檔案數目。如果有未 commit 的檔案的話,commit hash 後面就會補上檔案數目,方便分辨。

buildTypes 內的 buildConfigField 就是為 Gradle 每次 build 都會自動產生的 BuildConfig class 加入一個 public static final 的 field。只需要在 app 的 source code 直接用 BuildConfig.GIT_VERSION_NAME 就能拿到 Git commit hash。