Android构建gradle - 替换字符串资源值

时间:2016-05-26 14:19:09

标签: android string gradle replace resources

我有一个特殊情况,我需要在使用Jenkins构建时覆盖谷歌地图键字符串变量。我已经设置了这样一个特殊的结构:

  
      
  • 调试      
        
    • RES      
          
      • 值      
            
        • google_maps_api.xml
        •   
      •   
    •   
  •   
  • 主      
        
    • RES      
          
      • 值      
            
        • google_maps_api.xml
        •   
      •   
    •   
  •   

因此,在 res文件中,我放了发布API密钥,在 debug res文件中,我放了调试API密钥(对于我工作的机器) on - 为Android的debug.keystore生成。)

在构建gradle文件中,我有基于Jenkins环境设置的字符串资源的基本逻辑:

String googleMapApiKey = System.env.MAP_API_KEY;
...
android {
    ...
    buildTypes {
        ...
        debug {
             if (null != googleMapApiKey && !googleMapApiKey.equals("null")) {
                resValue "string", "google_maps_key", googleMapApiKey
            }
        }
        ...
    }
    ...
}

xml文件包含:

<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">
    MY_DEBUG_API_KEY
</string>

我知道问题是因为字符串资源的保留标志,但是如果删除那么有可能事情搞砸了并且松散了那个字符串资源。 有没有办法可以替换实际字符串资源的值,而不只是在构建gradle文件中创建一个新的?

我只是认为当我使用Jenkins环境中的值时,解决方案也可以排除该文件,但我不知道它是否适用于android gradle系统。有谁知道这是否可行,更重要的是,如何?

LE

我似乎必须将res文件从文件夹移动到发布文件夹中。因此,我现在有以下结构:

  
      
  • 调试      
        
    • RES      
          
      • 值      
            
        • google_maps_api.xml
        •   
      •   
    •   
  •   
  • 释放      
        
    • RES      
          
      • 值      
            
        • google_maps_api.xml
        •   
      •   
    •   
  •   

目前,它看起来像这样。

LLE: 从上面的方法不起作用,我很快得出结论。似乎仍然使用xml文件中的值,即使我在gradle脚本中声明了相同的内容(至少作为名称)。

1 个答案:

答案 0 :(得分:5)

作为解决方法,我实现了以下逻辑:

  • 我从发布文件夹
  • 中删除了google_maps_api.xml
  • 我创建了一个从local.properties加载属性的自定义方法:

    /**
     * Get Google Map API Key which should be used by google map services.
     * <br/>
     * Note that this key should not be used when an key is available from Jenkins as most probably debug.keystore is
     * different than the one on your machine.
     *
     * @return the value of your local Google Map API Key
     */
    def getLocalGoogleMapApiKey() {
        Properties properties = new Properties()
        properties.load(project.rootProject.file('local.properties').newDataInputStream())
        def localMalKey = properties.getProperty('google.map.apiKey')
        if (localMalKey == null) {
            // Throw an exception if the property wasn't setup for this
            throw new GradleException(
                    "Google Map API Key property not found. Define your debug Google Map API Key [google.map.apiKey] in " +
                            "your local.properties file! E.g.: google.map.apiKey=YOUR_GOOGLE_MAP_API_KEY")
        }
    
        return localMalKey
    }
    
  • 我在 local.properties 文件中添加了以下属性

    google.map.apiKey=MY_API_KEY
    
  • 我在 build.gradle 中添加了以下逻辑:

    ...
    // Google Map API Key - from Jenkins or from local
    String googleMapApiKey = System.env.MAP_API_KEY ?: getLocalGoogleMapApiKey();
    ...
    android {
        ...
        buildTypes {
            ...
            debug {
                /* Create a string resource which will be used in AndroidManifest.xml file (from Jenkins or local)*/
                resValue "string", "google_maps_key", googleMapApiKey
                println(">>>>>>>>> Google Map API Key: " + googleMapApiKey)
            }
            ...
        }
        ...
    }
    

我选择了这个解决方案,原因如下:

  • 每个用户都可以设置自己的API KEY进行调试(local.properties文件不会影响其他开发人员,因为它永远不会进入存储库)
  • Jenkins可以在不影响项目或任何开发人员的情况下随时更改密钥
  • 没有必要改变项目的结构或乱用它的资源
  • 任何人都可以安全地使用该方法,如果有人没有正确设置属性,它会抛出一个很好的错误

我希望这有助于其他有类似问题的人: