I really need to find out how to save API Keys to avoid exposing sensitive keys on public repos.
Most online tutorials advise using local.properties file to save API Keys but I see a disclaimer at the top of the local.properties file - Do not modify this file -- YOUR CHANGES WILL BE ERASED!

I need to generate a buildConfigField to access the key on the main source code; this is the code that I have on my build.gradle app file for Kotlin DSL.
defaultConfig{ ...
val properties = Properties()
val apiKey: String
val localPropertiesFile = project.rootProject.file("local.properties")
apiKey = if (localPropertiesFile.exists()) {
properties.load(localPropertiesFile.inputStream())
properties.getProperty("API_KEY") ?: ""
} else {
System.getenv("API_KEY") ?: ""
}
buildConfigField(
"String",
"API_KEY",
"\"$apiKey\""
)
... }
On the idea of using local.properties to save api keys file the docs disagree:
Caution: The local.properties file is reserved for properties specific to the Android Gradle plugin. Putting your own values in this file can cause problems. If you need to define your own local properties, create a separate properties file and manually load it.
Out of sheer curiosity, I went ahead and saved the key inside the local.properties file - the app built fine but the buildConfigField returned an Empty String.

Who knows how to go about this in a safe recommended way?
As noted by @CommonsWare on comments, the easiest way is to create a separate properties file.
Step 1:
Create apikeys.properties file (you can use your preferred file name as long as it has .properties file extension) in your project's root directory and add your API key:
API_KEY = "xyz"
Step 2: Add the created .properties file on .gitignore file to avoid its tracking by your version control.
local.properties
gradle.properties
apikey.properties
Make sure you don't also accept VC's dialogue prompt to add the .properties file to staging.
Step 3: Inside build.gradle.kts file ( i.e. inside the Android block) you can load the key-value properties from the .properties file and access them as follows:
android { ...
defaultConfig { ...
//load the values from .properties file
val keystoreFile = project.rootProject.file("apikey.properties")
val properties = Properties()
properties.load(keystoreFile.inputStream())
//return empty key in case something goes wrong
val apiKey = properties.getProperty("API_KEY") ?: ""
Above code loads the API key from.properties file and adds it as a BuildConfig class' constant for both release and debug build types.
BuildConfig class is automatically generated by Gradle plugin during the build process, it contains various constants and flags that can be accessed in your Android code.
Step 4: Specify the buildConfigField() function - buildConfigField (...) allows us to define custom fields in the BuildConfig class. This fxn is useful for injecting config values such as API keys etc. It takes 3 args - Type (in this case our good-old String), Name as specified on .properties file and Value which is our loaded api key.
val apiKey = properties.getProperty("API_KEY") ?: ""
buildConfigField(
type = "String",
name = "API_KEY",
value = apiKey
)
Step 5: Access the BuildConfig class constant on your main source code:
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//call BuildConfig to access its API_KEY Constant
val apiKey = BuildConfig.API_KEY
Log.i("tag", apiKey)
This way, when you push your code into a public repo it won't leak .properties file which has your classfied info out there. However, you will still have access to the api keys locally.
Cheers.
Do not save them in local.properties. As you mentioned, the file can be erased. Also, if you need such keys in several projects, you have to keep adding the same values, and it will be useless for CI. Instead of that, add them to your environment and read them from there. The same approach is valid on a CI server (like jenkins), and it will be a bit safer.
Reading an environment value from gradle:
var auth = if(System.getenv("your_key")!=null){
println("api key is present!")
System.getenv("your_key")
} else {
println("api key is absent. Set it manually and make sure to not commit it.")
""
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With