Skip to content

Instantly share code, notes, and snippets.

@alexsinger
Last active July 10, 2019 04:42
Show Gist options
  • Select an option

  • Save alexsinger/2b5b1b7ae2d2fca1ffdb to your computer and use it in GitHub Desktop.

Select an option

Save alexsinger/2b5b1b7ae2d2fca1ffdb to your computer and use it in GitHub Desktop.
Separate Crashlytics reporting for debug and release buildTypes using a Gradle build
// The following code allows an app to report Crashlytics crashes separately
// for release and debug buildTypes when using Gradle. This code should be inserted
// into the specified locations within your build.gradle (Module:app) file
// The buildTypes { } block should be inserted inside the android { } block
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
ext.crashlyticsApiSecret = "release api secret"
ext.crashlyticsApiKey = "release api key"
}
debug {
ext.crashlyticsApiSecret = "debug api secret"
ext.crashlyticsApiKey = "debug api key"
}
}
// The following code can be inserted at the bottom of your build.gradle file
import com.crashlytics.tools.utils.PropertiesUtils
File crashlyticsProperties = new File("${project.projectDir.absolutePath}/fabric.properties")
android.applicationVariants.all { variant ->
def variantSuffix = variant.name.capitalize()
def generateResourcesTask = project.tasks.getByName("fabricGenerateResources${variantSuffix}")
def generatePropertiesTask = task("fabricGenerateProperties${variantSuffix}") << {
Properties properties = new Properties()
println "...copying apiSecret for ${variant.name}"
properties.put("apiSecret", variant.buildType.ext.crashlyticsApiSecret)
println "...copying apiKey for ${variant.name}"
properties.put("apiKey", variant.buildType.ext.crashlyticsApiKey)
PropertiesUtils.injectPropertyInFile(crashlyticsProperties, properties, "")
}
generateResourcesTask.dependsOn generatePropertiesTask
}
@chantellosejo

Copy link
Copy Markdown

