Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mobiRic
Created September 5, 2018 07:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mobiRic/5dffbac906749028da40c090a759adc5 to your computer and use it in GitHub Desktop.
Save mobiRic/5dffbac906749028da40c090a759adc5 to your computer and use it in GitHub Desktop.
Basic wrapper for Crashlytics
package mobi.glowworm.lib.utils.debug;
import android.content.Context;
import android.support.annotation.NonNull;
import com.crashlytics.android.Crashlytics;
import io.fabric.sdk.android.Fabric;
/**
* Singleton wrapper for {@link Crashlytics}.
* <p>
* Implementation has been modelled on Crashlytics.
*/
// TODO generalise the initialisation process to allow for different implementations
// TODO introduce logging
@SuppressWarnings("unused")
public class CrashLog {
private static final String TAG = CrashLog.class.getSimpleName();
private static volatile CrashLog INSTANCE = null;
/**
* Initialises the singleton copy of the {@link CrashLog} with
* the default .
* <p>
* This must be called before {@link CrashLog} can be used.
* If this method is not called before trying to use {@link CrashLog},
* then any method called will throw an {@link IllegalStateException}.
* <p>
* Subsequent calls to this method will do nothing.
*
* @param context context to send to Crashlytics
*/
public static void init(@NonNull Context context) {
if (INSTANCE == null) {
synchronized (TAG) {
if (INSTANCE == null) {
INSTANCE = new CrashLog(context);
}
}
}
}
/**
* Asserts that {@link CrashLog} has been correctly initialised.
*
* @throws IllegalStateException if {@link CrashLog} has not been initialised before use.
*/
private static void assertInit() throws IllegalStateException {
if (INSTANCE == null) {
throw new IllegalStateException("CrashLog needs to be initialised before use.");
}
}
/**
* Confirms that {@link CrashLog} has been correctly initialised,
* and returns the instance for use.
*
* @return {@link CrashLog#INSTANCE}
*/
@NonNull
private static CrashLog getInstance() {
assertInit();
return INSTANCE;
}
public static void logException(Throwable throwable) {
getInstance().core.logException(throwable);
}
public static void log(String msg) {
getInstance().core.log(msg);
}
public static void log(int priority, String tag, String msg) {
getInstance().core.log(priority, tag, msg);
}
public static void setUserIdentifier(String identifier) {
getInstance().core.setUserIdentifier(identifier);
}
public static void setUserName(String name) {
getInstance().core.setUserName(name);
}
public static void setUserEmail(String email) {
getInstance().core.setUserEmail(email);
}
public static void setString(String key, String value) {
getInstance().core.setString(key, value);
}
public static void setBool(String key, boolean value) {
getInstance().core.setBool(key, value);
}
public static void setDouble(String key, double value) {
getInstance().core.setDouble(key, value);
}
public static void setFloat(String key, float value) {
getInstance().core.setFloat(key, value);
}
public static void setInt(String key, int value) {
getInstance().core.setInt(key, value);
}
public static void setLong(String key, long value) {
getInstance().core.setLong(key, value);
}
// TODO allow different implementations for e.g. logging only, or different crash frameworks
private CrashLogImpl core;
private CrashLog(Context context) {
if (BuildConfig.CRASHLYTICS) {
Fabric.with(context.getApplicationContext(), new Crashlytics());
}
core = new DefaultImpl();
}
/**
* Default implementation of the {@link CrashLogImpl}
* that is used by {@link CrashLog}.
*/
private class DefaultImpl implements CrashLogImpl {
@Override
public void logException(Throwable throwable) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.logException(throwable);
}
}
@Override
public void log(String msg) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.log(msg);
}
}
@Override
public void log(int priority, String tag, String msg) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.log(priority, tag, msg);
}
}
@Override
public void setUserIdentifier(String identifier) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setUserIdentifier(identifier);
}
}
@Override
public void setUserName(String name) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setUserName(name);
}
}
@Override
public void setUserEmail(String email) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setUserEmail(email);
}
}
@Override
public void setString(String key, String value) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setString(key, value);
}
}
@Override
public void setBool(String key, boolean value) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setBool(key, value);
}
}
@Override
public void setDouble(String key, double value) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setDouble(key, value);
}
}
@Override
public void setFloat(String key, float value) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setFloat(key, value);
}
}
@Override
public void setInt(String key, int value) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setInt(key, value);
}
}
@Override
public void setLong(String key, long value) {
if (BuildConfig.CRASHLYTICS) {
Crashlytics.setLong(key, value);
}
}
}
/**
* Interface defining what calls to {@link Crashlytics} have been
* wrapped by {@link CrashLog}.
* <p>
* Future versions can use this to create a No-Op stub version
* of {@link CrashLog} to be used on development builds.
*/
private interface CrashLogImpl {
void logException(Throwable throwable);
void log(String msg);
void log(int priority, String tag, String msg);
void setUserIdentifier(String identifier);
void setUserName(String name);
void setUserEmail(String email);
void setString(String key, String value);
void setBool(String key, boolean value);
void setDouble(String key, double value);
void setFloat(String key, float value);
void setInt(String key, int value);
void setLong(String key, long value);
}
}
@mobiRic
Copy link
Author

mobiRic commented Sep 5, 2018

First version of a clean-room rewrite of a Crashlytics wrapper that I used in Mr D Food app. This was done for the MoboTour project.

This implementation requires a BuildConfig.CRASHLYTICS flag to be declared in the build.gradle file, and imported into this CrashLog:

// allow Crashlytics configuration based on build type - disable this in debug builds
buildConfigField("boolean", "CRASHLYTICS", "true")

Future Plans:

  1. create a no-operation/stub version that can be used by default in debug builds
  2. generalise for different crash reporting frameworks
  3. update build files so that Crashlytics/Fabric are not required in builds that don't use them
  4. generalise this wrapper for other analytics

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