package com.bugsnag.android; import android.support.annotation.NonNull; import java.util.Arrays; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Observable; import java.util.Observer; /** * User-specified configuration storage object, contains information * specified at the client level, api-key and endpoint configuration. */ public class Configuration extends Observable implements Observer { static final String DEFAULT_ENDPOINT = "https://notify.bugsnag.com"; private final String apiKey; private String buildUUID; private String appVersion; private String context; private String endpoint = DEFAULT_ENDPOINT; private String[] filters = new String[]{"password"}; private String[] ignoreClasses; private String[] notifyReleaseStages = null; private String[] projectPackages; private String releaseStage; private boolean sendThreads = true; private boolean enableExceptionHandler = true; private boolean persistUserBetweenSessions = false; String defaultExceptionType = "android"; private MetaData metaData; private final Collection<BeforeNotify> beforeNotifyTasks = new LinkedList<BeforeNotify>(); /** * Construct a new Bugsnag configuration object * * @param apiKey The API key to send reports to */ public Configuration(@NonNull String apiKey) { this.apiKey = apiKey; this.metaData = new MetaData(); this.metaData.addObserver(this); } /** * Gets the API key to send reports to * * @return API key */ public String getApiKey() { return apiKey; } /** * Gets the application version sent to Bugsnag. * * @return App Version */ public String getAppVersion() { return appVersion; } /** * Set the application version sent to Bugsnag. By default we'll pull this * from your AndroidManifest.xml * * @param appVersion the app version to send */ public void setAppVersion(String appVersion) { this.appVersion = appVersion; notifyBugsnagObservers(NotifyType.APP); } /** * Gets the context to be sent to Bugsnag. * * @return Context */ public String getContext() { return context; } /** * Set the context sent to Bugsnag. By default we'll attempt to detect the * name of the top-most activity at the time of a report, and use this * as the context, but sometime this is not possible. * * @param context set what was happening at the time of a crash */ public void setContext(String context) { this.context = context; notifyBugsnagObservers(NotifyType.CONTEXT); } /** * Get the endpoint to send data * * @return Endpoint */ public String getEndpoint() { return endpoint; } /** * Set the endpoint to send data to. By default we'll send reports to * the standard https://notify.bugsnag.com endpoint, but you can override * this if you are using Bugsnag Enterprise to point to your own Bugsnag * endpoint. * * @param endpoint the custom endpoint to send report to */ public void setEndpoint(String endpoint) { this.endpoint = endpoint; } /** * Get the buildUUID. * * @return build UUID */ public String getBuildUUID() { return buildUUID; } /** * Set the buildUUID to your own value. This is used to identify proguard * mapping files in the case that you publish multiple different apps with * the same appId and versionCode. The default value is read from the * com.bugsnag.android.BUILD_UUID meta-data field in your app manifest. * * @param buildUUID the buildUUID. */ public void setBuildUUID(String buildUUID) { this.buildUUID = buildUUID; notifyBugsnagObservers(NotifyType.APP); } /** * Get which keys should be filtered when sending metaData to Bugsnag * * @return Filters */ public String[] getFilters() { return filters; } /** * Set which keys should be filtered when sending metaData to Bugsnag. * Use this when you want to ensure sensitive information, such as passwords * or credit card information is stripped from metaData you send to Bugsnag. * Any keys in metaData which contain these strings will be marked as * [FILTERED] when send to Bugsnag. * <p/> * For example: * <p/> * client.setFilters("password", "credit_card"); * * @param filters a list of keys to filter from metaData */ public void setFilters(String[] filters) { this.filters = filters; this.metaData.setFilters(filters); } /** * Get which exception classes should be ignored (not sent) by Bugsnag. * * @return Ignore classes */ public String[] getIgnoreClasses() { return ignoreClasses; } /** * Set which exception classes should be ignored (not sent) by Bugsnag. * <p/> * For example: * <p/> * client.setIgnoreClasses("java.lang.RuntimeException"); * * @param ignoreClasses a list of exception classes to ignore */ public void setIgnoreClasses(String[] ignoreClasses) { this.ignoreClasses = ignoreClasses; } /** * Get for which releaseStages errors should be sent to Bugsnag. * * @return Notify release stages */ public String[] getNotifyReleaseStages() { return notifyReleaseStages; } /** * Set for which releaseStages errors should be sent to Bugsnag. * Use this to stop errors from development builds being sent. * <p/> * For example: * <p/> * client.setNotifyReleaseStages("production"); * * @param notifyReleaseStages a list of releaseStages to notify for * @see #setReleaseStage */ public void setNotifyReleaseStages(String[] notifyReleaseStages) { this.notifyReleaseStages = notifyReleaseStages; notifyBugsnagObservers(NotifyType.RELEASE_STAGES); } /** * Get which packages should be considered part of your application. * * @return packages */ public String[] getProjectPackages() { return projectPackages; } /** * Set which packages should be considered part of your application. * Bugsnag uses this to help with error grouping, and stacktrace display. * <p/> * For example: * <p/> * client.setProjectPackages("com.example.myapp"); * <p/> * By default, we'll mark the current package name as part of you app. * * @param projectPackages a list of package names */ public void setProjectPackages(String[] projectPackages) { this.projectPackages = projectPackages; } /** * Get the current "release stage" of your application. * * @return release stage */ public String getReleaseStage() { return releaseStage; } /** * Set the current "release stage" of your application. * By default, we'll set this to "development" for debug builds and * "production" for non-debug builds. * * @param releaseStage the release stage of the app * @see #setNotifyReleaseStages */ public void setReleaseStage(String releaseStage) { this.releaseStage = releaseStage; notifyBugsnagObservers(NotifyType.APP); } /** * Get whether to send thread-state with report. * * @return send threads */ public boolean getSendThreads() { return sendThreads; } /** * Set whether to send thread-state with report. * By default, this will be true. * * @param sendThreads should we send thread-state with report? */ public void setSendThreads(boolean sendThreads) { this.sendThreads = sendThreads; } /** * Get whether or not Bugsnag should automatically handle uncaught exceptions * * @return should Bugsnag automatically handle uncaught exceptions */ public boolean getEnableExceptionHandler() { return enableExceptionHandler; } /** * Set whether or not Bugsnag should automatically handle uncaught exceptions * * @param enableExceptionHandler should Bugsnag automatically handle uncaught exceptions */ public void setEnableExceptionHandler(boolean enableExceptionHandler) { this.enableExceptionHandler = enableExceptionHandler; } /* * Gets any meta data associated with the error * * @return meta data */ protected MetaData getMetaData() { return metaData; } /** * Sets any meta data associated with the error * * @param metaData meta data */ protected void setMetaData(MetaData metaData) { this.metaData.deleteObserver(this); this.metaData = metaData; this.metaData.addObserver(this); notifyBugsnagObservers(NotifyType.META); } /** * Gets any before notify tasks to run * * @return the before notify tasks */ protected Collection<BeforeNotify> getBeforeNotifyTasks() { return beforeNotifyTasks; } /** * Get whether or not Bugsnag should persist user information between application settings * * @return whether or not Bugsnag should persist user information */ public boolean getPersistUserBetweenSessions() { return persistUserBetweenSessions; } /** * Set whether or not Bugsnag should persist user information between application settings * if set then any user information set will be re-used until * @see Client#clearUser() is called * * @param persistUserBetweenSessions whether or not Bugsnag should persist user information */ public void setPersistUserBetweenSessions(boolean persistUserBetweenSessions) { this.persistUserBetweenSessions = persistUserBetweenSessions; } /** * Checks if the given release stage should be notified or not * * @param releaseStage the release stage to check * @return true if the release state should be notified else false */ protected boolean shouldNotifyForReleaseStage(String releaseStage) { if(this.notifyReleaseStages == null) return true; List<String> stages = Arrays.asList(this.notifyReleaseStages); return stages.contains(releaseStage); } /** * Checks if the given exception class should be ignored or not * * @param className the exception class to check * @return true if the exception class should be ignored else false */ protected boolean shouldIgnoreClass(String className) { if(this.ignoreClasses == null) return false; List<String> classes = Arrays.asList(this.ignoreClasses); return classes.contains(className); } /** * Adds a new before notify task * * @param beforeNotify the new before notify task */ protected void beforeNotify(BeforeNotify beforeNotify) { this.beforeNotifyTasks.add(beforeNotify); } /** * Checks if the given class name should be marked as in the project or not * * @param className the class to check * @return true if the class should be considered in the project else false */ protected boolean inProject(String className) { if(projectPackages != null) { for(String packageName : projectPackages) { if(packageName != null && className.startsWith(packageName)) { return true; } } } return false; } private void notifyBugsnagObservers(NotifyType type) { setChanged(); super.notifyObservers(type.getValue()); } @Override public void update(Observable o, Object arg) { if (arg instanceof Integer) { NotifyType type = NotifyType.fromInt((Integer) arg); if (type != null) { notifyBugsnagObservers(type); } } } }