Android: automatically choose debug/release Maps v2 api key? - android

I'm using Google Maps v2 API in my project. In Google Maps v2 the debug/release API key is defined in AndroidManifest.xml. I have seen the link but in that map key is defined in a xml layout file not in AndroidManifest.xml. So can I define both debug and release keys for my project in AndroidManifest.xml?
I want something like this in AndroidManifest.xml:
If debug mode:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/debug_map_api_key"/>
If release mode:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/release_map_api_key"/>

Using build.gradle
buildTypes {
debug {
buildConfigField("String", "map_api_key", "\"your debug map api key here\"")
}
release {
buildConfigField("String", "map_api_key", "\"your release map api key here\"")
}
}
I solved this issue using this steps:
In Google Developer API Console
Click on Create New Android key...
In cmd.exe/Terminal: keytool -list -v -keystore mystore.keystore
Password: android
Now enter SHA1 key;package name for debug and press enter
Enter SHA1 key;package name for release
Click on Create
Now use this API key your project
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/common_map_api_key"/>

One of the Best way to use build.gradle file in latest Android 5.0 and Android 6.0, Android 9+ (API 20, 21,22,23, 24, 25,26, 27 28, 29)
Well you can use them simply without creating product flavors in gradle. This is another example we can achieve via Gradle. You can achieve it with two simple steps.
Add custom value to manifestplaceholders build.gradle file.
See below
buildTypes {
debug {
manifestPlaceholders = [ mapApiKeyValue:"GHjaSyAjlyp3O831lgaonHMXsd-_DpQ3002x3S4"]
}
release {
manifestPlaceholders = [ mapApiKeyValue:"AIzaSyAuMGDLr2HeuRed4JA0CrdYYdZRjeC3EA"]
}
}
Edit manifest file like below.
part of my manifest file
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="${mapApiKeyValue}" />
This solution works for the latest Android 5.0 and Android 6.0 (API 20, 21,22,23)
Updated on 5/3/2018 for Xamarin Form and Xamarin Native Apps
Open AssemblyInfo.cs in Android Project and addd the following code
#if DEBUG
[assembly: MetaData("com.google.android.maps.v2.API_KEY", Value = "DebugKey123123123")]
#else
[assembly: MetaData("com.google.android.maps.v2.API_KEY", Value = "ReleaseKey123123123")]
#endif
To Check the AndroidManifest file, goto obj/Debug/android folder and open the manifest file and check the meta info,
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="DebugKey123123123" />