def generateResourcesTask = project.tasks.getByName("crashlyticsGenerateResources${variantSuffix}") def generatePropertiesTask = task("crashlyticsGenerateProperties${variantSuffix}") << {

These two lines should use "fabricGenerateResources..." like below:

def generateResourcesTask = project.tasks.getByName("fabricGenerateResources${variantSuffix}") def generatePropertiesTask = task("fabricGenerateProperties${variantSuffix}") << {

@eric-labelle

Copy link
Copy Markdown

How could we wrap the whole fabric generating file in a condition evaluating if the ext.enableCrashlytics is true or false? Otherwise, disabling crashlytics with this flag for a specific variant or buildType or flavor will end up in an Exception. The "not-so-elegant" solution would be a try catch.. but I'd prefer to be able to test ext.enableCrashlytics

def variantSuffix = variant.name.capitalize()
def generateResourcesTask = project.tasks.getByName("fabricGenerateResources${variantSuffix}")
def generatePropertiesTask = task("fabricGenerateProperties${variantSuffix}") << {
       Properties properties = new Properties()
        println "...copying apiSecret for ${variant.name}"
        properties.put("apiSecret", variant.buildType.ext.crashlyticsApiSecret)
        println "...copying apiKey for ${variant.name}"
        properties.put("apiKey", variant.buildType.ext.crashlyticsApiKey)
        PropertiesUtils.injectPropertyInFile(crashlyticsProperties, properties, "")
}
generateResourcesTask.dependsOn generatePropertiesTask

Thanks

@fernandospr

Copy link
Copy Markdown

I had to modify the original code to support various flavors and build types (beta, release and ignore debug).
Each flavor has different API Keys and API Secret.
In my case I had to depend the task that modifies the properties on the crashlyticsUploadDistribution_Variant_ task, otherwise it won't work:

File crashlyticsProperties = new File("${project.projectDir.absolutePath}/fabric.properties")
applicationVariants.all { variant ->
    variant.productFlavors.each { flavor ->
        def variantSuffix = variant.name.capitalize()
        if (!variantSuffix.contains("Debug")) {
            def generatePropertiesTask = task("crashlyticsGenerateProperties${variantSuffix}") << {
                Properties properties = new Properties()
                properties.put("apiSecret", flavor.crashlyticsApiSecret)
                println "Setting apiSecret: ${flavor.crashlyticsApiSecret} to fabric.properties"
                properties.store(new FileWriter(crashlyticsProperties), "")
            }

            def generateResourcesTask = project.tasks.getByName("crashlyticsUploadDistribution${variantSuffix}")
            generateResourcesTask.dependsOn generatePropertiesTask
            generateResourcesTask.doLast {
                println "Removing fabric.properties"
                crashlyticsProperties.delete()
            }
        }
    }
}

@mxl

mxl commented Dec 25, 2015

Copy link
Copy Markdown

I slightly modifed original and @fernandospr solutions and post self-answered question on SO http://stackoverflow.com/q/34462065/746347

@djensen47

Copy link
Copy Markdown

So it appears that if you use applicationIdSuffix ".debug" in your debug section Fabric will actually identify it as a separate app.

@jeffdgr8

jeffdgr8 commented Jul 14, 2016

Copy link
Copy Markdown

Does this method still work? I am using Crashlytics 2.5.7 and Fabric tools 1.21.7. I get the gradle error "Task with name 'fabricGenerateResourcesDebug' not found in project ':app'."

@jeffdgr8

Copy link
Copy Markdown

OK, I figured it out. I needed to remove ext.enableCrashlytics = false from the debug build type for that gradle task to be generated. Testing it out now.

I do have the question of how the apiKey in fabric.properties works. Does this replace the need for having it in the AndroidManifest.xml?

@jeffdgr8

Copy link
Copy Markdown

Inspecting the AndroidManifest.xml within the apk package, I see the apiKey is in fact added to the final manifest in the build. Good to know how this works! Thanks.

@saurabh-bhatia

saurabh-bhatia commented Jul 28, 2016

Copy link
Copy Markdown

What changes we need to do in AndroidManifest.xml file ?

@Dragas

Dragas commented May 23, 2017

Copy link
Copy Markdown

OR You could just create an AndroidManifest.xml per build flavor and add <metadata> tag corresponding for key to use within that flavor. So essentially you'd have:

src
    debug
        AndroidManifest.xml // contains key for debug
    release
        AndroidManifest.xml // contains key for release

Then gradle does its magic and takes resources, be it classes, resources, manifests, etc. depending on current build flavor and merges their manifests. You can read about building for flavors here.

@wwdablu

wwdablu commented Nov 1, 2017

Copy link
Copy Markdown

@jeffdgr8
I do have the question of how the apiKey in fabric.properties works. Does this replace the need for having it in the AndroidManifest.xml?

+1
How do we separate out fabric.properties for debug and release build?

@DmitriyYakovlev

Copy link
Copy Markdown

Hi.
Can you please, specify where to get crashlyticsApiSecret. I can see where to get crashlyticsApiKey. For example, with using of fabric plugin for IDE

@heliobmartins

Copy link
Copy Markdown

@DmitriyYakovlev, you can get the crashlyticsApiSecret on

https://fabric.io/settings/organizations

Select your desired organisation and right bellow the name of your organization you will find API key and Build Secret.

Hope it helps.

@MehulKK

MehulKK commented Jul 10, 2019

Copy link
Copy Markdown

If you get an error like could not find method leftshift() after applying the above thing then.
Replace leftshift(<<) with doLast.

import com.crashlytics.tools.utils.PropertiesUtils

File crashlyticsProperties = new File("${project.projectDir.absolutePath}/fabric.properties")
android.applicationVariants.all { variant ->
    def variantSuffix = variant.name.capitalize()
    def generateResourcesTask = project.tasks.getByName("fabricGenerateResources${variantSuffix}")
    def generatePropertiesTask = task("fabricGenerateProperties${variantSuffix}") doLast {
        Properties properties = new Properties()
        println "...copying apiSecret for ${variant.name}"
        properties.put("apiSecret", variant.buildType.ext.crashlyticsApiSecret)
        println "...copying apiKey for ${variant.name}"
        properties.put("apiKey", variant.buildType.ext.crashlyticsApiKey)
        PropertiesUtils.injectPropertyInFile(crashlyticsProperties, properties, "")
    }
    generateResourcesTask.dependsOn generatePropertiesTask
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment