如何在Android应用程序中以编程方式显示当前的Git分支?

6
我希望在我的Android应用程序的“关于”对话框中显示GIT仓库的当前哈希/分支引用。我可以手动复制它,但通过编程实现更有趣。
我的应用程序有一个库,所以我的活动和应用程序继承自我的库类。因此,我考虑向我的库应用程序类添加一个方法[getGitHash()]。我可以通过读取.git/HEAD来引用当前分支,在Eclipse项目下的res/raw文件中虚拟引用(请参见这里了解如何完成)。我的项目现在具有R.raw.HEAD资源。
但是,现在库无法引用R.raw.HEAD,因此我无法在库中实现该方法。库中的方法应该像这样:
public static String getGitHash(int nDigits) {
    
    String hash = "";
    SB_ResourceReader.LoadRAWFile(R.raw.HEAD,SB_Application.getContext());
    return hash;
}

LoadRAWFile()是一个静态方法,用于读取原始文件内容,而SB_Application.getContext()是另一个静态方法,用于检索应用程序上下文。

这个库是否有可能“信任”将会有某个资源存在,尽管在编译时无法访问它?


虽然我没有尝试过,在ICS中引入的新开发工具中,库项目有所不同。通过创建存根文件,可能可以覆盖内容,因为R中变量的值不再是final。在与Android应用程序项目的最终编译中,它应该变成final。虽然我没有尝试过,但尽管这可能绕过编译步骤,但aapt可能无法一致地打包正确的内容。 - Greg Giacovelli
好的,谢谢!听起来是需要学习的东西,但我正在为这个项目使用2.2版本,不知道工具与ICS实体有多少耦合。 - Dani bISHOP
5个回答

9
更容易地(无需任何插件),您可以通过在app.gradle中设置一个新的资源来实现,如下所示:
android {
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1"
        resValue "string", "gitBranch", gitBranch()
    }
    buildTypes {...}
}


def gitBranch() {
    def branch = ""
    def proc = "git rev-parse --abbrev-ref HEAD".execute()
    proc.in.eachLine { line -> branch = line }
    proc.err.eachLine { line -> println line }
    proc.waitFor()
    branch
}

这样你就可以访问到一个新的字符串资源

getString(R.string.gitBranch)

1
@CaptainCrunch,所展示的代码既不是Kotlin也不是Java(除了最后的getString,但OP的意思是针对Android的...) - Hugo Gresse

4
build.gradle的末尾编写复用函数以执行一些命令。
static def getExecute(command) {
  def result = ""
  def proc = command.execute()
  proc.in.eachLine { line -> result = line }
  proc.err.eachLine { line -> println line }
  proc.waitFor()
  return result 
}

