How to maintain two google-services.json, production and debug - android

I am including feature of gcm in my app, For that i need to maintain two google-services.json one for debug and one for release build. How to do that ?? can i configure gcm without using google-services.json ??

First, place the respective google_services.json for each buildType in the following locations:
app/src/debug/google_services.json
app/src/test/google_services.json
app/google_services.json
Note: Root app/google_services.json This file should be there according to the build variants copy the json code in the root json file
Now, let’s whip up some gradle tasks in your: app’s build.gradle to automate moving the appropriate google_services.json to app/google_services.json
copy this in the app/Gradle file
task switchToDebug(type: Copy) {
description = 'Switches to DEBUG google-services.json'
from "src/debug"
include "google-services.json"
into "."
}
task switchToRelease(type: Copy) {
description = 'Switches to RELEASE google-services.json'
from "src/release"
include "google-services.json"
into "."
}
Great — but having to manually run these tasks before you build your app is cumbersome. We would want the appropriate copy task above run sometime before: assembleDebug or :assembleRelease is run. Let’s see what happens when :assembleRelease is run: copy this one in the /gradlew file
Zaks-MBP:my_awesome_application zak$ ./gradlew assembleRelease
Parallel execution is an incubating feature.
.... (other tasks)
:app:processReleaseGoogleServices
....
:app:assembleRelease
Notice the :app:processReleaseGoogleServices task. This task is responsible for processing the root google_services.json file. We want the correct google_services.json to be processed, so we must run our copy task immediately beforehand.
Add this to your build.gradle. Note the afterEvaluate enclosing.
copy this in the app/Gradle file
afterEvaluate {
processDebugGoogleServices.dependsOn switchToDebug
processReleaseGoogleServices.dependsOn switchToRelease
}
Now, anytime :app:processReleaseGoogleServices is called, our newly defined :app:switchToRelease will be called beforehand. Same logic for the debug buildType. You can run :app:assembleRelease and the release version google_services.json will be automatically copied to your app module’s root folder.
Credit goes to the : Zak Taccardi
https://medium.com/google-cloud/automatic-per-variant-google-services-json-configurations-with-gradle-d3d3e40abc0e

The current plugin (com.google.gms:google-services:2.1.X) supports flavors but not types.
So if you create a productflavor you can put the json file in src/$flavorname
Example:
app/src/
flavor1/google-services.json
flavor2/google-services.json
Currently it doesn't work with types (debug, release...) but you can use somenthing like this:
app/src/release/google-services.json
app/google-services.json
In this case the plugin looks in the locations and stops when it finds a google-services.json file.
If you are using a flavor it becomes:
app/src/foo/release/google-services.json
app/src/foo/google-services.json
You can find updated info here.

I'm currently using the following versions: com.google.gms:google-services:4.3.3, com.google.firebase:firebase-messaging:20.2.0
Place your google-services.json file in your $projectName/app/src/$buildType directory. For example, place one json file in src/release and another in src/debug. You will likely need to create the release & debug folders.
Note: It's a common mistake to add these files in the app folder, be sure you add this in the src folder as described above.
The google-services plugin always looks for the google-services.json
file in two directories: First, on the
$projectName/app/src/$buildType/google-services.json. If it does not
find it here, it goes one level above, to the
$projectName/app/google-services.json. So, when you are building the
debug version of your app, it will search for the google-services.json
on the $projectName/app/src/debug/ directory.
At the link below, see David Ojeda's response.

Related

Minimum Necessary files for an android build