For organizations that need to maintain separate keys, you can place them in separate directories in Android Studio. Make sure the subdirectory of src you use matches a flavor or buildType
From Building Your Project with Gradle:
To build each version of your app, the build system combines source code and resources from:
src/main/ - the main source directory (common to all variants)
src/<buildType>/ - the build type source directory
src/<flavorName>/ - the flavor source directory
In projectroot/yourapp/build.gradle:
buildTypes {
debug {
runProguard false
debuggable true
}
release {
runProguard true
debuggable false
...
}
In projectroot/yourapp/src/main/AndroidManifest.xml:
...
<application
android:name=".MyApplication"
android:theme="#style/Theme">
<!-- Don't put your key here -->
...
In projectroot/yourapp/src/debug/AndroidManifest.xml, fully qualify the name of the app.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:name="com.hipmunk.android.HipmunkApplication">
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="yourdebugkey" />
</application>
</manifest>
In projectroot/yourapp/src/release/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:name="com.hipmunk.android.HipmunkApplication">
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="release key" />
</application>
</manifest>

Since you are using gradle you can do the following:
build.gradle
android {
.. .. ...
buildTypes {
debug {
resValue "string", "google_maps_api_key", "[YOUR DEV KEY]"
}
release {
resValue "string", "google_maps_api_key", "[YOUR PROD KEY]"
}
}
}
And in your AndroidManifest.xml
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/google_maps_api_key"/>
This way you only have one AndroidManifest.xml and you set value based on your build type. Hope this helps.

Related

How to secure Fabric API Key from APK decompilation?

While decompiling my android app APK file, I have found the fabric ApiKey key in manifest file. How to secure Fabric API Key from APK decompilation?
I have done following code changes for hiding Fabric API key from manifest file. But still it is visible after APK decompilation.
I added my fabric API key
FabricAPIKey=0123456789ABCDEF012345123456789ABCDEF012
in gradle.properties.
In build.gradle(Module)
...........
def FABRIC_API_ID = FabricAPIKey
.....
buildTypes {
debug {
..........
manifestPlaceholders = [//this is used for defining the variable for manifest file
FABRIC_API_KEY:FABRIC_API_ID
]
}
release{ ..........
manifestPlaceholders = [//this is used for defining the variable for manifest file
FABRIC_API_KEY:FABRIC_API_ID
]
}
And in AndroidManifest.xml
<meta-data
android:name="io.fabric.ApiKey"
android:value="${FABRIC_API_KEY}" />
Mike from Fabric here. Seva's point should be well noticed - "a sufficiently motivated hacker can eventually get to it, given a debugger and enough time".
If you want, you can place the API key and Build secret in a fabric.properties file. Copy your api key out of your android manifest, and delete the line that reads: <meta-data android:name="com.crashlytics.ApiKey" android:value="YOUR_API_KEY_HERE"/>
Then make a file called fabric.properties and place this folder in the root of the module that applies crashlytics in its' build.gradle In the fabric.properies file, add:apiKey=YOUR_API_KEY_HERE
Once that's complete, refresh your dependencies to pull in the change: ./gradlew clean --refresh-dependencies
Try to save that in strings.xml and refer that here.
Then manifest will only show resource id in int format.
But if you open the strings.xml file it will be retrieved.

Android add separate google map api key for release and debug build modes

i am developing an android application using android studio 2.3. I added google map activity to my project using built in add activity dialog.
When i check the google map api key it is saved in a separate xml file inside values folder but under debug varient. I need to add a new api key that is going to use only for relase mode (builds). How do i add such a separate api key xml file for release mode as well?
Thanks in advance!!
AndroidManifest.xml:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/google_maps_api_key"/>
app/build.gradle:
android {
...
buildTypes {
debug {
resValue "string", "google_maps_api_key", "[YOUR DEBUG KEY]"
}
release {
resValue "string", "google_maps_api_key", "[YOUR RELEASE KEY]"
}
}
}
Just create same xml file in release folder.
You're default debug key is probably in file project_location/src/debug/res/values/some_file_name.xml.
You need to create same file in project_location/src/release/res/values/some_file_name.xml And put you'r release key there.
Recreate the debug and\or release folder structure in the same folder as your "main" one. Any files placed here will replace the ones in main depending on the build type.

Change debug/release manifest key dynamically for each flavor

I am using one service where it's required to setup API key in AndroidManifest like this:
<meta-data
android:name="service_api_key"
android:value="#string/my_api_key" />
The problem with this is that I have a couple of flavors of my app and I need to setup different API keys for each flavor. Each flavor needs to have different API key for debug and release:
flavor1
- debug key: key1
- release key: key2
flavor2
- debug key: key3
- release key: key4
flavor3
- debug key: key5
- release key: key6
What would be the recommended way to accomplish this?
What would be the recommended way to accomplish this?
Step #1: Create sourcesets for each build variant (src/flavor1Debug/, src/flavor1Release/, etc.) for which you need a different API key than whatever you have in src/main/.
Step #2: In each sourceset, have a res/values/strings.xml file that contains that build variant's value for my_api_key.
Step #3: Beer.
not tested but I imagine you could try something like this...
applicationVariants.all {variants ->
variant.productFlavors.all { flavor ->
flavorChoosed = " ${flavor.name}"
}
}
release {
switch(flavorChoosed){
case "flavor1":
resValue "string", "flavorId", apiKeyRealeseFlavor1
break
.....
}
}
debug{
switch(flavorChoosed){
case "flavor1":
resValue "string", "flavorId", apiKeyDebugFlavor1
break
.....
}
}
<meta-data
android:name="service_api_key"
android:value="${flavorId}" />
For each Product Flavor you have added to your gradle file you should add a string.xml resource file for values.
When you switch your build variant, Android studio will be smart enough to grab the matching value for your build.
If you dont specify one, then it defaults to the main one.
EDIT:
Then for the source set, select the release or debug version of your productFlavor:

Android Facebook content provider authority

I'm developing an app with (at least) two flavors having different package names - therefore actually two different apps as far as the android system is concerned. The app uses Facebook sharing, so I have the provider declared in the manifest:
<provider android:authorities="com.facebook.app.FacebookContentProvider{app id here}"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
This is done according to Facebook's instructions: https://developers.facebook.com/docs/sharing/android
This works fine with one app, but trying to install the second app on the same device fails with the error INSTALL_FAILED_CONFLICTING_PROVIDER. This is the only provider defined in the manifest so I'm pretty sure it's the problem. If I change the provider string to be something different it crashes when attempting to open a Facebook share dialog.
I've seen claims that it's possible to use the same Facebook app in multiple android apps, but can't find anything in Facebook's documentation about it. Has anybody done this, and how did you get around the provider authority problem? Thanks.
One of the possible solutions I have found is the one described here
http://gradlewhy.ghost.io/overcoming-install-failed-conflicting-provider/
I am already using this for (debug/release variants) android.support.v4.content.FileProvider and as far I have tested also works for com.facebook.app.FacebookContentProvider.
Just add into apps build.gradle
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
resValue "string", "fb_provider_id", "com.facebook.app.FacebookContentProvider{app_id_1}"
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
resValue "string", "fb_provider_id", "com.facebook.app.FacebookContentProvider{app_id_2}"
}
and then in the AndroidManifest
<provider android:authorities="#string/fb_provider_id"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
I was able to solve this by having separate manifests for my debug and release flavors and in my debug flavor manifest, I added the snippet for the provider but set the exported value to false. In my release flavor manifest, I have the original provider snippet with exported set to true.
After I did this, I no longer got the INSTALL_FAILED_CONFLICTING_PROVIDER error.
<provider android:authorities="com.facebook.app.FacebookContentProvider{app id here}"
android:name="com.facebook.FacebookContentProvider"
android:exported="false"/>
<provider android:authorities="com.facebook.app.FacebookContentProvider{app id here}"
android:name="com.facebook.FacebookContentProvider"
android:exported="false"/>
exported can be "true"
If your have one project and multiple flavors(means: multiple apps with minor tweaks) like me, you can
1.create multiple facebook app (from https://developers.facebook.com/apps/)
2.add codes for correspoding flavor
3.add facebook_app_id string value in the corresponding flavor's folder.
Example:
app/build.gradle
...
flavorDimensions "regular"
productFlavors {
flavour_name {
dimension "regular"
resValue "string", "authority", "com.facebook.app.FacebookContentProvider123456789"
}
app/src/main/AndroidManifest.xml
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id"/>
<provider android:authorities="#string/authority"
android:name="com.facebook.FacebookContentProvider"
android:exported="true" />
app/src/flavour_name/res/values/string.xml
<string name="facebook_app_id" translatable="false">123456789</string>

Android Google Maps v2 - Debug key vs Release key

it is clear to me how to get a debug key for use with Google Maps v2 library, and also how to get a release key. Currently the relevant section of my manifest file looks like this:
<!-- Debug -->
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="[my debug key here]"/>
<!-- Release
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="[my release key here]"/>
-->
The relevant key is uncommented, the other one is commented.
Can anyone indicate a comfortable way to avoid this annoyance of commenting/uncommenting these pieces of manifest file everytime a debug rather than release version is needed?
With version 2 API's you can use the same key for release and debug. In your google api's console edit your allowed android apps and on each line put your debug/release key, and then your app name. You can use multiple lines, then it will work with both keys.
Different Google Map API keys for debug build and release build can be defined in build.gradle:
...
android {
...
buildTypes {
debug {
resValue "string", "google_maps_api_key", "<debug_key>"
...
}
release {
resValue "string", "google_maps_api_key", "<release_key>"
...
}
}
}
Just replace <debug_key> and <release_key> with your actual keys.
And refer to this resource value in AndroidManifest.xml:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/google_maps_api_key"/>
This solution is also described in the following Stack Overflow question:
Manage Google Maps API Key with Gradle in Android Studio
Alternatively, you can place your debug key in app/src/debug/res/values/google_maps_api.xml with a content similar to this:
<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">AIzaXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx</string>
In the same way, place the release key in app/src/release/res/values/google_maps_api.xml.
In this manner you have both keys and same source code. This is very convenient for open source projects where you want to publish your source code but not your API keys. You just need to ignore / not upload the google_maps_api.xml file and you're good to go.

Categories

Resources