那么你有两个选项:

  • 1: buildConfig

     buildConfigField "String", "BUILD_TIME", "\"${getExecute("git rev-parse --abbrev-ref HEAD")}\""
     buildConfigField "String", "GIT_BRANCH", "\"${getExecute("git rev-parse --abbrev-ref HEAD")}\""
     buildConfigField "String", "GIT_COMMIT", "\"${getExecute("git rev-parse --short HEAD")}\""
     buildConfigField "String", "GIT_COMMIT_NAME", "\"${getExecute("git show-branch --no-name HEAD")}\""
     buildConfigField "String", "GIT_LAST_COMMIT_TIME", "\"${getExecute(" git log -1 --format=%cd")}\""
     buildConfigField "String", "GIT_UESRNAME", "\"${getExecute("git config user.name")}\""
     buildConfigField "String", "GIT_EMAIL", "\"${getExecute("git config user.email")}\""
    

    and call them like this,

    private fun getGitInfo() :String {
      var gitInfo = ""
    
      gitInfo += "build time: " + BuildConfig.BUILD_TIME + "\n"
      gitInfo += "branch: " + BuildConfig.GIT_BRANCH + "\n"
      gitInfo += "commit: " + BuildConfig.GIT_COMMIT + "\n"
      gitInfo += "commit name: " + BuildConfig.GIT_COMMIT_NAME + "\n"
      gitInfo += "time: " + BuildConfig.GIT_LAST_COMMIT_TIME + "\n"
      gitInfo += "username: " + BuildConfig.GIT_UESRNAME
      gitInfo += "email: " + BuildConfig.GIT_EMAIL
    
      return gitInfo
    }
    
  • 2: resValue

    resValue "string", "build_time", getExecute("date")
    resValue("string", "git_branch", "\"${getExecute("git rev-parse --abbrev-ref HEAD")}\"")
     resValue("string", "git_commit", "\"${getExecute("git rev-parse --short HEAD")}\"")
     resValue("string", "git_commit_name", "\"${getExecute("git show-branch --no-name HEAD")}\"")
     resValue("string", "git_last_commit_time", "\"${getExecute(" git log -1 --format=%cd")}\"")
     resValue("string", "git_username", "\"${getExecute("git config user.name")}\"")
     resValue("string", "git_email", "\"${getExecute("git config user.email")}\"")
    

    and call them like this,

    private fun getGitInfo() :String {
      var gitInfo = ""
      gitInfo += "build time: " + getString(R.string.build_time) + "\n"
      gitInfo += "branch: " + getString(R.string.git_branch) + "\n"
      gitInfo += "commit: " + getString(R.string.git_commit) + "\n"
      gitInfo += "commit name: " + getString(R.string.git_commit_name) + "\n"
      gitInfo += "time: " + getString(R.string.git_last_commit_time) + "\n"
      gitInfo += "username: " + getString(R.string.git_username) + "\n"
      gitInfo += "email: " + getString(R.string.git_email)
    
      return gitInfo
    }
    

2
如果您正在使用Eclipse,可以尝试以下操作:将.git文件夹添加为源文件夹,并将包含模式写为“HEAD”。这将导致HEAD文件被存储为jar中的资产(而不是Android资源!)。您可以使用getClass().getResourceAsStream("/HEAD")方法访问它:
    try {
        InputStream is = getClass().getResourceAsStream("/HEAD");
        byte buff[] = new byte[256];
        int len = is.read(buff);
        String s = new String(buff, 0, len);
        System.out.println("!!! HEAD: " + s);
    } catch (Exception e) {
        e.printStackTrace();
    }

我会尽快尝试一下。谢谢! - Dani bISHOP

0
感谢 @Hugo Gresse 的回答。如果您正在使用 gradle.kts (Kotlin),则需要进行以下修改:
在您的 build.gradle.kts 文件中:
    android {
        defaultConfig {
            compileSdkVersion(29)
            applicationId = "xxx.xxxxxx.xxxx"
            minSdkVersion(21)
            targetSdkVersion(29)
            versionCode = 3
            versionName = "0.0.3"
            resValue("string", "gitBranch", getGitBranchName())
        }
    }

    // function to read current git branch name
    fun getGitBranchName(): String {
        val process = Runtime.getRuntime().exec("git rev-parse --abbrev-ref HEAD")
        val sb: StringBuilder = StringBuilder()
        while (true) {
            val char = process.inputStream.read()
            if (char == -1) break
            sb.append(char.toChar())
        }
        return sb.toString()
    }

然后您将可以访问名为gitBranch的新字符串资源:

getString(R.string.gitBranch)

0

因此,实现这一点的方法是在您的ant构建文件中编写脚本。您应该查看各种ant文件任务。我认为在您的情况下,ReplaceRegEx正是您所需要的。在您想要放置当前git分支的文件中放置某种唯一字符串,运行一个命令来获取当前git分支,并用该命令的输出替换唯一字符串。


感谢@kurtis-nusbaum!我看到了一些关于ant任务的东西,但我甚至没有去查看它。现在我有了一个完美的借口。基本上你所说的是在编译之前进行标签替换。尽快我会试一下。 - Dani bISHOP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接