Trying to find the bare minimum source and build files needed to build an android project in Android Studio. I want to publish to github and avoid uploading generated build files or binaries.
I do have a Android.gitignore from but I still see some more files getting pushed into the repo which may not be necessary. I understand the few obvious ones but about others, do I need them and if so kindly explain the usage.
So the question, do I need the following and if so then a short description of why?
root
build.gradle
gradle.properties
gradlew
gradlew.bat
settings.gradle
/app
app/build.gradle
app/proguard-rules.pro
/gradle (tested, android can re-download/generate following it if not present)
gradle/wrapper/gradle-wrapper.jar
gradle/wrapper/gradle-wrapper.properties
This question can have two different answers based on the meaning of the word needed.
First (the real one)
Assuming your project has currently those files, if your question is:
Should I commit these files on my Git repo?
The answer is yes, all of them, and I'm explaining why:
root
build.gradle -> defines the configuration for all the Gradle modules in your project (e.g. use the same remote repositories to download some Gradle plugins)
gradle.properties -> defines some optional flags used when building the app (e.g. enabling the incremental KAPT, enabling the AndroidX jetifier)
gradlew -> invokes the Gradle wrapper (which can be found under gradle/wrapper/gradle-wrapper.jar) to avoid to have Gradle installed when building your project on Darwin/Linux
gradlew.bat -> the same of gradlew but for Windows
settings.gradle -> defines the list of modules which are part of your project
app/
app/build.gradle -> defines the configuration only for your app module (e.g. its build types, its flavors, its version code and version name)
app/proguard-rules.pro -> defines the obfuscation rules when your app enables the minification
gradle/
gradle/wrapper/gradle-wrapper.jar -> provides the same version of the Gradle wrapper jar for all the users. This is very important because it forces the users to use the same version of the Gradle wrapper to compile your app
gradle/wrapper/gradle-wrapper.properties -> same as above, it defines which version of the Gradle wrapper you need
Second (the useless one)
Now, I'll give you the answer to the question:
Are these files strictly needed to compile an Android project?
To successfully compile an Android project with Gradle you just need the root build.gradle if you have Gradle installed on your machine or build.gradle + the wrapper files if you have not Gradle installed on your machine.
Theoretically you can:
put your application code in the root project and that avoids you one build.gradle and settings.gradle
disable the obfuscation and that avoids you proguard-rules.pro
remove gradle.properties and set the properties via command line
Obviously this solution won't happen on a real project scenario.

How to use different settings.gradle files for different environments

The problem
I have two projects, A (ui) and B (background service). Project A has a dependency on B. Project B gets published to a maven repository and included in project A like so in build.gradle
debugImplementation ('com.example:project-B:0.0.0-SNAPSHOT') { changing = true }
releaseImplementation ('com.example:project-B:1.6.2')
This works, but it's a pain to validate my service changes on the UI side. I need to publish project B to my nexus repo and resync project A.
I changed project A to the following:
build.gradle:
debugImplementation project(":project-b")
settings.gradle:
include ':project-a'
include 'project-b'
project(':project-b').projectDir = new File(settingsDir, "${project-b-path}")
I can have all my code in one IDE window and have A use local instance of B. But the problem is this will break on my build server since there is no local B project, only the one on nexus.
Is there a way to configure the settings.gradle for release vs debug? I can just commit my changes and overwrite the file on the build server, but I want to know if there are other ways?
You can use gradle command line to set which settings or build file should be used.
Settings File
-c, --settings-file
Specifies the settings file. For example: gradle --settings-file=somewhere/else/settings.gradle
Build File
-b, --build-file
Specifies the build file. For example: gradle --build-file=foo.gradle. The default is build.gradle, then build.gradle.kts, then myProjectName.gradle.
You can find more details here: Gradle docs: Environment options

How to change path for release APK artifact?

How can I configure a Gradle Android project so that a release APK built by the IDE is saved to a path of my choosing (eg the project root) rather than buried deep in the build folder?
I've added this to the defaultConfig section of the app build file to sensibly name the APK and it works well, but how can I specify where it goes, or move it post build completion?
archivesBaseName = "AppName-v$versionName" // AppName-v1.2.3-release.apk
UPDATE:
I created a task in the app-level Gradle build file that successfully copies the release APK, if I run the Gradle task manually:
task copyReleaseApk(type: Copy) {
from 'build/outputs/apk'
into '..' // project root, one-level above "app"
include '**/*release.apk'
}
But I have not yet found a way to make the task run automatically after the last build task. I tried this:
assembleRelease.finalizedBy(copySupportFiles)
But that results in "Could not get unknown property 'assembleRelease' for object of type com.android.build.gradle.AppExtension."
I also tried this:
assembleRelease.finalizedBy(copySupportFiles)
It appears not to do anything.
This worked (in the android tag of the app build.gradle file). The afterEvaluate seems to be required in order to refer to tasks like packageRelease that don't initially exist.
task copyReleaseApk(type: Copy) {
from 'build/outputs/apk'
into '..' // folder above the app folder
include '**/*release.apk'
}
afterEvaluate {
packageRelease.finalizedBy(copyReleaseApk)
}
It can be defined in the project's root build.gradle:
allprojects {
buildDir = "/path/to/build/${rootProject.name}/${project.name}"
}

Could not get unknown property 'processReleaseGoogleServices'

