【问题标题】:Android Gradle Read App Name from strings.xmlAndroid Gradle 从 strings.xml 读取应用程序名称
【发布时间】:2015-09-16 08:18:54
【问题描述】:

我正在尝试为每个构建变体重命名我的 APK 文件,以包括应用程序名称、版本名称、版本代码和内部版本号(如果存在)。到目前为止,除了应用程序名称之外,我一切正常。

我想使用AndroidManifest.xml 文件用于android:label 的相同值。这来自字符串资源@string/app_name。我已经看到了使用以下方法替换资源值的能力:

resValue "string", "app_name", "Some new value"

但我只想读取这个值并用它来命名我的 APK 文件。

android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        renameApk(variant, output)
    }
}

def renameApk(variant, output) {
    def apkPath = output.outputFile.parent
    def baseName = project.archivesBaseName

    baseName += "-${variant.buildType.name}"

    // add version name and version code
    baseName += "-v${variant.mergedFlavor.versionName}-${variant.mergedFlavor.versionCode}"

    // if built on jenkins ci, add jenkins build number:
    def buildNumber = System.getenv('BUILD_NUMBER')
    if (buildNumber && buildNumber.size() > 0) {
        baseName += "-b${buildNumber}"
    }

    // if the variant will not be zipAligned, specify that
    if (!output.zipAlign) {
        baseName += '-unaligned'
    }

    // set the output file
    output.outputFile = new File(apkPath, "${baseName}.apk");
}

【问题讨论】:

    标签: android groovy gradle build android-gradle-plugin


    【解决方案1】:

    我在 Android 插件文档中没有看到任何用于访问资源的方法,因此您可以使用以下代码通过搜索资源来找到您的应用名称:

    def getAppName() {
        def stringsFile = android.sourceSets.main.res.sourceFiles.find { it.name.equals 'strings.xml' }
        return new XmlParser().parse(stringsFile).string.find { it.@name.equals 'app_name' }.text()
    }
    

    但我完全同意@Samuil Yanovski 的观点,因为这不值得——最好硬编码一个字符串。我不认为它会减慢构建过程,但这只是不必要的。

    【讨论】:

    • 无法使用构建工具 3.2,def stringsFile = android.sourceSets.main.res.sourceFiles.find { it.name.equals 'strings.xml' } 行出现一些错误。
    【解决方案2】:

    我认为这不是一件容易的事。资源解析是在移动设备上完成的,以适应屏幕方向、本地化等。例如,Gradle 构建系统无法知道使用哪个语言环境。如果您坚持从资源中获取值,您可以打开您想要使用的特定 strings.xml 文件,解析 XML 并自己获取值。在我看来,这是一个巨大的矫枉过正,而且会非常缓慢和丑陋。

    应用程序名称不会经常更改,因此我对硬编码感到满意(特别是因为最终用户看不到 apk 文件名,所以即使发生错误,影响也很小)。如果您正在开发一个白标应用程序并且必须支持动态应用程序名称,那么将值提取到 gradle.properties 文件(或您正在使用的其他类型的配置文件)应该是一个更好的选择,而不是使用应用程序的资源.

    【讨论】:

    • 确实适用于白标应用。我打算确保我们的构建输出根据我们正在构建的当前供应商以不同的方式命名。这样我们的 QA 部门就可以根据 APK 名称轻松区分差异。你有使用 gradle.properties 的例子吗?
    • @steji113,你能告诉我你是如何区分不同的标签的——你是在使用单独的 git 分支、产品风味还是其他东西?我将尝试找出一种基于此生成应用名称的好方法。
    • 因此,在引入产品风味之前,我们已经建立了白色标签基础设施。我们基本上编写了一个 python 脚本,它将一些字符串资源替换为 OEM 值,然后运行构建。目前,我们的 Jenkins 构建环境提取最新代码,运行 python OEM 脚本,然后执行 gradle 构建,最后恢复 OEM 脚本所做的更改。既然 gradle 可能会提供一种更简单的方法,我们愿意以不同的方式来做这件事。我们只是不太确定那是什么。
    • @steji113,我将为每个 OEM 创建一个单独的产品风味,并为每个风味分配一个自定义源集。重要的部分是为品牌提供一个单独的资源文件夹(无需覆盖其他源目录)。在此之后,您可以使用默认 res 文件夹来存储所有共享资源并将 OEM 特定值放在自定义目录中。 Gradle 将在构建时合并资源,因此您无需执行任何其他操作。
    • 太棒了,这似乎是让一切正常工作的方法。我会试试看。
    【解决方案3】:

    我已经使用@Yaroslav 的回答 (https://stackoverflow.com/a/37432654/6711554) 创建了方法。

    def getApplicationName() {
      try {
         def stringsFile = file("./src/main/res/values/string.xml")
         return new XmlParser().parse(stringsFile).string.find { it.@name.equals 'your_app_name' }.text()
      }catch(e){
         println(e)
         return "Default App Name"
      }
    }
    

    您可以从任何资源文件中读取 gradle 中的任何字符串。

    【讨论】:

    • 这个怎么用?代码放在哪里?
    猜你喜欢
    • 1970-01-01
    • 2011-08-21
    • 2012-04-06
    • 2016-07-07
    • 2012-02-27
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多