25

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 !

4 Answers 4

42

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.

Sign up to request clarification or add additional context in comments.

5 Comments

You should also untrack your api-keys.xml file before creating the gitignore file. Otherwise you'll still push changes. link
Just a small FYI, for some reason, IntelliJIdea does not want api-keys.xml so use api_keys.xml instead.
This is a great answer. For some reason I thought all string resource xml files needed to be named values by convention. Now I have learned that I can do the same thing on Android as I do for my other projects!
My preferred solution to handle the modfied file is to use the command: git update-index --assumed-unchanged api-key.xml.
This is great, but can the project be built without the key file? Does not it violate the "basic" rule of version control -- only code that can be compiled should be versioned?
1

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" /> 

Comments

0

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.

Comments

0

If you create Google Maps Activity from Android Studio as a template it will add needed plugin in your build.gradle file, and then you can put your API key in local.properties file and use it as variable in Manifest file as for example: "${API_KEY}"

For more information visit https://developers.google.com/maps/documentation/places/android-sdk/secrets-gradle-plugin

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.