I updated to use Android Studio 2.2 and Gradle 2.2.0. And now I have a problem building.
I followed this post https://medium.com/google-cloud/automatic-per-variant-google-services-json-configurations-with-gradle-d3d3e40abc0e#.g1p7c1tx2 to configure two "google-services.json" files to be used for dev vs prod builds and use the following method in my app/build.gradle file to toggle between the copying the two "google-services.json" files.
afterEvaluate {
processDebugGoogleServices.dependsOn switchToDebug
processReleaseGoogleServices.dependsOn switchToRelease
}
task switchToDebug(type: Copy) {
description = 'Switches to DEBUG google-services.json'
from "src/gcm-dev"
include "google-services.json"
into "."
}
task switchToRelease(type: Copy) {
description = 'Switches to RELEASE google-services.json'
from "src/gcm-prod"
include "google-services.json"
into "."
}
Gradle complies fine but when I click on the "Run app" (triangle "play" icon) or "Debug app" (triangle "play" icon with a bug behind) buttons in Android Studio, I get the following:
* What went wrong:
A problem occurred configuring project ':app'.
> Could not get unknown property 'processReleaseGoogleServices' for object of type com.android.build.gradle.AppExtension.
Please help, much appreciated.
I had the same issue and problem was in enabled instant run.Try to disable it and run again.
You should update Google Play Services gradle plugin as well, follow the documentation to set it up: https://developers.google.com/android/guides/google-services-plugin
The great thing is that you no longer need to write gradle tasks which create appropriate google-services.json files in your root directory. Build type specific google-services.json are now supported by the plugin:
"As of version 2.2.0 the plugin supports build type and product flavor
specific JSON files. All of the following directory structures are
valid"
An alternative way to this is to refer to the task in the following way:
tasks.whenTaskAdded { task ->
if (task.name == 'assembleDebug') {
task.dependsOn 'switchToDebug'
} else if (task.name == 'assembleRelease') {
task.dependsOn 'switchToRelease'
}
}
UPDATE
The problem you mentioned in comment is related to your google-services.json file. You need to place google-services.json into app/ dir. And for each build type there should be accordant director in app/src folder.
If file already exists check if correct package name inside it
"client_info": {
"mobilesdk_app_id": "1:6596814400689:android:65d6f25f5006145",
"android_client_info": {
"package_name": "com.my.app.package.name"
}
As described by #Singed, add a directory pr build type/flavor under src-directory and the corresponding google-services.jsonand Google Play gradle plugin will take care of the rest, e.g.:
src/
debug/google-services.json
release/google-services.json
During build the correct file will be processed, ending up in build/generated/res/google-services/debug|release/values/values.xml

Crashlytics NDK symbols and Gradle tasks

I have a question that mostly relates to gradle.
I'm using Crashlytics to report NDK crashes in my Android app.
I have a task in build.gradle that calls ndk-build and compiles the cpp files into an .so file.
At the end of this task I want to call a task that uploads generated symbols mapping to Crashlytics.
After installing the Fabric plugin in Android Studio, I saw there are some new tasks that were added to the Gradle tab. One of them is
crashlyticsUploadSymbols[buildType][flavour] where buildType and flavour indicate which buildtype and flavour is currently selected.
This task does seem to upload a symbols file.
My question is,
Is it possible to call this task from within build.gradle?
Currently I use a manual call in Android Studio's terminal tab in the form of:
./gradlew crashlyticsUploadSymbols[buildType][flavour]
Is it possible to call this task somehow from within build.gradle?
To call this task I use finalizedBy at the end of the buildNdk task, so once buildNdk has finished, the upload task will execute.
Also very important, how can I get the current buildType and flavour so I am able to add it to the crashlyticsUploadSymbols call?
Thank you!
Mike from Crashlytics and Fabric here.
This was also answered on the Twitter Community forum's, but sharing the same answer here.
Option 1:
If you only want or need to upload symbols for your release builds, then you can set crashlticsUploadSymbolsRelease as the finalizedBy task for your ndk-build task.
Option 2:
If you have multiple variant-based tasks, you can do something like:
android.applicationVariants.all { variant ->
def variantName = variant.name.capitalize()
def task = project.task ("ndkBuild${variantName}")
task.finalizedBy project.("crashlyticsUploadSymbols${variantName}")
}
The following did the job for me:
android {
...
afterEvaluate {
assembleDebug.finalizedBy(crashlyticsUploadSymbolsDebug)
assembleRelease.finalizedBy(crashlyticsUploadSymbolsRelease)
}
}

Categories

Resources