XML getting values from another XML file

Viewed 742

I am trying to build an android application that uses the Google Map API and I want to put this project on GIT. So I have an API key and this information is inside AndroidManifest.xml like this (I have replaced my actual API key with *key* here

<meta-data
android:name="com.google.android.geo.API_KEY"
android:value= *key* />

I don't want this sensitive information pushed on git, but I can't gitignore this file. Is it possible to make another XML file that has the secret key and make the AndroidManfiest.xml get it from there (so that I can gitignore this one)?

AndroidManifest.xml has this bit of code

<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps"
android:launchMode="singleTop" />

And I noticed that the label property gets its value from another XML file that's located in res/values/strings.xml so:

  1. how does AndroidManifest.xml know where to find the value for label
  2. what does the @ mean?
  3. can I put a XML file (called Config.xml) anywhere? or does it have to be in the res folder?
2 Answers

To avoid uploading your key:

  1. Create the key in a properties file and add the file in .gitignore

     API_KEY=XXXXXXXXXXX
    

    inside .gitignore, add the path

     secretKeys.properties 
    
  2. Read the file in app/build.gradle and create a string resource variable using buildConfigField

     def apikeyPropertiesFile = rootProject.file("apikey.properties")
     def apikeyProperties = new Properties()
     apikeyProperties.load(new FileInputStream(apikeyPropertiesFile))
    
     android {
    
       defaultConfig {
    
         buildConfigField("String", "API_KEY", apikeyProperties['API_KEY'])
       }
     } 
    
  3. Use the created variable!

Follow the blog for complete details.

how does AndroidManifest.xml know where to find the value for the label

Android build generates an R.java file for all the XML contants and maps all the occurrence of XML contents with the value from the R.Java file.

what does the @ mean?

This is a special symbol, used by the parser to parse specific string resources. For example, @+id/root means, parse this as an id resource string to replace value from R.java.

can I put an XML file (called Config.xml) anywhere? or does it have to be in the > res folder?

Yes, it has to be in a res folder.

You should be able to put the secret string in its own XML file and add that file to your gitignore. You can then reference the string in AndroidManifest.xml.

Example:

app/src/main/res/values/secrets.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="google_api_key">abcdefg-12345</string>    
</resources>
app/src/main/AndroidManifest.xml

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

To answer your questions: Any Android XML file (like AndroidManifest.xml, layout, and other files) interprets the value of an attribute as a raw string unless it starts with @. The @ prefix tells it to look up a resource. @string indicates a string resource, @layout means a layout, @drawable means a drawable, @id means an ID, and etc. Each of these resources are typically defined in their own file, but not always. No matter what, the file is always within a sub-directory of res. For your case, strings are defined in res/values/some_file.xml. You can make any number of files within res/values and the contents of all these files gets merged together during the AAPT compile step, so you can reference any of them by their defined name, regardless of the file name.

Check out https://developer.android.com/guide/topics/manifest/meta-data-element for more information on the <meta-data> tag and https://developer.android.com/guide/topics/resources/string-resource for info on string resources.

Related