package com.bugsnag.android; import android.annotation.SuppressLint; import android.content.Context; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.List; import java.util.Map; import java.util.Set; /** * Static access to a Bugsnag Client, the easiest way to use Bugsnag in your Android app. * For example: *
* Bugsnag.start(this, "your-api-key");
* Bugsnag.notify(new RuntimeException("something broke!"));
*
* @see Client
*/
@SuppressWarnings("checkstyle:JavadocTagContinuationIndentation")
public final class Bugsnag {
private static final Object lock = new Object();
@SuppressLint("StaticFieldLeak")
static Client client;
private Bugsnag() {
}
/**
* Initialize the static Bugsnag client
*
* @param androidContext an Android context, usually this
*/
@NonNull
public static Client start(@NonNull Context androidContext) {
return start(androidContext, Configuration.load(androidContext));
}
/**
* Initialize the static Bugsnag client
*
* @param androidContext an Android context, usually this
* @param apiKey your Bugsnag API key from your Bugsnag dashboard
*/
@NonNull
public static Client start(@NonNull Context androidContext, @NonNull String apiKey) {
return start(androidContext, Configuration.load(androidContext, apiKey));
}
/**
* Initialize the static Bugsnag client
*
* @param androidContext an Android context, usually this
* @param config a configuration for the Client
*/
@NonNull
public static Client start(@NonNull Context androidContext, @NonNull Configuration config) {
synchronized (lock) {
if (client == null) {
client = new Client(androidContext, config);
} else {
logClientInitWarning();
}
}
return client;
}
/**
* Returns true if one of the start
methods have been has been called and
* so Bugsnag is initialized; false if start
has not been called and the
* other methods will throw IllegalStateException.
*/
public static boolean isStarted() {
return client != null;
}
private static void logClientInitWarning() {
getClient().logger.w("Multiple Bugsnag.start calls detected. Ignoring.");
}
/**
* Bugsnag uses the concept of "contexts" to help display and group your errors. Contexts
* represent what was happening in your application at the time an error occurs.
*
* In an android app the "context" is automatically set as the foreground Activity. * If you would like to set this value manually, you should alter this property. */ @Nullable public static String getContext() { return getClient().getContext(); } /** * Bugsnag uses the concept of "contexts" to help display and group your errors. Contexts * represent what was happening in your application at the time an error occurs. *
* In an android app the "context" is automatically set as the foreground Activity. * If you would like to set this value manually, you should alter this property. */ public static void setContext(@Nullable final String context) { getClient().setContext(context); } /** * Sets the user associated with the event. */ public static void setUser(@Nullable final String id, @Nullable final String email, @Nullable final String name) { getClient().setUser(id, email, name); } /** * Returns the currently set User information. */ @NonNull public static User getUser() { return getClient().getUser(); } /** * Add a "on error" callback, to execute code at the point where an error report is * captured in Bugsnag. *
* You can use this to add or modify information attached to an Event
* before it is sent to your dashboard. You can also return
* false
from any callback to prevent delivery. "on error"
* callbacks do not run before reports generated in the event
* of immediate app termination from crashes in C/C++ code.
*
* For example: *
* Bugsnag.addOnError(new OnErrorCallback() { * public boolean run(Event event) { * event.setSeverity(Severity.INFO); * return true; * } * }) * * @param onError a callback to run before sending errors to Bugsnag * @see OnErrorCallback */ public static void addOnError(@NonNull OnErrorCallback onError) { getClient().addOnError(onError); } /** * Removes a previously added "on error" callback * * @param onError the callback to remove */ public static void removeOnError(@NonNull OnErrorCallback onError) { getClient().removeOnError(onError); } /** * Add an "on breadcrumb" callback, to execute code before every * breadcrumb captured by Bugsnag. *
* You can use this to modify breadcrumbs before they are stored by Bugsnag.
* You can also return false
from any callback to ignore a breadcrumb.
*
* For example: *
* Bugsnag.onBreadcrumb(new OnBreadcrumbCallback() { * public boolean run(Breadcrumb breadcrumb) { * return false; // ignore the breadcrumb * } * }) * * @param onBreadcrumb a callback to run before a breadcrumb is captured * @see OnBreadcrumbCallback */ public static void addOnBreadcrumb(@NonNull final OnBreadcrumbCallback onBreadcrumb) { getClient().addOnBreadcrumb(onBreadcrumb); } /** * Removes a previously added "on breadcrumb" callback * * @param onBreadcrumb the callback to remove */ public static void removeOnBreadcrumb(@NonNull OnBreadcrumbCallback onBreadcrumb) { getClient().removeOnBreadcrumb(onBreadcrumb); } /** * Add an "on session" callback, to execute code before every * session captured by Bugsnag. *
* You can use this to modify sessions before they are stored by Bugsnag.
* You can also return false
from any callback to ignore a session.
*
* For example: *
* Bugsnag.onSession(new OnSessionCallback() {
* public boolean run(Session session) {
* return false; // ignore the session
* }
* })
*
* @param onSession a callback to run before a session is captured
* @see OnSessionCallback
*/
public static void addOnSession(@NonNull OnSessionCallback onSession) {
getClient().addOnSession(onSession);
}
/**
* Removes a previously added "on session" callback
*
* @param onSession the callback to remove
*/
public static void removeOnSession(@NonNull OnSessionCallback onSession) {
getClient().removeOnSession(onSession);
}
/**
* Notify Bugsnag of a handled exception
*
* @param exception the exception to send to Bugsnag
*/
public static void notify(@NonNull final Throwable exception) {
getClient().notify(exception);
}
/**
* Notify Bugsnag of a handled exception
*
* @param exception the exception to send to Bugsnag
* @param onError callback invoked on the generated error report for
* additional modification
*/
public static void notify(@NonNull final Throwable exception,
@Nullable final OnErrorCallback onError) {
getClient().notify(exception, onError);
}
/**
* Adds a map of multiple metadata key-value pairs to the specified section.
*/
public static void addMetadata(@NonNull String section, @NonNull Map
* The returned collection is readonly and mutating the list will cause no effect on the
* Client's state. If you wish to alter the breadcrumbs collected by the Client then you should
* use {@link Configuration#setEnabledBreadcrumbTypes(Set)} and
* {@link Configuration#addOnBreadcrumb(OnBreadcrumbCallback)} instead.
*
* @return a list of collected breadcrumbs
*/
@NonNull
public static List
* For example, this allows checking whether the app crashed on its last launch, which could
* be used to perform conditional behaviour to recover from crashes, such as clearing the
* app data cache.
*/
@Nullable
public static LastRunInfo getLastRunInfo() {
return getClient().getLastRunInfo();
}
/**
* Informs Bugsnag that the application has finished launching. Once this has been called
* {@link AppWithState#isLaunching()} will always be false in any new error reports,
* and synchronous delivery will not be attempted on the next launch for any fatal crashes.
*
* By default this method will be called after Bugsnag is initialized when
* {@link Configuration#getLaunchDurationMillis()} has elapsed. Invoking this method manually
* has precedence over the value supplied via the launchDurationMillis configuration option.
*/
public static void markLaunchCompleted() {
getClient().markLaunchCompleted();
}
/**
* Add a single feature flag with no variant. If there is an existing feature flag with the
* same name, it will be overwritten to have no variant.
*
* @param name the name of the feature flag to add
* @see #addFeatureFlag(String, String)
*/
public static void addFeatureFlag(@NonNull String name) {
getClient().addFeatureFlag(name);
}
/**
* Add a single feature flag with an optional variant. If there is an existing feature
* flag with the same name, it will be overwritten with the new variant. If the variant is
* {@code null} this method has the same behaviour as {@link #addFeatureFlag(String)}.
*
* @param name the name of the feature flag to add
* @param variant the variant to set the feature flag to, or {@code null} to specify a feature
* flag with no variant
*/
public static void addFeatureFlag(@NonNull String name, @Nullable String variant) {
getClient().addFeatureFlag(name, variant);
}
/**
* Add a collection of feature flags. This method behaves exactly the same as calling
* {@link #addFeatureFlag(String, String)} for each of the {@code FeatureFlag} objects.
*
* @param featureFlags the feature flags to add
* @see #addFeatureFlag(String, String)
*/
public static void addFeatureFlags(@NonNull Iterable