Project shows how to:
- setup Crashlytics on android with gradle build system
- disable Crashlytics for the debug build type
- hide
apiSecret
andapiKey
from repository - support custom source folder structure
Crashlytics for Android delivers deep, rich crash reporting across devices in real-time. Crashlytics performs a detailed analysis of every thread on every Android device to identify the most important issues.
Crashlytics is one of the crash reporting tools available to collect crash info from the user devices. Very likely you are using one of the alternatives already: Acra, Bugsense, Crittercism, etc. Crashlytics have all the features we would expect from crash reporting tool. Most important are: proguard deobfuscation, support for both handled and unhandled exceptions with no limits on free account.
First of all we need to login at Crashlytics dashboard www.crashlytics.com and download Android Studio plugin. Successful authorization within Android Studio plugin is required to continue.
Then we enable Crashlytics by adding crashlytics plugin and compile dependency to our project build script. Make sure to add Crashlytics maven repository because Crashlytics binaries are not available at maven central.
app/build.gradle
buildscript {
repositories {
maven { url 'http://download.crashlytics.com/maven' }
}
dependencies {
classpath 'com.crashlytics.tools.gradle:crashlytics-gradle:1.+'
}
}
apply plugin: 'crashlytics'
repositories {
maven { url 'http://download.crashlytics.com/maven' }
}
dependencies {
compile 'com.crashlytics.android:crashlytics:1.+'
}
Then start Crashlytics from application entry point and that's all is needed to catch unhandled exception on server.
src/java/com.github.plastiv.crashlyticsdemo.CrashlyticsDemoApplication
public class CrashlyticsDemoApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Crashlytics.start(this);
}
}
Wait a second, if that's all what needed, how does Crashlytics authorize SDK and knows where to send the crashes? Glad you asked.
Crashlytics gradle plugin generates additional files with supporting information which are used later to get apiKey
from code. After building the project we can see next autogenerated modification to sources:
app/src/main/assets/crashlytics-build.properties
version_name=0.0.1
package_name=com.github.plastiv.crashlyticsdemo
build_id=d8ba607c-1abc-49c5-9f55-2f45b7de083b
version_code=1
app_name=Crashlytics Demo
app/src/main/res/values/com_crashlytics_export_strings.xml
<resources>
<string name="com.crashlytics.android.build_id" translatable="false">d8ba607c-1abc-49c5-9f55-2f45b7de083b</string>
</resources>
app/src/main/AndroidManifest.xml
<meta-data
android:name="com.crashlytics.ApiKey"
android:value="cc238b2a4866ceb061b008839cdb49a8b77"/>
Both crashlytics-build.properties
and com_crashlytics_export_strings.xml
are autogenerated files and should be excluded from source control as they would be modified on each build by Crashlytics plugin. Meta data at AndroidManifest not needed to be hardcoded as it would be autogenerated also.
Version name, code and package will be loaded from gradle build script. Crashlytics credentials can be controlled from crashlytics.properties
file.
app/crashlytics.properties
apiSecret=7c9df6d057e7bb62b17ab364e8115a75fcf7430873b6274bb094d1a8adb
apiKey=cc238b2a4866ceb061b008839cdb49a8b77
We can get apiSecret
and apiKey
from ~/.crashlytics/User.json
where they were created after successful login with Crashlytics plugin GUI for Android Studio. It make sense to keep this values private without sharing them at repository so we added crashlytics.properties
file to the .gitignore
too.
.gitignore
# Crashlytics plugin
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
We may want to disable Crashlytics crash logging during debugging on local machine. Because all crashes are directly accessible from adb logcat with no need to use server infrastructure and be reported by mail. This could be done with gradle flavors and ext.enableCrashlytics
parameter.
app/build.gradle
android {
buildTypes {
debug {
// disable crashlytics
buildConfigField "boolean", "USE_CRASHLYTICS", "false"
ext.enableCrashlytics = false
}
release {
// enable crashlytics
buildConfigField "boolean", "USE_CRASHLYTICS", "true"
ext.enableCrashlytics = true
}
}
}
After disabling Crashlytics gradle plugin with ext.enableCrashlytics=false
it stops to create crashlytics-build.properties
and com_crashlytics_export_strings.xml
files and starting Crashlytics from code results in exception due to missing information. We wrap Crashlytics.start()
with declared build config field to prevent it initialization.
@Override
public void onCreate() {
if (BuildConfig.USE_CRASHLYTICS) {
Crashlytics.start(this);
}
}
We may want to keep your apiKey
and apiSecret
private without sharing it within git repository. But we still need this values to be able to run build from CI or other team members machines. Same technique is used here as when we hiding signingConfig keys from repository by providing it with project properties.
app/build.gradle
afterEvaluate {
initCrashlyticsPropertiesIfNeeded()
}
def initCrashlyticsPropertiesIfNeeded() {
def propertiesFile = file('crashlytics.properties')
if (!propertiesFile.exists()) {
def commentMessage = "This is autogenerated crashlytics property from system environment to prevent key to be committed to source control."
ant.propertyfile(file: "crashlytics.properties", comment: commentMessage) {
entry(key: "apiSecret", value: crashlyticsdemoApisecret)
entry(key: "apiKey", value: crashlyticsdemoApikey)
}
}
}
Additional task is added which autogenerates crashlytics.properties
file with crashlyticsdemoApisecret
and crashlyticsdemoApikey
project properties. With gradle it is really convenient to set project properties:
- First of all we can hardcode the properties in the script itself.
crashlyticsdemoApikey=cc238b2a4866c96030
- Or use the -P command-line argument to pass a property to the build script.
gradlew assemble -PcrashlyticsdemoApikey=cc238b2a4866c96030
- Or define a
gradle.properties
file and set the property in this file. We can place the file in our project directory or in the<USER_HOME>/.gradle directory
. The properties defined in the property file in our home directory take precedence over the properties defined in the file in our project directory.
gradle.properties or ~/.gradle/gradle.properties
crashlyticsdemoApisecret=0cf7c9df6d057e7bb62b1427ab364e8115a75fcf7430873b6274bb094d1a8adb
crashlyticsdemoApikey=cc238b2a4866c96030
- Or use an environment variable of which the name starts with
ORG_GRADLE_PROJECT_
followed by the property name.
export ORG_GRADLE_PROJECT_crashlyticsdemoApikey=cc238b2a4866c96030
- Or use the Java system property that starts with
org.gradle.project.
followed by the property name.
java -Dorg.gradle.project.crashlyticsdemoApikey="cc238b2a4866c96030"
We can override Crashlytics source sets when default source folder structure is overrided with gradle so Crashlytics gradle plugin knows where to place autogenerated files. It is useful for projects compatible with Eclipse.
app/build.gradle
crashlytics.manifestPath = "relative/path/to/manifest"
crashlytics.resPath = "relative/path/to/res"
crashlytics.assetsPath = "relative/path/to/assets"