android – Edit an AndroidManifest when compiling to remove API-key-ThrowExceptions

Exception or error:

I’m currently working on an Android project, and learning how to use git.
I’m blocked because of a problem with git : I have my Google Maps api key declared in my android-manifest file :

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

Now, I’d like to push my code in github, but I can’t push my AndroidManifest, because it contains my api key (which is supposed to remain secret).

I’d like to know if there is a way to modify it before every push, or maybe modify it each time I compile my application?

Thank you for your help !

How to solve:

Create a new *.xml file in your res/values (call it api-keys.xml or something similar).

Change your manifest to point to this string:

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

When you first push your changes to the public, put in a dummy key.

Then edit the file with your real API key.

Then add the file to your .gitignore file so it doesn’t get pushed again.

###

Well, what you could do is put your AndroidManifest.XML file in your .gitignore file and that way it won’t get pushed up with the rest of your code.. Then just push up a readme file or something that has a generalized AndroidManifest.xml source that anyone would have to copy and paste into an AndroidManifest.xml file in order to build your application. That way you can make changes in your app, build it as needed and then not have to deal with generalizing it on every build and push into source control.

###

I suggest to use Gradle to dynamically load the API key for different build types and load a dummy key if none is found. This has the advantage that also a CI can build your application without the need of a real API key, but every new developer in your team has to set up the API key.

  1. create a properties file google-maps-api.properties in your root gradle folder. Ignore the file by adding this line gradle/google-maps-api.properties to your .gitignore and put in the following 2 properties:
googleMapsApiKeyDebug=[YOUR_DEBUG_GOOGLE_MAPS_API_KEY_HERE]
googleMapsApiKeyRelease=[YOUR_RELEASE_GOOGLE_MAPS_API_KEY_HERE]
  1. Next create the following google-maps-api-config.gradle file in your root gradle folder. This Gradle file will load the property file you created in step 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. Add the the following to your app/build.gradle file:
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)}\""
        }
    }

This will create a String Resource with the key google_maps_key and the value of your API key. You can delete any other API key references, e.g. Android Studio generate the following files: app/src/debug/res/values/google_maps_api.xml and app/src/release/res/values/google_maps_api.xml – you can delete them.

  1. Add the Google Maps API Key to your manifest:
<application>

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

###

The way I have approached similar issues in the past is by using specific branches in my git repo for pubic pushes.

Say you have a local master branch with your keys in the manifest. When you are ready to push to github (or wherever else) you can make a new “release” branch with no history. You can see a bit more about that here: How to push new branch without history git branch --orphan release. Once you do that remove all private information, commit all files and push only that branch to github git push origin release.

The issue with this is you will not have a commit history, maybe someone else can come up with something better.

Leave a Reply

Your email address will not be published. Required fields are marked *