【问题标题】:Edit an AndroidManifest when compiling to remove API-key编译时编辑 AndroidManifest 以删除 API-key
【发布时间】:2012-12-08 09:05:58
【问题描述】:

我目前正在做一个 Android 项目,并学习如何使用 git。 由于 git 的问题,我被阻止了:我在我的 android-manifest 文件中声明了我的 Google Maps api 密钥:

<meta-data
    android:name="com.google.android.maps.v2.API_KEY"
    android:value="HEREISMYKEY"/>

现在,我想在 github 中推送我的代码,但我无法推送我的 AndroidManifest,因为它包含我的 api 密钥(应该保密)。

我想知道是否有办法在每次推送之前修改它,或者每次编译我的应用程序时修改它?

感谢您的帮助!

【问题讨论】:

    标签: android eclipse git github


    【解决方案1】:

    在您的 res/values 中创建一个新的 *.xml 文件(称其为 api-keys.xml 或类似名称)。

    更改清单以指向此字符串:

     <meta-data
        android:name="com.google.android.maps.v2.API_KEY"
        android:value="@string/GoogleMapsKey"/>
    

    当您第一次向公众推送您的更改时,请输入一个虚拟密钥。

    然后使用您的真实 API 密钥编辑文件。

    然后将该文件添加到您的 .gitignore 文件中,这样它就不会再次被推送。

    【讨论】:

    • 您还应该在创建 gitignore 文件之前取消跟踪您的 api-keys.xml 文件。否则,您仍然会推送更改。 link
    • 仅供参考,出于某种原因,IntelliJIdea 不想要 api-keys.xml,所以请改用 api_keys.xml。
    • 这是一个很好的答案。出于某种原因,我认为所有字符串资源 xml 文件都需要按约定命名为值。现在我了解到,我可以在 Android 上做与其他项目相同的事情!
    • 我首选的处理修改文件的解决方案是使用命令:git update-index --assumed-unchanged api-key.xml。
    • 这很好,但是没有密钥文件可以构建项目吗?是不是违反了版本控制的“基本”规则——只有可以编译的代码才应该被版本化?
    【解决方案2】:

    我建议使用 Gradle 为不同的构建类型动态加载 API 密钥,如果没有找到则加载一个虚拟密钥。这样做的好处是 CI 也可以在不需要真正的 API 密钥的情况下构建您的应用程序,但是您团队中的每个新开发人员都必须设置 API 密钥。

    1. 在您的根gradle 文件夹中创建一个属性文件google-maps-api.properties通过将这一行 gradle/google-maps-api.properties 添加到您的 .gitignore 来忽略该文件并放入以下 ​​2 个属性:
    googleMapsApiKeyDebug=[YOUR_DEBUG_GOOGLE_MAPS_API_KEY_HERE]
    googleMapsApiKeyRelease=[YOUR_RELEASE_GOOGLE_MAPS_API_KEY_HERE]
    
    1. 接下来在您的根gradle 文件夹中创建以下google-maps-api-config.gradle 文件。此 Gradle 文件将加载您在第 1 步中创建的属性文件。
    ext {
        googleMapsApiConfig = new GoogleMapsApiConfigLogic(project)
    }
    
    /*
    Before you run your application, you need a Google Maps API key.
    
    Using these values:
    
    Package name:
    at.ict4d.covid19map
    
    SHA-1 certificate fingerprint:
    DE:4A:F0:B1:F5:F4:00:88:B6:E0:03:3E:31:1F:11:88:3F:43:0D:8B
    
    Follow the directions here:
    https://developers.google.com/maps/documentation/android/start#get-key
    
    Once you have your key (it starts with "AIza") create a file with the name "google-maps-api.properties" in the gradle folder:
    gradle/google-maps-api.properties
    
    Put in 2 properties:
    googleMapsApiKeyDebug:[THE KEY YOU JUST CREATED]
    googleMapsApiKeyRelease:[YOUR RELEASE GOOGLE MAPS KEY] (if you are just developing and not planning to publish then fill in "YOUR_RELEASE_KEY_HERE")
    
    "gradle/google-maps-api.properties" example:
    googleMapsApiKeyDebug=AIzaFJKLJKsdLFDDsjlkdfDFJKLdjkf
    googleMapsApiKeyRelease=YOUR_RELEASE_KEY_HERE
    
    Sync your project and build.
    */
    
    class GoogleMapsApiConfigLogic {
    
        public final keyGoogleMapsApiKeyDebug = "googleMapsApiKeyDebug"
        public final keyGoogleMapsApiKeyRelease = "googleMapsApiKeyRelease"
        private final configGoogleMapsApiPropsFileName = "gradle/google-maps-api.properties"
    
        public final props
    
        private final project
    
        GoogleMapsApiConfigLogic(project) {
            this.project = project
            this.props = loadGoogleMapsApiProperties()
        }
    
        def loadGoogleMapsApiProperties() {
    
            Properties propertiesObj
    
            if ((propertiesObj = loadFromProperties("$project.rootDir/$configGoogleMapsApiPropsFileName")) != null) {
                project.logger.quiet("google-maps-api-config: use local properties file for Google Maps API")
                return propertiesObj
            } else {
                propertiesObj = new Properties()
                propertiesObj.put(keyGoogleMapsApiKeyDebug, "YOUR_KEY_HERE")
                propertiesObj.put(keyGoogleMapsApiKeyRelease, "YOUR_KEY_HERE")
            }
    
            project.logger.quiet("google-maps-api-config: no API key found for Google Maps")
            return propertiesObj
        }
    
        def loadFromProperties(fileName) {
            Properties props = new Properties()
            File propFile = new File(fileName)
    
            if (propFile.exists()) {
                props.load(new FileInputStream(propFile))
                if (props.get(keyGoogleMapsApiKeyDebug) != null &&
                        props.get(keyGoogleMapsApiKeyRelease) != null) {
                    project.logger.quiet("google-maps-api-config: use $fileName for Google Maps API")
                    return props
                }
            } else {
                project.logger.quiet("google-maps-api-config: $propFile does not exist for Google Maps API")
            }
            return null
        }
    }
    
    1. 将以下内容添加到您的 app/build.gradle 文件中:
    plugins {
        id 'com.android.application'
        id 'kotlin-android'
        id 'kotlin-android-extensions'
        // ...
    }
    
    apply from: "$rootDir/gradle/google-maps-api-config.gradle" // handles Google Maps API key
    
    android {
    
       // ...
    
       buildTypes {
            release {
    
                // other config
    
                resValue "string", "google_maps_key", "\"${googleMapsApiConfig.props.getProperty(googleMapsApiConfig.keyGoogleMapsApiKeyRelease)}\""
            }
    
            debug {
                // other config
    
                resValue "string", "google_maps_key", "\"${googleMapsApiConfig.props.getProperty(googleMapsApiConfig.keyGoogleMapsApiKeyDebug)}\""
            }
        }
    

    这将创建一个字符串资源,其中包含密钥 google_maps_key 和您的 API 密钥的值。您可以删除任何其他 API 密钥引用,例如Android Studio 生成以下文件:app/src/debug/res/values/google_maps_api.xmlapp/src/release/res/values/google_maps_api.xml - 您可以删除它们。

    1. 将 Google Maps API 密钥添加到您的清单中:
    <application>
    
            <meta-data
                android:name="com.google.android.geo.API_KEY"
                android:value="@string/google_maps_key" />
    

    【讨论】:

      【解决方案3】:

      好吧,你可以做的就是把你的 AndroidManifest.XML 文件放在你的 .gitignore 文件中,这样它就不会被你的其余代码推上去。然后只需推上一个自述文件或其他有一个通用的 AndroidManifest.xml 源,任何人都必须将其复制并粘贴到 AndroidManifest.xml 文件中才能构建您的应用程序。这样您就可以在您的应用程序中进行更改,根据需要构建它,然后不必在每次构建时都对其进行泛化处理并推送到源代码控制中。

      【讨论】:

      • 这条评论太糟糕了,应该一直投反对票,以防止它浮出水面。 AndroidManifest.XML 需要在源代码管理中,因为它包含任何 Android 应用程序的关键配置。
      【解决方案4】:

      我过去处理类似问题的方法是使用我的 git 存储库中的特定分支进行公共推送。

      假设您有一个本地主分支,其中您的密钥在清单中。当您准备好推送到 github(或其他任何地方)时,您可以创建一个没有历史记录的新“发布”分支。你可以在这里看到更多相关信息:How to push new branch without historygit branch --orphan release。删除所有私人信息后,提交所有文件并仅将该分支推送到 github git push origin release

      问题是你不会有提交历史,也许其他人可以想出更好的东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-18
        • 2020-05-20
        • 2013-10-15
        • 2015-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多