diff --git a/CHANGELOG.md b/CHANGELOG.md index f734a77f74..a56bb71e1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,32 @@ # Changelog -## 4.X.X (TBD) +## 4.10.0 (2019-01-07) + +* Improve kotlin support by allowing property access + [#393](https://github.com/bugsnag/bugsnag-android/pull/393) + +* Added additional nullability annotations to public API + [#395](https://github.com/bugsnag/bugsnag-android/pull/395) + +* Migrate metaData.device.cpuAbi to device.cpuAbi in JSON payload + [#404](https://github.com/bugsnag/bugsnag-android/pull/404) ### Bug fixes -* Make config.metadata publicly accessible - [#406](https://github.com/bugsnag/bugsnag-android/pull/406) +* Add binary architecture of application to payload + [#389](https://github.com/bugsnag/bugsnag-android/pull/389) * Prevent errors from leaving a self-referencing breadcrumb [#391](https://github.com/bugsnag/bugsnag-android/pull/391) +* Fix calculation of durationInForeground when autoCaptureSessions is false + [#394](https://github.com/bugsnag/bugsnag-android/pull/394) + * Prevent Bugsnag.init from instantiating more than one client [#403](https://github.com/bugsnag/bugsnag-android/pull/403) +* Make config.metadata publicly accessible + [#406](https://github.com/bugsnag/bugsnag-android/pull/406) ## 4.9.3 (2018-11-29) diff --git a/README.md b/README.md index b8912bc74a..af6ece3399 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build status](https://travis-ci.org/bugsnag/bugsnag-android.svg?branch=master)](https://travis-ci.org/bugsnag/bugsnag-android) [![Coverage Status](https://coveralls.io/repos/github/bugsnag/bugsnag-android/badge.svg?branch=master)](https://coveralls.io/github/bugsnag/bugsnag-android?branch=master) -![Method count and size](https://img.shields.io/badge/Methods%20and%20size-88%20classes%20|%20666%20methods%20|%20348%20fields%20|%20128%20KB-e91e63.svg) +![Method count and size](https://img.shields.io/badge/Methods%20and%20size-88%20classes%20|%20678%20methods%20|%20350%20fields%20|%20132%20KB-e91e63.svg) Get comprehensive [Android crash reports](https://www.bugsnag.com/platforms/android/) to quickly debug errors. diff --git a/build.gradle b/build.gradle index 141730e42b..64fe14bc10 100644 --- a/build.gradle +++ b/build.gradle @@ -4,10 +4,11 @@ buildscript { mavenCentral() jcenter() } - ext.kotlin_version = '1.2.30' + ext.kotlin_version = '1.3.10' + ext.agpVersion = "3.2.1" dependencies { - classpath 'com.android.tools.build:gradle:3.1.4' + classpath "com.android.tools.build:gradle:$agpVersion" classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.8.2' diff --git a/examples/sdk-app-example/build.gradle b/examples/sdk-app-example/build.gradle index 7ea1febf53..6fa915b448 100644 --- a/examples/sdk-app-example/build.gradle +++ b/examples/sdk-app-example/build.gradle @@ -5,9 +5,9 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' + classpath "com.android.tools.build:gradle:$agpVersion" classpath 'com.bugsnag:bugsnag-android-gradle-plugin:3.4.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.30" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -80,7 +80,7 @@ dependencies { // api project(path: ':ndk', configuration: 'default') implementation 'com.android.support:appcompat-v7:27.0.0' implementation 'com.android.support:support-v4:27.0.0' - kotlinExampleImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.30" + kotlinExampleImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" androidTestImplementation "com.android.support.test:runner:0.5", { exclude group: 'com.android.support', module: 'support-annotations' } diff --git a/features/fixtures/mazerunner/build.gradle b/features/fixtures/mazerunner/build.gradle index 66228262e9..f984f640a7 100644 --- a/features/fixtures/mazerunner/build.gradle +++ b/features/fixtures/mazerunner/build.gradle @@ -14,7 +14,7 @@ buildscript { mavenCentral() jcenter() } - ext.kotlin_version = '1.2.30' + ext.kotlin_version = '1.3.10' dependencies { classpath 'com.android.tools.build:gradle:3.0.1' @@ -68,7 +68,7 @@ android { dependencies { implementation(name:'bugsnag-android', ext:'aar') implementation(name:'bugsnag-android-ndk', ext:'aar') - implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.21" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "com.facebook.infer.annotation:infer-annotation:0.11.2" api "com.android.support:support-annotations:27.0.0" } diff --git a/features/fixtures/mazerunner/src/main/java/com/bugsnag/android/TestHarnessHooks.kt b/features/fixtures/mazerunner/src/main/java/com/bugsnag/android/TestHarnessHooks.kt index 98bea56795..fa6666ba5c 100644 --- a/features/fixtures/mazerunner/src/main/java/com/bugsnag/android/TestHarnessHooks.kt +++ b/features/fixtures/mazerunner/src/main/java/com/bugsnag/android/TestHarnessHooks.kt @@ -26,12 +26,12 @@ internal fun createSlowDelivery(context: Context): Delivery { val delivery = DefaultDelivery(cm) return object : Delivery { - override fun deliver(payload: SessionTrackingPayload?, config: Configuration?) { + override fun deliver(payload: SessionTrackingPayload, config: Configuration) { Thread.sleep(500) delivery.deliver(payload, config) } - override fun deliver(report: Report?, config: Configuration?) { + override fun deliver(report: Report, config: Configuration) { Thread.sleep(500) delivery.deliver(report, config) } @@ -47,18 +47,18 @@ internal fun createCustomHeaderDelivery(context: Context): Delivery { return object : Delivery { val delivery: DefaultDelivery = createDefaultDelivery(context) - override fun deliver(payload: SessionTrackingPayload?, config: Configuration?) { - deliver(config?.sessionEndpoint, payload, config?.sessionApiHeaders) + override fun deliver(payload: SessionTrackingPayload, config: Configuration) { + deliver(config.sessionEndpoint, payload, config.sessionApiHeaders) } - override fun deliver(report: Report?, config: Configuration?) { - deliver(config?.endpoint, report, config?.errorApiHeaders) + override fun deliver(report: Report, config: Configuration) { + deliver(config.endpoint, report, config.errorApiHeaders) } - fun deliver(endpoint: String?, - streamable: JsonStream.Streamable?, - headers: MutableMap?) { - headers!!["Custom-Client"] = "Hello World" + fun deliver(endpoint: String, + streamable: JsonStream.Streamable, + headers: MutableMap) { + headers["Custom-Client"] = "Hello World" delivery.deliver(endpoint, streamable, headers) } } diff --git a/features/fixtures/mazerunner/src/main/java/com/bugsnag/android/mazerunner/scenarios/Scenario.kt b/features/fixtures/mazerunner/src/main/java/com/bugsnag/android/mazerunner/scenarios/Scenario.kt index 7e962d13a2..a7e132df87 100644 --- a/features/fixtures/mazerunner/src/main/java/com/bugsnag/android/mazerunner/scenarios/Scenario.kt +++ b/features/fixtures/mazerunner/src/main/java/com/bugsnag/android/mazerunner/scenarios/Scenario.kt @@ -18,11 +18,11 @@ abstract internal class Scenario(protected val config: Configuration, protected fun disableSessionDelivery() { val baseDelivery = Bugsnag.getClient().config.delivery Bugsnag.getClient().config.delivery = object: Delivery { - override fun deliver(payload: SessionTrackingPayload?, config: Configuration?) { + override fun deliver(payload: SessionTrackingPayload, config: Configuration) { throw DeliveryFailureException("Session Delivery NOP", RuntimeException("NOP")) } - override fun deliver(report: Report?, config: Configuration?) { + override fun deliver(report: Report, config: Configuration) { baseDelivery.deliver(report, config) } } @@ -34,11 +34,11 @@ abstract internal class Scenario(protected val config: Configuration, protected fun disableReportDelivery() { val baseDelivery = Bugsnag.getClient().config.delivery Bugsnag.getClient().config.delivery = object: Delivery { - override fun deliver(payload: SessionTrackingPayload?, config: Configuration?) { + override fun deliver(payload: SessionTrackingPayload, config: Configuration) { baseDelivery.deliver(payload, config) } - override fun deliver(report: Report?, config: Configuration?) { + override fun deliver(report: Report, config: Configuration) { throw DeliveryFailureException("Session Delivery NOP", RuntimeException("NOP")) } } @@ -57,11 +57,11 @@ abstract internal class Scenario(protected val config: Configuration, protected fun disableAllDelivery(config: Configuration) { config.delivery = object: Delivery { - override fun deliver(payload: SessionTrackingPayload?, config: Configuration?) { + override fun deliver(payload: SessionTrackingPayload, config: Configuration) { throw DeliveryFailureException("Error Delivery NOP", RuntimeException("NOP")) } - override fun deliver(report: Report?, config: Configuration?) { + override fun deliver(report: Report, config: Configuration) { throw DeliveryFailureException("Session Delivery NOP", RuntimeException("NOP")) } } diff --git a/features/handled_exception.feature b/features/handled_exception.feature index 1941258a3d..0770b04521 100644 --- a/features/handled_exception.feature +++ b/features/handled_exception.feature @@ -9,6 +9,7 @@ Scenario: Test handled Kotlin Exception And the payload field "events" is an array with 1 element And the exception "errorClass" equals "java.lang.RuntimeException" And the exception "message" equals "HandledExceptionScenario" + And the payload field "events.0.device.cpuAbi" is a non-empty array for request 0 Scenario: Test handled Java Exception When I run "HandledExceptionJavaScenario" diff --git a/features/native_api.feature b/features/native_api.feature index 19f861317d..559e552a50 100644 --- a/features/native_api.feature +++ b/features/native_api.feature @@ -12,6 +12,8 @@ Feature: Native API And the event "user.id" equals "324523" And the event "user.email" is null And the event "unhandled" is false + And the event "app.binaryArch" is not null + And the payload field "events.0.device.cpuAbi" is a non-empty array for request 0 Scenario: Adding user information in Java followed by a C crash When I run "CXXJavaUserInfoNativeCrashScenario" diff --git a/features/native_crash_handling.feature b/features/native_crash_handling.feature index 13c3357ecb..264707fe16 100644 --- a/features/native_crash_handling.feature +++ b/features/native_crash_handling.feature @@ -11,6 +11,8 @@ Feature: Native crash reporting And the exception "type" equals "c" And the event "severity" equals "error" And the event "unhandled" is true + And the event "app.binaryArch" is not null + And the payload field "events.0.device.cpuAbi" is a non-empty array for request 0 # This scenario will not pass on API levels < 18, as stack corruption # is handled without calling atexit handlers, etc. diff --git a/features/steps/build_steps.rb b/features/steps/build_steps.rb index 860ab6f7f7..6be02820c3 100644 --- a/features/steps/build_steps.rb +++ b/features/steps/build_steps.rb @@ -139,7 +139,7 @@ And the payload field "events.0.metaData.device.time" is not null for request #{index} And the payload field "events.0.severity" is not null for request #{index} And the payload field "events.0.severityReason.type" is not null for request #{index} - And the payload field "events.0.metaData.device.cpuAbi" is a non-empty array for request #{index} + And the payload field "events.0.device.cpuAbi" is a non-empty array for request #{index} } end diff --git a/features/unhandled_exception.feature b/features/unhandled_exception.feature index 16f78bbb24..865cd94996 100644 --- a/features/unhandled_exception.feature +++ b/features/unhandled_exception.feature @@ -10,6 +10,7 @@ Scenario: Test Unhandled Kotlin Exception without Session And the exception "errorClass" equals "java.lang.RuntimeException" And the exception "message" equals "UnhandledExceptionScenario" And the event "session" is null + And the payload field "events.0.device.cpuAbi" is a non-empty array for request 0 Scenario: Test Unhandled Java Exception with Session When I run "UnhandledExceptionJavaScenario" diff --git a/gradle.properties b/gradle.properties index d11a1ac47b..2a6e0cff03 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ org.gradle.jvmargs=-Xmx1536m # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME=4.9.3 +VERSION_NAME=4.10.0 GROUP=com.bugsnag POM_SCM_URL=https://github.com/bugsnag/bugsnag-android POM_SCM_CONNECTION=scm:git@github.com:bugsnag/bugsnag-android.git diff --git a/ndk/src/main/jni/bugsnag.c b/ndk/src/main/jni/bugsnag.c index 2189b7c0c1..528bb7d8aa 100644 --- a/ndk/src/main/jni/bugsnag.c +++ b/ndk/src/main/jni/bugsnag.c @@ -3,6 +3,7 @@ #include "bugsnag_ndk.h" #include "report.h" #include "utils/stack_unwinder.h" +#include "metadata.h" #include #include #include @@ -10,6 +11,8 @@ static JNIEnv *bsg_global_jni_env = NULL; +void bugsnag_set_binary_arch(JNIEnv *env); + void bugsnag_init(JNIEnv *env) { bsg_global_jni_env = env; } void bugsnag_notify_env(JNIEnv *env, char *name, char *message, @@ -109,6 +112,9 @@ void bugsnag_notify_env(JNIEnv *env, char *name, char *message, jstring jname = (*env)->NewStringUTF(env, name); jstring jmessage = (*env)->NewStringUTF(env, message); + // set application's binary arch + bugsnag_set_binary_arch(env); + (*env)->CallStaticVoidMethod(env, interface_class, notify_method, jname, jmessage, jseverity, trace); @@ -119,6 +125,18 @@ void bugsnag_notify_env(JNIEnv *env, char *name, char *message, (*env)->DeleteLocalRef(env, interface_class); } +void bugsnag_set_binary_arch(JNIEnv *env) { + jclass interface_class = + (*env)->FindClass(env, "com/bugsnag/android/NativeInterface"); + jmethodID set_arch_method = (*env)->GetStaticMethodID( + env, interface_class, "setBinaryArch", "(Ljava/lang/String;)V"); + + jstring arch = (*env)->NewStringUTF(env, bsg_binary_arch()); + (*env)->CallStaticVoidMethod(env, interface_class, set_arch_method, arch); + (*env)->DeleteLocalRef(env, arch); + (*env)->DeleteLocalRef(env, interface_class); +} + void bugsnag_set_user_env(JNIEnv *env, char *id, char *email, char *name) { jclass interface_class = (*env)->FindClass(env, "com/bugsnag/android/NativeInterface"); diff --git a/ndk/src/main/jni/metadata.c b/ndk/src/main/jni/metadata.c index 5544df8156..7f4a1f80ef 100644 --- a/ndk/src/main/jni/metadata.c +++ b/ndk/src/main/jni/metadata.c @@ -199,6 +199,20 @@ void bsg_populate_crumb_metadata(JNIEnv *env, bugsnag_breadcrumb *crumb, (*env)->DeleteLocalRef(env, keylist); } +char *bsg_binary_arch() { +#if defined(__i386__) + return "x86"; +#elif defined(__x86_64__) + return "x86_64"; +#elif defined(__arm__) + return "arm32"; +#elif defined(__aarch64__) + return "arm64"; +#else + return "unknown"; +#endif +} + void bsg_populate_app_data(JNIEnv *env, bsg_jni_cache *jni_cache, bugsnag_report *report) { jobject data = (*env)->CallStaticObjectMethod( @@ -232,6 +246,9 @@ void bsg_populate_app_data(JNIEnv *env, bsg_jni_cache *jni_cache, report->app.in_foreground = bsg_get_map_value_bool(env, jni_cache, data, "inForeground"); + bsg_strncpy_safe(report->app.binaryArch, + bsg_binary_arch(), + sizeof(report->app.binaryArch)); (*env)->DeleteLocalRef(env, data); } diff --git a/ndk/src/main/jni/metadata.h b/ndk/src/main/jni/metadata.h index a8babb3810..afba21a0c7 100644 --- a/ndk/src/main/jni/metadata.h +++ b/ndk/src/main/jni/metadata.h @@ -19,4 +19,7 @@ void bsg_populate_metadata(JNIEnv *env, bugsnag_report *report, jobject metadata */ void bsg_populate_crumb_metadata(JNIEnv *env, bugsnag_breadcrumb *crumb, jobject metadata); + +char *bsg_binary_arch(); + #endif diff --git a/ndk/src/main/jni/report.h b/ndk/src/main/jni/report.h index 95b4426f91..879e9f3b0a 100644 --- a/ndk/src/main/jni/report.h +++ b/ndk/src/main/jni/report.h @@ -80,6 +80,7 @@ typedef struct { bool in_foreground; bool low_memory; size_t memory_usage; + char binaryArch[32]; } bsg_app_info; typedef struct { diff --git a/ndk/src/main/jni/utils/serializer.c b/ndk/src/main/jni/utils/serializer.c index 25cb37c352..f2a7bb48e7 100644 --- a/ndk/src/main/jni/utils/serializer.c +++ b/ndk/src/main/jni/utils/serializer.c @@ -158,6 +158,8 @@ char *bsg_serialize_report_to_json_string(bugsnag_report *report) { if (strlen(report->app.build_uuid) > 0) { json_object_dotset_string(event, "app.buildUUID", report->app.build_uuid); } + json_object_dotset_string(event, "app.binaryArch", + report->app.binaryArch); json_object_dotset_number(event, "app.duration", report->app.duration); json_object_dotset_number(event, "app.durationInForeground", report->app.duration_in_foreground); @@ -182,6 +184,14 @@ char *bsg_serialize_report_to_json_string(bugsnag_report *report) { json_object_dotset_string(event, "device.model", report->device.model); json_object_dotset_string(event, "device.orientation", report->device.orientation); + + JSON_Value *abi_val = json_value_init_array(); + JSON_Array *cpu_abis = json_value_get_array(abi_val); + json_object_dotset_value(event, "device.cpuAbi", abi_val); + for (int i = 0; i < report->device.cpu_abi_count; i++) { + json_array_append_string(cpu_abis, report->device.cpu_abi[i].value); + } + json_object_dotset_string(event, "metaData.device.osBuild", report->device.os_build); json_object_dotset_number(event, "device.totalMemory", @@ -212,12 +222,6 @@ char *bsg_serialize_report_to_json_string(bugsnag_report *report) { gmtime(&report->device.time)); json_object_dotset_string(event, "metaData.device.time", report_time); } - JSON_Value *abi_val = json_value_init_array(); - JSON_Array *cpu_abis = json_value_get_array(abi_val); - json_object_dotset_value(event, "metaData.device.cpuAbi", abi_val); - for (int i = 0; i < report->device.cpu_abi_count; i++) { - json_array_append_string(cpu_abis, report->device.cpu_abi[i].value); - } // Serialize custom metadata { diff --git a/sdk/build.gradle b/sdk/build.gradle index f2e85099ef..96389af83f 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -31,6 +31,7 @@ android { abortOnError true warningsAsErrors true checkAllWarnings true + baseline file("lint-baseline.xml") } // TODO replace with https://issuetracker.google.com/issues/72050365 once released. @@ -51,7 +52,7 @@ coveralls { dependencies { api "com.android.support:support-annotations:$supportLibVersion" - androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" testImplementation "junit:junit:$junitVersion" testImplementation "org.mockito:mockito-core:$mockitoVersion" diff --git a/sdk/lint-baseline.xml b/sdk/lint-baseline.xml new file mode 100644 index 0000000000..b51ce56bf2 --- /dev/null +++ b/sdk/lint-baseline.xml @@ -0,0 +1,4 @@ + + + + diff --git a/sdk/src/androidTest/java/com/bugsnag/android/ClientConfigTest.java b/sdk/src/androidTest/java/com/bugsnag/android/ClientConfigTest.java index db8692112d..461b69acfd 100644 --- a/sdk/src/androidTest/java/com/bugsnag/android/ClientConfigTest.java +++ b/sdk/src/androidTest/java/com/bugsnag/android/ClientConfigTest.java @@ -47,7 +47,7 @@ public void testSetReleaseStage() throws Exception { @Test public void testSetAutoCaptureSessions() throws Exception { client.setAutoCaptureSessions(true); - assertEquals(true, config.shouldAutoCaptureSessions()); + assertEquals(true, config.getAutoCaptureSessions()); } @Test diff --git a/sdk/src/androidTest/java/com/bugsnag/android/ClientTest.java b/sdk/src/androidTest/java/com/bugsnag/android/ClientTest.java index 53df93aaa3..54fdf436d0 100644 --- a/sdk/src/androidTest/java/com/bugsnag/android/ClientTest.java +++ b/sdk/src/androidTest/java/com/bugsnag/android/ClientTest.java @@ -218,7 +218,7 @@ public void testFullManifestConfig() { assertEquals(false, protoConfig.getSendThreads()); assertEquals(false, protoConfig.getEnableExceptionHandler()); assertEquals(true, protoConfig.getPersistUserBetweenSessions()); - assertEquals(true, protoConfig.shouldAutoCaptureSessions()); + assertEquals(true, protoConfig.getAutoCaptureSessions()); } @SuppressWarnings("deprecation") // test backwards compatibility of client.setMaxBreadcrumbs @@ -333,7 +333,7 @@ public void testPopulateDeviceMetadata() { Client client = generateClient(); Map metaData = client.getDeviceData().getDeviceMetaData(); - assertEquals(14, metaData.size()); + assertEquals(13, metaData.size()); assertNotNull(metaData.get("batteryLevel")); assertNotNull(metaData.get("charging")); assertNotNull(metaData.get("locationStatus")); @@ -347,6 +347,5 @@ public void testPopulateDeviceMetadata() { assertNotNull(metaData.get("dpi")); assertNotNull(metaData.get("emulator")); assertNotNull(metaData.get("screenResolution")); - assertNotNull(metaData.get("cpuAbi")); } } diff --git a/sdk/src/androidTest/java/com/bugsnag/android/ConfigurationTest.java b/sdk/src/androidTest/java/com/bugsnag/android/ConfigurationTest.java index b989c8a009..4f77d3cf9e 100644 --- a/sdk/src/androidTest/java/com/bugsnag/android/ConfigurationTest.java +++ b/sdk/src/androidTest/java/com/bugsnag/android/ConfigurationTest.java @@ -58,15 +58,15 @@ public void testEmptyNotifyEndpoint() { public void testInvalidSessionEndpoint() { //noinspection ConstantConditions config.setEndpoints("http://example.com", null); - assertFalse(config.shouldAutoCaptureSessions()); + assertFalse(config.getAutoCaptureSessions()); assertNull(config.getSessionEndpoint()); config.setEndpoints("http://example.com", ""); - assertFalse(config.shouldAutoCaptureSessions()); + assertFalse(config.getAutoCaptureSessions()); assertNull(config.getSessionEndpoint()); config.setEndpoints("http://example.com", "http://sessions.example.com"); - assertFalse(config.shouldAutoCaptureSessions()); + assertFalse(config.getAutoCaptureSessions()); assertEquals("http://sessions.example.com", config.getSessionEndpoint()); } @@ -74,7 +74,7 @@ public void testInvalidSessionEndpoint() { public void testAutoCaptureOverride() { config.setAutoCaptureSessions(false); config.setEndpoints("http://example.com", "http://example.com"); - assertFalse(config.shouldAutoCaptureSessions()); + assertFalse(config.getAutoCaptureSessions()); } @SuppressWarnings("deprecation") @@ -163,9 +163,9 @@ public void testLaunchThreshold() throws Exception { @Test public void testAutoCaptureSessions() throws Exception { - assertTrue(config.shouldAutoCaptureSessions()); + assertTrue(config.getAutoCaptureSessions()); config.setAutoCaptureSessions(false); - assertFalse(config.shouldAutoCaptureSessions()); + assertFalse(config.getAutoCaptureSessions()); } @Test diff --git a/sdk/src/androidTest/java/com/bugsnag/android/DeviceDataSummaryTest.java b/sdk/src/androidTest/java/com/bugsnag/android/DeviceDataSummaryTest.java index 81df0b5450..5a8000cf83 100644 --- a/sdk/src/androidTest/java/com/bugsnag/android/DeviceDataSummaryTest.java +++ b/sdk/src/androidTest/java/com/bugsnag/android/DeviceDataSummaryTest.java @@ -66,6 +66,7 @@ public void testJsonSerialisation() throws JSONException { assertNotNull(deviceDataJson.getString("osVersion")); assertNotNull(deviceDataJson.getString("manufacturer")); assertNotNull(deviceDataJson.getString("model")); + assertNotNull(deviceDataJson.get("cpuAbi")); assertTrue(deviceDataJson.has("jailbroken")); } diff --git a/sdk/src/androidTest/java/com/bugsnag/android/ErrorReaderTest.java b/sdk/src/androidTest/java/com/bugsnag/android/ErrorReaderTest.java index 23b3723cfc..c76480a340 100644 --- a/sdk/src/androidTest/java/com/bugsnag/android/ErrorReaderTest.java +++ b/sdk/src/androidTest/java/com/bugsnag/android/ErrorReaderTest.java @@ -139,6 +139,11 @@ public void testReadErrorDeviceData() throws JSONException { assertEquals("sdk_phone_armv7", data.get("model")); assertEquals("portrait", data.get("orientation")); assertEquals(134217728, data.get("totalMemory")); + + @SuppressWarnings("unchecked") + List cpuAbi = (List) data.get("cpuAbi"); + assertEquals("armeabi-v7a", cpuAbi.get(0)); + assertEquals("armeabi", cpuAbi.get(1)); } @Test @@ -174,10 +179,6 @@ public void testReadErrorMetaData() throws JSONException { assertEquals(1, metadata.getTab("device").get("screenDensity")); assertEquals("480x320", metadata.getTab("device").get("screenResolution")); assertEquals("2018-10-19T18:56:13Z", metadata.getTab("device").get("time")); - @SuppressWarnings("unchecked") - List cpuAbi = (List)metadata.getTab("device").get("cpuAbi"); - assertEquals("armeabi-v7a", cpuAbi.get(0)); - assertEquals("armeabi", cpuAbi.get(1)); } @Test diff --git a/sdk/src/androidTest/java/com/bugsnag/android/NativeInterfaceTest.java b/sdk/src/androidTest/java/com/bugsnag/android/NativeInterfaceTest.java new file mode 100644 index 0000000000..f558d4f899 --- /dev/null +++ b/sdk/src/androidTest/java/com/bugsnag/android/NativeInterfaceTest.java @@ -0,0 +1,16 @@ +package com.bugsnag.android; + +import static org.junit.Assert.assertNotSame; + +import org.junit.Test; + +public class NativeInterfaceTest { + + @Test + public void getMetaData() { + Client client = BugsnagTestUtils.generateClient(); + NativeInterface.setClient(client); + assertNotSame(client.config.getMetaData().store, NativeInterface.getMetaData()); + } + +} diff --git a/sdk/src/androidTest/res/raw/error.json b/sdk/src/androidTest/res/raw/error.json index 78b4d1d39c..988ccb21ba 100644 --- a/sdk/src/androidTest/res/raw/error.json +++ b/sdk/src/androidTest/res/raw/error.json @@ -90,11 +90,7 @@ "dpi": 160, "screenDensity": 1, "screenResolution": "480x320", - "time": "2018-10-19T18:56:13Z", - "cpuAbi": [ - "armeabi-v7a", - "armeabi" - ] + "time": "2018-10-19T18:56:13Z" }, "customer": { "name": "Acme Co", @@ -109,7 +105,11 @@ "manufacturer": "Hudan", "model": "sdk_phone_armv7", "orientation": "portrait", - "totalMemory": 134217728 + "totalMemory": 134217728, + "cpuAbi": [ + "armeabi-v7a", + "armeabi" + ] }, "session": { "id": "225bcada-e0c8-15a0-0bba-0e3c7f43c13f", diff --git a/sdk/src/main/java/com/bugsnag/android/AppData.java b/sdk/src/main/java/com/bugsnag/android/AppData.java index cfd997285f..ee334deb27 100644 --- a/sdk/src/main/java/com/bugsnag/android/AppData.java +++ b/sdk/src/main/java/com/bugsnag/android/AppData.java @@ -26,6 +26,7 @@ class AppData { private final Context appContext; private final String packageName; + private String binaryArch = null; @Nullable final String appName; @@ -76,6 +77,7 @@ Map getAppData() { map.put("durationInForeground", calculateDurationInForeground()); map.put("inForeground", client.sessionTracker.isInForeground()); map.put("packageName", packageName); + map.put("binaryArch", binaryArch); return map; } @@ -90,6 +92,10 @@ Map getAppDataMetaData() { return map; } + void setBinaryArch(String binaryArch) { + this.binaryArch = binaryArch; + } + /** * Get the time in milliseconds since Bugsnag was initialized, which is a * good approximation for how long the app has been running. diff --git a/sdk/src/main/java/com/bugsnag/android/BadResponseException.java b/sdk/src/main/java/com/bugsnag/android/BadResponseException.java index f42c62f1b6..81b7642764 100644 --- a/sdk/src/main/java/com/bugsnag/android/BadResponseException.java +++ b/sdk/src/main/java/com/bugsnag/android/BadResponseException.java @@ -1,5 +1,7 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + import java.util.Locale; /** @@ -10,7 +12,7 @@ public class BadResponseException extends Exception { private static final long serialVersionUID = -870190454845379171L; - public BadResponseException(String msg, int responseCode) { + public BadResponseException(@NonNull String msg, int responseCode) { super(String.format(Locale.US, "%s (%d)", msg, responseCode)); } } diff --git a/sdk/src/main/java/com/bugsnag/android/BeforeNotify.java b/sdk/src/main/java/com/bugsnag/android/BeforeNotify.java index 01112e0dea..a67eb3a359 100644 --- a/sdk/src/main/java/com/bugsnag/android/BeforeNotify.java +++ b/sdk/src/main/java/com/bugsnag/android/BeforeNotify.java @@ -1,5 +1,7 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + /** * A callback to be run before reports are sent to Bugsnag. *

@@ -18,5 +20,5 @@ public interface BeforeNotify { * @param error the error to be sent to Bugsnag * @see Error */ - boolean run(Error error); + boolean run(@NonNull Error error); } diff --git a/sdk/src/main/java/com/bugsnag/android/BeforeSend.java b/sdk/src/main/java/com/bugsnag/android/BeforeSend.java index e652b49277..41babd2b52 100644 --- a/sdk/src/main/java/com/bugsnag/android/BeforeSend.java +++ b/sdk/src/main/java/com/bugsnag/android/BeforeSend.java @@ -1,5 +1,7 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + /** * A callback to be run before every report sent to Bugsnag. *

@@ -16,5 +18,5 @@ public interface BeforeSend { * * @param report the {@link Report} to be sent to Bugsnag */ - boolean run(Report report); + boolean run(@NonNull Report report); } diff --git a/sdk/src/main/java/com/bugsnag/android/BreadcrumbType.java b/sdk/src/main/java/com/bugsnag/android/BreadcrumbType.java index 39140de43a..b9408a1f4e 100644 --- a/sdk/src/main/java/com/bugsnag/android/BreadcrumbType.java +++ b/sdk/src/main/java/com/bugsnag/android/BreadcrumbType.java @@ -1,5 +1,7 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + /** * Recognized types of breadcrumbs */ @@ -40,11 +42,12 @@ public enum BreadcrumbType { private final String type; - BreadcrumbType(String type) { + BreadcrumbType(@NonNull String type) { this.type = type; } @Override + @NonNull public String toString() { return type; } diff --git a/sdk/src/main/java/com/bugsnag/android/Bugsnag.java b/sdk/src/main/java/com/bugsnag/android/Bugsnag.java index 34063c18b9..97aa905ee1 100644 --- a/sdk/src/main/java/com/bugsnag/android/Bugsnag.java +++ b/sdk/src/main/java/com/bugsnag/android/Bugsnag.java @@ -95,7 +95,7 @@ private static void logClientInitWarning() { * * @param appVersion the app version to send */ - public static void setAppVersion(final String appVersion) { + public static void setAppVersion(@NonNull final String appVersion) { getClient().setAppVersion(appVersion); } @@ -104,7 +104,7 @@ public static void setAppVersion(final String appVersion) { * * @return Context */ - public static String getContext() { + @Nullable public static String getContext() { return getClient().getContext(); } @@ -115,7 +115,7 @@ public static String getContext() { * * @param context set what was happening at the time of a crash */ - public static void setContext(final String context) { + public static void setContext(@Nullable final String context) { getClient().setContext(context); } @@ -130,7 +130,7 @@ public static void setContext(final String context) { * instead. */ @Deprecated - public static void setEndpoint(final String endpoint) { + public static void setEndpoint(@NonNull final String endpoint) { getClient().setEndpoint(endpoint); } @@ -143,7 +143,7 @@ public static void setEndpoint(final String endpoint) { * @param buildUuid the buildUuid. */ @SuppressWarnings("checkstyle:AbbreviationAsWordInName") - public static void setBuildUUID(final String buildUuid) { + public static void setBuildUUID(@Nullable final String buildUuid) { getClient().setBuildUUID(buildUuid); } @@ -160,7 +160,7 @@ public static void setBuildUUID(final String buildUuid) { * * @param filters a list of keys to filter from metaData */ - public static void setFilters(final String... filters) { + public static void setFilters(@Nullable final String... filters) { getClient().setFilters(filters); } @@ -173,7 +173,7 @@ public static void setFilters(final String... filters) { * * @param ignoreClasses a list of exception classes to ignore */ - public static void setIgnoreClasses(final String... ignoreClasses) { + public static void setIgnoreClasses(@Nullable final String... ignoreClasses) { getClient().setIgnoreClasses(ignoreClasses); } @@ -188,7 +188,7 @@ public static void setIgnoreClasses(final String... ignoreClasses) { * @param notifyReleaseStages a list of releaseStages to notify for * @see #setReleaseStage */ - public static void setNotifyReleaseStages(final String... notifyReleaseStages) { + public static void setNotifyReleaseStages(@Nullable final String... notifyReleaseStages) { getClient().setNotifyReleaseStages(notifyReleaseStages); } @@ -204,7 +204,7 @@ public static void setNotifyReleaseStages(final String... notifyReleaseStages) { * * @param projectPackages a list of package names */ - public static void setProjectPackages(final String... projectPackages) { + public static void setProjectPackages(@Nullable final String... projectPackages) { getClient().setProjectPackages(projectPackages); } @@ -218,7 +218,7 @@ public static void setProjectPackages(final String... projectPackages) { * @param releaseStage the release stage of the app * @see #setNotifyReleaseStages {@link #setLoggingEnabled(boolean)} */ - public static void setReleaseStage(final String releaseStage) { + public static void setReleaseStage(@Nullable final String releaseStage) { getClient().setReleaseStage(releaseStage); } @@ -256,7 +256,9 @@ public static void setAutoCaptureSessions(boolean autoCapture) { * @param email the email address of the current user * @param name the name of the current user */ - public static void setUser(final String id, final String email, final String name) { + public static void setUser(@Nullable final String id, + @Nullable final String email, + @Nullable final String name) { getClient().setUser(id, email, name); } @@ -274,7 +276,7 @@ public static void clearUser() { * * @param id a unique identifier of the current user */ - public static void setUserId(final String id) { + public static void setUserId(@Nullable final String id) { getClient().setUserId(id); } @@ -284,7 +286,7 @@ public static void setUserId(final String id) { * * @param email the email address of the current user */ - public static void setUserEmail(final String email) { + public static void setUserEmail(@Nullable final String email) { getClient().setUserEmail(email); } @@ -294,7 +296,7 @@ public static void setUserEmail(final String email) { * * @param name the name of the current user */ - public static void setUserName(final String name) { + public static void setUserName(@Nullable final String name) { getClient().setUserName(name); } @@ -356,7 +358,7 @@ public static void setSessionTrackingApiClient(@NonNull SessionTrackingApiClient * @param beforeNotify a callback to run before sending errors to Bugsnag * @see BeforeNotify */ - public static void beforeNotify(final BeforeNotify beforeNotify) { + public static void beforeNotify(@NonNull final BeforeNotify beforeNotify) { getClient().beforeNotify(beforeNotify); } @@ -378,7 +380,8 @@ public static void beforeNotify(final BeforeNotify beforeNotify) { * @param beforeRecordBreadcrumb a callback to run before a breadcrumb is captured * @see BeforeRecordBreadcrumb */ - public static void beforeRecordBreadcrumb(final BeforeRecordBreadcrumb beforeRecordBreadcrumb) { + public static void beforeRecordBreadcrumb( + @NonNull final BeforeRecordBreadcrumb beforeRecordBreadcrumb) { getClient().beforeRecordBreadcrumb(beforeRecordBreadcrumb); } @@ -398,7 +401,8 @@ public static void notify(@NonNull final Throwable exception) { * @param callback callback invoked on the generated error report for * additional modification */ - public static void notify(@NonNull final Throwable exception, final Callback callback) { + public static void notify(@NonNull final Throwable exception, + @Nullable final Callback callback) { getClient().notify(exception, callback); } @@ -414,7 +418,7 @@ public static void notify(@NonNull final Throwable exception, final Callback cal public static void notify(@NonNull String name, @NonNull String message, @NonNull StackTraceElement[] stacktrace, - Callback callback) { + @Nullable Callback callback) { getClient().notify(name, message, stacktrace, callback); } @@ -425,7 +429,8 @@ public static void notify(@NonNull String name, * @param severity the severity of the error, one of Severity.ERROR, * Severity.WARNING or Severity.INFO */ - public static void notify(@NonNull final Throwable exception, final Severity severity) { + public static void notify(@NonNull final Throwable exception, + @NonNull final Severity severity) { getClient().notify(exception, severity); } @@ -457,7 +462,8 @@ public void beforeNotify(@NonNull Report report) { * @deprecated Use {@link #notify(Throwable, Callback)} to send and modify error reports */ @Deprecated - public static void notify(@NonNull final Throwable exception, final Severity severity, + public static void notify(@NonNull final Throwable exception, + @NonNull final Severity severity, @NonNull final MetaData metaData) { getClient().notify(exception, new Callback() { @Override @@ -481,8 +487,10 @@ public void beforeNotify(@NonNull Report report) { * to send and modify error reports */ @Deprecated - public static void notify(@NonNull String name, @NonNull String message, - @NonNull StackTraceElement[] stacktrace, Severity severity, + public static void notify(@NonNull String name, + @NonNull String message, + @NonNull StackTraceElement[] stacktrace, + @NonNull Severity severity, @NonNull MetaData metaData) { final Severity finalSeverity = severity; final MetaData finalMetaData = metaData; @@ -511,8 +519,11 @@ public void beforeNotify(@NonNull Report report) { @Deprecated @SuppressWarnings("checkstyle:JavadocTagContinuationIndentation") - public static void notify(@NonNull String name, @NonNull String message, String context, - @NonNull StackTraceElement[] stacktrace, Severity severity, + public static void notify(@NonNull String name, + @NonNull String message, + @Nullable String context, + @NonNull StackTraceElement[] stacktrace, + @NonNull Severity severity, @NonNull MetaData metaData) { final String finalContext = context; final Severity finalSeverity = severity; @@ -532,9 +543,9 @@ public void beforeNotify(@NonNull Report report) { * Android is not supported. */ public static void internalClientNotify(@NonNull final Throwable exception, - Map clientData, + @NonNull Map clientData, boolean blocking, - Callback callback) { + @Nullable Callback callback) { getClient().internalClientNotify(exception, clientData, blocking, callback); } @@ -551,7 +562,9 @@ public static void internalClientNotify(@NonNull final Throwable exception, * @param key the name of the diagnostic information * @param value the contents of the diagnostic information */ - public static void addToTab(final String tab, final String key, final Object value) { + public static void addToTab(@NonNull final String tab, + @NonNull final String key, + @Nullable final Object value) { getClient().addToTab(tab, key, value); } @@ -560,7 +573,7 @@ public static void addToTab(final String tab, final String key, final Object val * * @param tabName the dashboard tab to remove diagnostic data from */ - public static void clearTab(String tabName) { + public static void clearTab(@NonNull String tabName) { getClient().clearTab(tabName); } diff --git a/sdk/src/main/java/com/bugsnag/android/BugsnagException.java b/sdk/src/main/java/com/bugsnag/android/BugsnagException.java index 3abe5585b6..25a9dd7b91 100644 --- a/sdk/src/main/java/com/bugsnag/android/BugsnagException.java +++ b/sdk/src/main/java/com/bugsnag/android/BugsnagException.java @@ -1,5 +1,7 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + /** * Used to store information about an exception that was not provided with an exception object */ @@ -19,7 +21,9 @@ public class BugsnagException extends Throwable { * @param message The exception message * @param frames The exception stack trace */ - public BugsnagException(String name, String message, StackTraceElement[] frames) { + public BugsnagException(@NonNull String name, + @NonNull String message, + @NonNull StackTraceElement[] frames) { super(message); super.setStackTrace(frames); @@ -29,6 +33,7 @@ public BugsnagException(String name, String message, StackTraceElement[] frames) /** * @return The name of the exception (used instead of the exception class) */ + @NonNull public String getName() { return name; } diff --git a/sdk/src/main/java/com/bugsnag/android/Callback.java b/sdk/src/main/java/com/bugsnag/android/Callback.java index 483d89a441..58b20a03a0 100644 --- a/sdk/src/main/java/com/bugsnag/android/Callback.java +++ b/sdk/src/main/java/com/bugsnag/android/Callback.java @@ -1,6 +1,8 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + /** * A callback to be run before an individual report is sent to Bugsnag. *

@@ -11,5 +13,5 @@ */ public interface Callback { - void beforeNotify(Report report); + void beforeNotify(@NonNull Report report); } diff --git a/sdk/src/main/java/com/bugsnag/android/Client.java b/sdk/src/main/java/com/bugsnag/android/Client.java index 62f4adf552..80b554b2a9 100644 --- a/sdk/src/main/java/com/bugsnag/android/Client.java +++ b/sdk/src/main/java/com/bugsnag/android/Client.java @@ -71,7 +71,7 @@ public class Client extends Observable implements Observer { final SessionStore sessionStore; - private final EventReceiver eventReceiver; + final EventReceiver eventReceiver; final SessionTracker sessionTracker; SharedPreferences sharedPrefs; @@ -230,7 +230,7 @@ public void onOrientationChanged(int orientation) { errorStore.flushOnLaunch(); } - private class ConnectivityChangeReceiver extends BroadcastReceiver { + class ConnectivityChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { ConnectivityManager cm = @@ -263,14 +263,14 @@ public void run() { } } - private void enqueuePendingNativeReports() { + void enqueuePendingNativeReports() { setChanged(); notifyObservers(new Message( NativeInterface.MessageType.DELIVER_PENDING, null)); } @Override - public void update(Observable observable, Object arg) { + public void update(@NonNull Observable observable, @NonNull Object arg) { if (arg instanceof Message) { setChanged(); super.notifyObservers(arg); @@ -294,7 +294,7 @@ public void startSession() { * This is an integration point for custom libraries implementing automatic session capture * which differs from the default activity-based initialization. */ - public void startFirstSession(Activity activity) { + public void startFirstSession(@NonNull Activity activity) { sessionTracker.startFirstSession(activity); } @@ -304,7 +304,7 @@ public void startFirstSession(Activity activity) { * * @param appVersion the app version to send */ - public void setAppVersion(String appVersion) { + public void setAppVersion(@NonNull String appVersion) { config.setAppVersion(appVersion); } @@ -313,7 +313,7 @@ public void setAppVersion(String appVersion) { * * @return Context */ - public String getContext() { + @Nullable public String getContext() { return config.getContext(); } @@ -324,7 +324,7 @@ public String getContext() { * * @param context set what was happening at the time of a crash */ - public void setContext(String context) { + public void setContext(@Nullable String context) { config.setContext(context); } @@ -339,7 +339,7 @@ public void setContext(String context) { * instead. */ @Deprecated - public void setEndpoint(String endpoint) { + public void setEndpoint(@NonNull String endpoint) { config.setEndpoint(endpoint); } @@ -352,7 +352,7 @@ public void setEndpoint(String endpoint) { * @param buildUuid the buildUuid. */ @SuppressWarnings("checkstyle:AbbreviationAsWordInName") - public void setBuildUUID(final String buildUuid) { + public void setBuildUUID(@Nullable final String buildUuid) { config.setBuildUUID(buildUuid); } @@ -370,7 +370,7 @@ public void setBuildUUID(final String buildUuid) { * * @param filters a list of keys to filter from metaData */ - public void setFilters(String... filters) { + public void setFilters(@Nullable String... filters) { config.setFilters(filters); } @@ -383,7 +383,7 @@ public void setFilters(String... filters) { * * @param ignoreClasses a list of exception classes to ignore */ - public void setIgnoreClasses(String... ignoreClasses) { + public void setIgnoreClasses(@Nullable String... ignoreClasses) { config.setIgnoreClasses(ignoreClasses); } @@ -398,7 +398,7 @@ public void setIgnoreClasses(String... ignoreClasses) { * @param notifyReleaseStages a list of releaseStages to notify for * @see #setReleaseStage */ - public void setNotifyReleaseStages(String... notifyReleaseStages) { + public void setNotifyReleaseStages(@Nullable String... notifyReleaseStages) { config.setNotifyReleaseStages(notifyReleaseStages); } @@ -414,7 +414,7 @@ public void setNotifyReleaseStages(String... notifyReleaseStages) { * * @param projectPackages a list of package names */ - public void setProjectPackages(String... projectPackages) { + public void setProjectPackages(@Nullable String... projectPackages) { config.setProjectPackages(projectPackages); } @@ -426,7 +426,7 @@ public void setProjectPackages(String... projectPackages) { * @param releaseStage the release stage of the app * @see #setNotifyReleaseStages */ - public void setReleaseStage(String releaseStage) { + public void setReleaseStage(@Nullable String releaseStage) { config.setReleaseStage(releaseStage); Logger.setEnabled(!AppData.RELEASE_STAGE_PRODUCTION.equals(releaseStage)); } @@ -470,7 +470,7 @@ public void setAutoCaptureSessions(boolean autoCapture) { * @param email the email address of the current user * @param name the name of the current user */ - public void setUser(String id, String email, String name) { + public void setUser(@Nullable String id, @Nullable String email, @Nullable String name) { setUserId(id); setUserEmail(email); setUserName(name); @@ -529,7 +529,7 @@ public void clearUser() { * * @param id a unique identifier of the current user */ - public void setUserId(String id) { + public void setUserId(@Nullable String id) { user.setId(id); if (config.getPersistUserBetweenSessions()) { @@ -543,7 +543,7 @@ public void setUserId(String id) { * * @param email the email address of the current user */ - public void setUserEmail(String email) { + public void setUserEmail(@Nullable String email) { user.setEmail(email); if (config.getPersistUserBetweenSessions()) { @@ -557,7 +557,7 @@ public void setUserEmail(String email) { * * @param name the name of the current user */ - public void setUserName(String name) { + public void setUserName(@Nullable String name) { user.setName(name); if (config.getPersistUserBetweenSessions()) { @@ -619,7 +619,7 @@ void setSessionTrackingApiClient(@NonNull SessionTrackingApiClient apiClient) { * @param beforeNotify a callback to run before sending errors to Bugsnag * @see BeforeNotify */ - public void beforeNotify(BeforeNotify beforeNotify) { + public void beforeNotify(@NonNull BeforeNotify beforeNotify) { config.beforeNotify(beforeNotify); } @@ -641,7 +641,7 @@ public void beforeNotify(BeforeNotify beforeNotify) { * @param beforeRecordBreadcrumb a callback to run before a breadcrumb is captured * @see BeforeRecordBreadcrumb */ - public void beforeRecordBreadcrumb(BeforeRecordBreadcrumb beforeRecordBreadcrumb) { + public void beforeRecordBreadcrumb(@NonNull BeforeRecordBreadcrumb beforeRecordBreadcrumb) { config.beforeRecordBreadcrumb(beforeRecordBreadcrumb); } @@ -665,7 +665,7 @@ public void notify(@NonNull Throwable exception) { * @param callback callback invoked on the generated error report for * additional modification */ - public void notify(@NonNull Throwable exception, Callback callback) { + public void notify(@NonNull Throwable exception, @Nullable Callback callback) { Error error = new Error.Builder(config, exception, sessionTracker.getCurrentSession(), Thread.currentThread(), false) .severityReasonType(HandledState.REASON_HANDLED_EXCEPTION) @@ -685,7 +685,7 @@ public void notify(@NonNull Throwable exception, Callback callback) { public void notify(@NonNull String name, @NonNull String message, @NonNull StackTraceElement[] stacktrace, - Callback callback) { + @Nullable Callback callback) { Error error = new Error.Builder(config, name, message, stacktrace, sessionTracker.getCurrentSession(), Thread.currentThread()) .severityReasonType(HandledState.REASON_HANDLED_EXCEPTION) @@ -700,7 +700,7 @@ public void notify(@NonNull String name, * @param severity the severity of the error, one of Severity.ERROR, * Severity.WARNING or Severity.INFO */ - public void notify(@NonNull Throwable exception, Severity severity) { + public void notify(@NonNull Throwable exception, @NonNull Severity severity) { Error error = new Error.Builder(config, exception, sessionTracker.getCurrentSession(), Thread.currentThread(), false) .severity(severity) @@ -736,7 +736,7 @@ public void notify(@NonNull Throwable exception, * @deprecated Use {@link #notify(Throwable, Callback)} to send and modify error reports */ @Deprecated - public void notify(@NonNull Throwable exception, Severity severity, + public void notify(@NonNull Throwable exception, @NonNull Severity severity, @NonNull MetaData metaData) { Error error = new Error.Builder(config, exception, sessionTracker.getCurrentSession(), Thread.currentThread(), false) @@ -760,7 +760,7 @@ public void notify(@NonNull Throwable exception, Severity severity, */ @Deprecated public void notify(@NonNull String name, @NonNull String message, - @NonNull StackTraceElement[] stacktrace, Severity severity, + @NonNull StackTraceElement[] stacktrace, @NonNull Severity severity, @NonNull MetaData metaData) { Error error = new Error.Builder(config, name, message, stacktrace, sessionTracker.getCurrentSession(), Thread.currentThread()) @@ -786,9 +786,9 @@ public void notify(@NonNull String name, @NonNull String message, @Deprecated public void notify(@NonNull String name, @NonNull String message, - String context, + @Nullable String context, @NonNull StackTraceElement[] stacktrace, - Severity severity, + @NonNull Severity severity, @NonNull MetaData metaData) { Error error = new Error.Builder(config, name, message, stacktrace, sessionTracker.getCurrentSession(), Thread.currentThread()) @@ -927,7 +927,7 @@ public void notifyBlocking(@NonNull Throwable exception) { * @param callback callback invoked on the generated error report for * additional modification */ - public void notifyBlocking(@NonNull Throwable exception, Callback callback) { + public void notifyBlocking(@NonNull Throwable exception, @Nullable Callback callback) { Error error = new Error.Builder(config, exception, sessionTracker.getCurrentSession(), Thread.currentThread(), false) .severityReasonType(HandledState.REASON_HANDLED_EXCEPTION) @@ -947,7 +947,7 @@ public void notifyBlocking(@NonNull Throwable exception, Callback callback) { public void notifyBlocking(@NonNull String name, @NonNull String message, @NonNull StackTraceElement[] stacktrace, - Callback callback) { + @Nullable Callback callback) { Error error = new Error.Builder(config, name, message, stacktrace, sessionTracker.getCurrentSession(), Thread.currentThread()) .severityReasonType(HandledState.REASON_HANDLED_EXCEPTION) @@ -983,7 +983,7 @@ public void notifyBlocking(@NonNull Throwable exception, * @deprecated Use {@link #notifyBlocking(Throwable, Callback)} to send and modify error reports */ @Deprecated - public void notifyBlocking(@NonNull Throwable exception, Severity severity, + public void notifyBlocking(@NonNull Throwable exception, @NonNull Severity severity, @NonNull MetaData metaData) { Error error = new Error.Builder(config, exception, sessionTracker.getCurrentSession(), Thread.currentThread(), false) @@ -1009,7 +1009,7 @@ public void notifyBlocking(@NonNull Throwable exception, Severity severity, public void notifyBlocking(@NonNull String name, @NonNull String message, @NonNull StackTraceElement[] stacktrace, - Severity severity, + @NonNull Severity severity, @NonNull MetaData metaData) { Error error = new Error.Builder(config, name, message, stacktrace, sessionTracker.getCurrentSession(), Thread.currentThread()) @@ -1035,9 +1035,9 @@ public void notifyBlocking(@NonNull String name, @Deprecated public void notifyBlocking(@NonNull String name, @NonNull String message, - String context, + @Nullable String context, @NonNull StackTraceElement[] stacktrace, - Severity severity, + @NonNull Severity severity, @NonNull MetaData metaData) { Error error = new Error.Builder(config, name, message, stacktrace, sessionTracker.getCurrentSession(), Thread.currentThread()) @@ -1055,7 +1055,7 @@ public void notifyBlocking(@NonNull String name, * @param severity the severity of the error, one of Severity.ERROR, * Severity.WARNING or Severity.INFO */ - public void notifyBlocking(@NonNull Throwable exception, Severity severity) { + public void notifyBlocking(@NonNull Throwable exception, @NonNull Severity severity) { Error error = new Error.Builder(config, exception, sessionTracker.getCurrentSession(), Thread.currentThread(), false) .severity(severity) @@ -1072,9 +1072,9 @@ public void notifyBlocking(@NonNull Throwable exception, Severity severity) { * @param callback a callback when notifying */ public void internalClientNotify(@NonNull Throwable exception, - Map clientData, + @NonNull Map clientData, boolean blocking, - Callback callback) { + @Nullable Callback callback) { String severity = getKeyFromClientData(clientData, "severity", true); String severityReason = getKeyFromClientData(clientData, "severityReason", true); @@ -1122,7 +1122,7 @@ private String getKeyFromClientData(Map clientData, * @param key the name of the diagnostic information * @param value the contents of the diagnostic information */ - public void addToTab(String tab, String key, Object value) { + public void addToTab(@NonNull String tab, @NonNull String key, @Nullable Object value) { config.getMetaData().addToTab(tab, key, value); } @@ -1131,7 +1131,7 @@ public void addToTab(String tab, String key, Object value) { * * @param tabName the dashboard tab to remove diagnostic data from */ - public void clearTab(String tabName) { + public void clearTab(@NonNull String tabName) { config.getMetaData().clearTab(tabName); } @@ -1370,4 +1370,8 @@ public long getLaunchTimeMs() { return AppData.getDurationMs(); } + void setBinaryArch(String binaryArch) { + getAppData().setBinaryArch(binaryArch); + } + } diff --git a/sdk/src/main/java/com/bugsnag/android/Configuration.java b/sdk/src/main/java/com/bugsnag/android/Configuration.java index 2953368a60..637da67f6a 100644 --- a/sdk/src/main/java/com/bugsnag/android/Configuration.java +++ b/sdk/src/main/java/com/bugsnag/android/Configuration.java @@ -73,7 +73,7 @@ public Configuration(@NonNull String apiKey) { /** * Respond to an update notification from observed objects, like MetaData */ - public void update(Observable observable, Object arg) { + public void update(@NonNull Observable observable, @NonNull Object arg) { if (arg instanceof NativeInterface.Message) { setChanged(); notifyObservers(arg); @@ -95,6 +95,7 @@ public String getApiKey() { * * @return App Version */ + @NonNull public String getAppVersion() { return appVersion; } @@ -105,7 +106,7 @@ public String getAppVersion() { * * @param appVersion the app version to send */ - public void setAppVersion(String appVersion) { + public void setAppVersion(@NonNull String appVersion) { this.appVersion = appVersion; setChanged(); notifyObservers(new NativeInterface.Message( @@ -117,6 +118,7 @@ public void setAppVersion(String appVersion) { * * @return Context */ + @Nullable public String getContext() { return context; } @@ -128,7 +130,7 @@ public String getContext() { * * @param context set what was happening at the time of a crash */ - public void setContext(String context) { + public void setContext(@Nullable String context) { this.context = context; setChanged(); notifyObservers(new NativeInterface.Message( @@ -140,6 +142,7 @@ public void setContext(String context) { * * @return Endpoint */ + @NonNull public String getEndpoint() { return endpoint; } @@ -154,7 +157,7 @@ public String getEndpoint() { * @deprecated use {@link com.bugsnag.android.Configuration#setEndpoints(String, String)} */ @Deprecated - public void setEndpoint(String endpoint) { + public void setEndpoint(@NonNull String endpoint) { this.endpoint = endpoint; } @@ -198,6 +201,7 @@ public void setEndpoints(@NonNull String notify, @NonNull String sessions) * * @return the endpoint */ + @NonNull public String getSessionEndpoint() { return sessionEndpoint; } @@ -212,7 +216,7 @@ public String getSessionEndpoint() { * @deprecated use {@link com.bugsnag.android.Configuration#setEndpoints(String, String)} */ @Deprecated - public void setSessionEndpoint(String endpoint) { + public void setSessionEndpoint(@NonNull String endpoint) { this.sessionEndpoint = endpoint; } @@ -222,6 +226,7 @@ public void setSessionEndpoint(String endpoint) { * @return build UUID */ @SuppressWarnings("checkstyle:AbbreviationAsWordInName") + @Nullable public String getBuildUUID() { return buildUuid; } @@ -235,7 +240,7 @@ public String getBuildUUID() { * @param buildUuid the buildUUID. */ @SuppressWarnings("checkstyle:AbbreviationAsWordInName") - public void setBuildUUID(String buildUuid) { + public void setBuildUUID(@Nullable String buildUuid) { this.buildUuid = buildUuid; setChanged(); notifyObservers(new NativeInterface.Message( @@ -247,6 +252,7 @@ public void setBuildUUID(String buildUuid) { * * @return Filters */ + @Nullable public String[] getFilters() { return metaData.getFilters(); } @@ -264,7 +270,7 @@ public String[] getFilters() { * * @param filters a list of keys to filter from metaData */ - public void setFilters(String[] filters) { + public void setFilters(@Nullable String[] filters) { this.metaData.setFilters(filters); } @@ -273,6 +279,7 @@ public void setFilters(String[] filters) { * * @return Ignore classes */ + @Nullable public String[] getIgnoreClasses() { return ignoreClasses; } @@ -286,7 +293,7 @@ public String[] getIgnoreClasses() { * * @param ignoreClasses a list of exception classes to ignore */ - public void setIgnoreClasses(String[] ignoreClasses) { + public void setIgnoreClasses(@Nullable String[] ignoreClasses) { this.ignoreClasses = ignoreClasses; } @@ -320,6 +327,7 @@ public void setNotifyReleaseStages(@Nullable String[] notifyReleaseStages) { * * @return packages */ + @Nullable public String[] getProjectPackages() { return projectPackages; } @@ -336,7 +344,7 @@ public String[] getProjectPackages() { * * @param projectPackages a list of package names */ - public void setProjectPackages(String[] projectPackages) { + public void setProjectPackages(@Nullable String[] projectPackages) { this.projectPackages = projectPackages; } @@ -345,6 +353,7 @@ public void setProjectPackages(String[] projectPackages) { * * @return release stage */ + @Nullable public String getReleaseStage() { return releaseStage; } @@ -357,7 +366,7 @@ public String getReleaseStage() { * @param releaseStage the release stage of the app * @see #setNotifyReleaseStages */ - public void setReleaseStage(String releaseStage) { + public void setReleaseStage(@Nullable String releaseStage) { this.releaseStage = releaseStage; setChanged(); notifyObservers(new NativeInterface.Message( @@ -405,8 +414,19 @@ public void setEnableExceptionHandler(boolean enableExceptionHandler) { * Get whether or not User sessions are captured automatically. * * @return true if sessions are captured automatically + * @deprecated use {@link #getAutoCaptureSessions()} */ + @Deprecated public boolean shouldAutoCaptureSessions() { + return getAutoCaptureSessions(); + } + + /** + * Get whether or not User sessions are captured automatically. + * + * @return true if sessions are captured automatically + */ + public boolean getAutoCaptureSessions() { return autoCaptureSessions; } @@ -543,7 +563,7 @@ public void setAutomaticallyCollectBreadcrumbs(boolean automaticallyCollectBread * Intended for internal use only - sets the type of the notifier (e.g. Android, React Native) * @param notifierType the notifier type */ - public void setNotifierType(String notifierType) { + public void setNotifierType(@NonNull String notifierType) { this.notifierType = notifierType; } @@ -551,15 +571,17 @@ public void setNotifierType(String notifierType) { * Intended for internal use only - sets the code bundle id for React Native * @param codeBundleId the code bundle id */ - public void setCodeBundleId(String codeBundleId) { + public void setCodeBundleId(@Nullable String codeBundleId) { this.codeBundleId = codeBundleId; } - String getCodeBundleId() { + @Nullable + public String getCodeBundleId() { return codeBundleId; } - String getNotifierType() { + @NonNull + public String getNotifierType() { return notifierType; } @@ -624,6 +646,7 @@ public void setDelivery(@NonNull Delivery delivery) { * * @return the HTTP headers */ + @NonNull public Map getErrorApiHeaders() { Map map = new HashMap<>(); map.put(HEADER_API_PAYLOAD_VERSION, "4.0"); @@ -637,6 +660,7 @@ public Map getErrorApiHeaders() { * * @return the HTTP headers */ + @NonNull public Map getSessionApiHeaders() { Map map = new HashMap<>(); map.put(HEADER_API_PAYLOAD_VERSION, "1.0"); @@ -666,7 +690,7 @@ public Map getSessionApiHeaders() { * @see BeforeSend * @see Report */ - public void beforeSend(BeforeSend beforeSend) { + public void beforeSend(@NonNull BeforeSend beforeSend) { if (!beforeSendTasks.contains(beforeSend)) { beforeSendTasks.add(beforeSend); } @@ -678,7 +702,7 @@ public void beforeSend(BeforeSend beforeSend) { * @param releaseStage the release stage to check * @return true if the release state should be notified else false */ - protected boolean shouldNotifyForReleaseStage(String releaseStage) { + protected boolean shouldNotifyForReleaseStage(@Nullable String releaseStage) { if (this.notifyReleaseStages == null) { return true; } @@ -693,7 +717,7 @@ protected boolean shouldNotifyForReleaseStage(String releaseStage) { * @param className the exception class to check * @return true if the exception class should be ignored else false */ - protected boolean shouldIgnoreClass(String className) { + protected boolean shouldIgnoreClass(@Nullable String className) { if (this.ignoreClasses == null) { return false; } @@ -707,7 +731,7 @@ protected boolean shouldIgnoreClass(String className) { * * @param beforeNotify the new before notify task */ - protected void beforeNotify(BeforeNotify beforeNotify) { + protected void beforeNotify(@NonNull BeforeNotify beforeNotify) { if (!beforeNotifyTasks.contains(beforeNotify)) { beforeNotifyTasks.add(beforeNotify); } @@ -718,7 +742,7 @@ protected void beforeNotify(BeforeNotify beforeNotify) { * * @param beforeRecordBreadcrumb the new before breadcrumb task */ - protected void beforeRecordBreadcrumb(BeforeRecordBreadcrumb beforeRecordBreadcrumb) { + protected void beforeRecordBreadcrumb(@NonNull BeforeRecordBreadcrumb beforeRecordBreadcrumb) { if (!beforeRecordBreadcrumbTasks.contains(beforeRecordBreadcrumb)) { beforeRecordBreadcrumbTasks.add(beforeRecordBreadcrumb); } @@ -747,6 +771,7 @@ protected boolean inProject(@NonNull String className) { * * @return the before breadcrumb tasks */ + @NonNull protected Collection getBeforeRecordBreadcrumbTasks() { return beforeRecordBreadcrumbTasks; } diff --git a/sdk/src/main/java/com/bugsnag/android/DefaultDelivery.java b/sdk/src/main/java/com/bugsnag/android/DefaultDelivery.java index fe82d72ba1..76ef349322 100644 --- a/sdk/src/main/java/com/bugsnag/android/DefaultDelivery.java +++ b/sdk/src/main/java/com/bugsnag/android/DefaultDelivery.java @@ -2,6 +2,7 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.io.BufferedWriter; @@ -23,8 +24,8 @@ class DefaultDelivery implements Delivery { } @Override - public void deliver(SessionTrackingPayload payload, - Configuration config) throws DeliveryFailureException { + public void deliver(@NonNull SessionTrackingPayload payload, + @NonNull Configuration config) throws DeliveryFailureException { String endpoint = config.getSessionEndpoint(); int status = deliver(endpoint, payload, config.getSessionApiHeaders()); @@ -36,8 +37,8 @@ public void deliver(SessionTrackingPayload payload, } @Override - public void deliver(Report report, - Configuration config) throws DeliveryFailureException { + public void deliver(@NonNull Report report, + @NonNull Configuration config) throws DeliveryFailureException { String endpoint = config.getEndpoint(); int status = deliver(endpoint, report, config.getErrorApiHeaders()); diff --git a/sdk/src/main/java/com/bugsnag/android/Delivery.java b/sdk/src/main/java/com/bugsnag/android/Delivery.java index 2bb75990c2..72222f7acb 100644 --- a/sdk/src/main/java/com/bugsnag/android/Delivery.java +++ b/sdk/src/main/java/com/bugsnag/android/Delivery.java @@ -1,6 +1,8 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + /** * Implementations of this interface deliver Error Reports and Sessions captured to the Bugsnag API. *

@@ -36,8 +38,8 @@ public interface Delivery { * @throws DeliveryFailureException when delivery is not successful and * the report should be stored for future attempts. */ - void deliver(SessionTrackingPayload payload, - Configuration config) throws DeliveryFailureException; + void deliver(@NonNull SessionTrackingPayload payload, + @NonNull Configuration config) throws DeliveryFailureException; /** * Posts an Error Report to the Bugsnag Error Reporting API. @@ -58,6 +60,6 @@ void deliver(SessionTrackingPayload payload, * @throws DeliveryFailureException when delivery is not successful and * the report should be stored for future attempts. */ - void deliver(Report report, - Configuration config) throws DeliveryFailureException; + void deliver(@NonNull Report report, + @NonNull Configuration config) throws DeliveryFailureException; } diff --git a/sdk/src/main/java/com/bugsnag/android/DeliveryCompat.java b/sdk/src/main/java/com/bugsnag/android/DeliveryCompat.java index 98edd77674..b711c7aa65 100644 --- a/sdk/src/main/java/com/bugsnag/android/DeliveryCompat.java +++ b/sdk/src/main/java/com/bugsnag/android/DeliveryCompat.java @@ -1,5 +1,7 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + /** * A compatibility implementation of {@link Delivery} which wraps {@link ErrorReportApiClient} and * {@link SessionTrackingApiClient}. This class allows for backwards compatibility for users still @@ -15,8 +17,8 @@ class DeliveryCompat implements Delivery { volatile SessionTrackingApiClient sessionTrackingApiClient; @Override - public void deliver(SessionTrackingPayload payload, - Configuration config) throws DeliveryFailureException { + public void deliver(@NonNull SessionTrackingPayload payload, + @NonNull Configuration config) throws DeliveryFailureException { if (sessionTrackingApiClient != null) { try { sessionTrackingApiClient.postSessionTrackingPayload(config.getSessionEndpoint(), @@ -28,7 +30,8 @@ public void deliver(SessionTrackingPayload payload, } @Override - public void deliver(Report report, Configuration config) throws DeliveryFailureException { + public void deliver(@NonNull Report report, + @NonNull Configuration config) throws DeliveryFailureException { if (errorReportApiClient != null) { try { errorReportApiClient.postReport(config.getEndpoint(), diff --git a/sdk/src/main/java/com/bugsnag/android/DeliveryFailureException.java b/sdk/src/main/java/com/bugsnag/android/DeliveryFailureException.java index 25315c9f1b..8b33e257e9 100644 --- a/sdk/src/main/java/com/bugsnag/android/DeliveryFailureException.java +++ b/sdk/src/main/java/com/bugsnag/android/DeliveryFailureException.java @@ -1,5 +1,8 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + /** * This should be thrown if delivery of a request was not successful and you wish to try again * later. The notifier will cache the payload and initiate delivery at a future time. @@ -10,11 +13,11 @@ public class DeliveryFailureException extends Exception { private static final long serialVersionUID = 1501477209400426470L; - public DeliveryFailureException(String message) { + public DeliveryFailureException(@NonNull String message) { super(message); } - public DeliveryFailureException(String message, Throwable cause) { + public DeliveryFailureException(@NonNull String message, @Nullable Throwable cause) { super(message, cause); } } diff --git a/sdk/src/main/java/com/bugsnag/android/DeviceData.java b/sdk/src/main/java/com/bugsnag/android/DeviceData.java index fe35c7da8c..9d444c925a 100644 --- a/sdk/src/main/java/com/bugsnag/android/DeviceData.java +++ b/sdk/src/main/java/com/bugsnag/android/DeviceData.java @@ -95,6 +95,7 @@ Map getDeviceDataSummary() { map.put("jailbroken", isRooted()); map.put("osName", "android"); map.put("osVersion", Build.VERSION.RELEASE); + map.put("cpuAbi", cpuAbi); return map; } @@ -123,7 +124,6 @@ Map getDeviceMetaData() { map.put("dpi", dpi); map.put("emulator", emulator); map.put("screenResolution", screenResolution); - map.put("cpuAbi", cpuAbi); return map; } diff --git a/sdk/src/main/java/com/bugsnag/android/Error.java b/sdk/src/main/java/com/bugsnag/android/Error.java index 246aa07f59..e623768c83 100644 --- a/sdk/src/main/java/com/bugsnag/android/Error.java +++ b/sdk/src/main/java/com/bugsnag/android/Error.java @@ -191,7 +191,7 @@ public Severity getSeverity() { * @param email the email address of the user * @param name the name of the user */ - public void setUser(String id, String email, String name) { + public void setUser(@Nullable String id, @Nullable String email, @Nullable String name) { this.user = new User(id, email, name); } @@ -212,7 +212,7 @@ public User getUser() { * * @param id the id of the user */ - public void setUserId(String id) { + public void setUserId(@Nullable String id) { this.user = new User(this.user); this.user.setId(id); } @@ -222,7 +222,7 @@ public void setUserId(String id) { * * @param email the email address of the user */ - public void setUserEmail(String email) { + public void setUserEmail(@Nullable String email) { this.user = new User(this.user); this.user.setEmail(email); } @@ -232,7 +232,7 @@ public void setUserEmail(String email) { * * @param name the name of the user */ - public void setUserName(String name) { + public void setUserName(@Nullable String name) { this.user = new User(this.user); this.user.setName(name); } @@ -250,7 +250,7 @@ public void setUserName(String name) { * @param key the name of the diagnostic information * @param value the contents of the diagnostic information */ - public void addToTab(String tabName, String key, Object value) { + public void addToTab(@NonNull String tabName, @NonNull String key, @Nullable Object value) { metaData.addToTab(tabName, key, value); } @@ -259,7 +259,7 @@ public void addToTab(String tabName, String key, Object value) { * * @param tabName the dashboard tab to remove diagnostic data from */ - public void clearTab(String tabName) { + public void clearTab(@NonNull String tabName) { metaData.clearTab(tabName); } @@ -299,6 +299,7 @@ public void setMetaData(@NonNull MetaData metaData) { /** * Get the class name from the exception contained in this Error report. */ + @NonNull public String getExceptionName() { if (exception instanceof BugsnagException) { return ((BugsnagException) exception).getName(); @@ -319,6 +320,7 @@ public String getExceptionMessage() { /** * The {@linkplain Throwable exception} which triggered this Error report. */ + @NonNull public Throwable getException() { return exception; } @@ -404,7 +406,7 @@ static class Builder { this.severityReasonType = HandledState.REASON_USER_SPECIFIED; // default if (session != null - && !config.shouldAutoCaptureSessions() && session.isAutoCaptured()) { + && !config.getAutoCaptureSessions() && session.isAutoCaptured()) { this.session = null; } else { this.session = session; diff --git a/sdk/src/main/java/com/bugsnag/android/ErrorReportApiClient.java b/sdk/src/main/java/com/bugsnag/android/ErrorReportApiClient.java index d3791806b8..9efd125bb2 100644 --- a/sdk/src/main/java/com/bugsnag/android/ErrorReportApiClient.java +++ b/sdk/src/main/java/com/bugsnag/android/ErrorReportApiClient.java @@ -1,5 +1,7 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + import java.util.Map; /** @@ -26,7 +28,9 @@ public interface ErrorReportApiClient { * @throws NetworkException if the client was unable to complete the request * @throws BadResponseException when a non-200 response code is received from the server */ - void postReport(String urlString, Report report, Map headers) + void postReport(@NonNull String urlString, + @NonNull Report report, + @NonNull Map headers) throws NetworkException, BadResponseException; } diff --git a/sdk/src/main/java/com/bugsnag/android/ErrorStore.java b/sdk/src/main/java/com/bugsnag/android/ErrorStore.java index 3f066cce36..e400321ecf 100644 --- a/sdk/src/main/java/com/bugsnag/android/ErrorStore.java +++ b/sdk/src/main/java/com/bugsnag/android/ErrorStore.java @@ -26,7 +26,7 @@ class ErrorStore extends FileStore { private static final long LAUNCH_CRASH_TIMEOUT_MS = 2000; private static final int LAUNCH_CRASH_POLL_MS = 50; - private volatile boolean flushOnLaunchCompleted = false; + volatile boolean flushOnLaunchCompleted = false; private final Semaphore semaphore = new Semaphore(1); static final Comparator ERROR_REPORT_COMPARATOR = new Comparator() { @@ -116,7 +116,7 @@ public void run() { } } - private void flushReports(Collection storedReports) { + void flushReports(Collection storedReports) { if (!storedReports.isEmpty() && semaphore.tryAcquire(1)) { try { Logger.info(String.format(Locale.US, diff --git a/sdk/src/main/java/com/bugsnag/android/EventReceiver.java b/sdk/src/main/java/com/bugsnag/android/EventReceiver.java index bf877b75f6..40820064a3 100644 --- a/sdk/src/main/java/com/bugsnag/android/EventReceiver.java +++ b/sdk/src/main/java/com/bugsnag/android/EventReceiver.java @@ -25,12 +25,12 @@ public class EventReceiver extends BroadcastReceiver { private final Client client; - public EventReceiver(Client client) { + public EventReceiver(@NonNull Client client) { this.client = client; } @Override - public void onReceive(Context context, @NonNull Intent intent) { + public void onReceive(@NonNull Context context, @NonNull Intent intent) { try { Map meta = new HashMap<>(); String fullAction = intent.getAction(); diff --git a/sdk/src/main/java/com/bugsnag/android/JsonStream.java b/sdk/src/main/java/com/bugsnag/android/JsonStream.java index 291126cbf8..89bd103456 100644 --- a/sdk/src/main/java/com/bugsnag/android/JsonStream.java +++ b/sdk/src/main/java/com/bugsnag/android/JsonStream.java @@ -26,7 +26,7 @@ public interface Streamable { * * @param out the writer */ - public JsonStream(Writer out) { + public JsonStream(@NonNull Writer out) { super(out); setSerializeNulls(false); this.out = out; diff --git a/sdk/src/main/java/com/bugsnag/android/MetaData.java b/sdk/src/main/java/com/bugsnag/android/MetaData.java index 4b440fe9db..026bcbdc20 100644 --- a/sdk/src/main/java/com/bugsnag/android/MetaData.java +++ b/sdk/src/main/java/com/bugsnag/android/MetaData.java @@ -57,7 +57,7 @@ public void toStream(@NonNull JsonStream writer) throws IOException { * @param key the name of the diagnostic information * @param value the contents of the diagnostic information */ - public void addToTab(String tabName, String key, Object value) { + public void addToTab(@NonNull String tabName, @NonNull String key, @Nullable Object value) { Map tab = getTab(tabName); setChanged(); if (value != null) { @@ -78,7 +78,7 @@ public void addToTab(String tabName, String key, Object value) { * * @param tabName the dashboard tab to remove diagnostic data from */ - public void clearTab(String tabName) { + public void clearTab(@NonNull String tabName) { store.remove(tabName); setChanged(); notifyObservers(new NativeInterface.Message( diff --git a/sdk/src/main/java/com/bugsnag/android/NativeInterface.java b/sdk/src/main/java/com/bugsnag/android/NativeInterface.java index 7a7fd19b63..4f552b234f 100644 --- a/sdk/src/main/java/com/bugsnag/android/NativeInterface.java +++ b/sdk/src/main/java/com/bugsnag/android/NativeInterface.java @@ -1,14 +1,16 @@ package com.bugsnag.android; -import static com.bugsnag.android.MapUtils.getStringFromMap; - import android.annotation.SuppressLint; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Observer; +import java.util.Queue; /** * Used as the entry point for native code to allow proguard to obfuscate other areas if needed @@ -114,10 +116,14 @@ public enum MessageType { * Wrapper for messages sent to native observers */ public static class Message { + + @NonNull public final MessageType type; + + @Nullable public final Object value; - public Message(MessageType type, Object value) { + public Message(@NonNull MessageType type, @Nullable Object value) { this.type = type; this.value = value; } @@ -172,6 +178,7 @@ public static void configureClientObservers(@NonNull Client client) { client.sendNativeSetupNotification(); } + @Nullable public static String getContext() { return getClient().getContext(); } @@ -180,6 +187,7 @@ public static boolean getLoggingEnabled() { return Logger.getEnabled(); } + @NonNull public static String getNativeReportPath() { return getClient().appContext.getCacheDir().getAbsolutePath() + "/bugsnag-native/"; } @@ -225,9 +233,21 @@ public static Map getDeviceData() { return deviceData; } + /** + * Retrieves global metadata from the static Client instance as a Map + */ @NonNull public static Map getMetaData() { - return getClient().getMetaData().store; + return new HashMap<>(getClient().getMetaData().store); + } + + /** + * Retrieves breadcrumbs from the static Client instance as a Map + */ + @NonNull + public static List getBreadcrumbs() { + Queue store = getClient().breadcrumbs.store; + return new ArrayList<>(store); } /** @@ -238,9 +258,9 @@ public static Map getMetaData() { * @param name name */ @SuppressWarnings("unused") - public static void setUser(final String id, - final String email, - final String name) { + public static void setUser(@Nullable final String id, + @Nullable final String email, + @Nullable final String name) { Client client = getClient(); client.setUserId(id); client.setUserEmail(email); @@ -255,15 +275,117 @@ public static void leaveBreadcrumb(@NonNull final String name, getClient().leaveBreadcrumb(name, type, new HashMap()); } + /** + * Leaves a breadcrumb on the static client instance + */ + public static void leaveBreadcrumb(@NonNull String name, + @NonNull String type, + @NonNull Map metadata) { + String typeName = type.toUpperCase(Locale.US); + Map map = metadata == null ? new HashMap() : metadata; + getClient().leaveBreadcrumb(name, BreadcrumbType.valueOf(typeName), map); + } + /** * Add metadata to subsequent exception reports */ - public static void addToTab(final String tab, - final String key, - final Object value) { + public static void addToTab(@NonNull final String tab, + @NonNull final String key, + @Nullable final Object value) { getClient().addToTab(tab, key, value); } + /** + * Set the client report release stage + */ + public static void setReleaseStage(@Nullable final String stage) { + getClient().setReleaseStage(stage); + } + + /** + * Return the client report release stage + */ + @Nullable + public static String getReleaseStage() { + return getClient().getConfig().getReleaseStage(); + } + + /** + * Return the client session endpoint + */ + @NonNull + public static String getSessionEndpoint() { + return getClient().getConfig().getSessionEndpoint(); + } + + /** + * Return the client report endpoint + */ + @NonNull + public static String getEndpoint() { + return getClient().getConfig().getEndpoint(); + } + + /** + * Set the client session endpoint + */ + @SuppressWarnings("deprecation") + public static void setSessionEndpoint(@NonNull final String endpoint) { + getClient().getConfig().setSessionEndpoint(endpoint); + } + + /** + * Set the client report endpoint + */ + @SuppressWarnings("deprecation") + public static void setEndpoint(@NonNull final String endpoint) { + getClient().getConfig().setEndpoint(endpoint); + } + + /** + * Set the client report context + */ + public static void setContext(@Nullable final String context) { + getClient().setContext(context); + } + + /** + * Set the client report app version + */ + public static void setAppVersion(@NonNull final String version) { + getClient().setAppVersion(version); + } + + /** + * Set the binary arch used in the application + */ + public static void setBinaryArch(@NonNull final String binaryArch) { + getClient().setBinaryArch(binaryArch); + } + + /** + * Return the client report app version + */ + @NonNull + public static String getAppVersion() { + return getClient().getConfig().getAppVersion(); + } + + /** + * Return which release stages notify + */ + @Nullable + public static String[] getNotifyReleaseStages() { + return getClient().getConfig().getNotifyReleaseStages(); + } + + /** + * Set which release stages notify + */ + public static void setNotifyReleaseStages(@Nullable String[] notifyReleaseStages) { + getClient().getConfig().setNotifyReleaseStages(notifyReleaseStages); + } + /** * Deliver a report, serialized as an event JSON payload. * @@ -272,7 +394,7 @@ public static void addToTab(final String tab, * stages */ @SuppressWarnings("unused") - public static void deliverReport(String releaseStage, String payload) { + public static void deliverReport(@Nullable String releaseStage, @NonNull String payload) { Client client = getClient(); if (releaseStage == null || releaseStage.length() == 0 @@ -292,7 +414,7 @@ public static void deliverReport(String releaseStage, String payload) { */ public static void notify(@NonNull final String name, @NonNull final String message, - final Severity severity, + @NonNull final Severity severity, @NonNull final StackTraceElement[] stacktrace) { getClient().notify(name, message, stacktrace, new Callback() { diff --git a/sdk/src/main/java/com/bugsnag/android/NetworkException.java b/sdk/src/main/java/com/bugsnag/android/NetworkException.java index 3c08e17d48..d8d06ba493 100644 --- a/sdk/src/main/java/com/bugsnag/android/NetworkException.java +++ b/sdk/src/main/java/com/bugsnag/android/NetworkException.java @@ -1,5 +1,8 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + import java.io.IOException; /** @@ -10,7 +13,7 @@ public class NetworkException extends IOException { private static final long serialVersionUID = -4370366096145029322L; - public NetworkException(String msg, Throwable cause) { + public NetworkException(@NonNull String msg, @Nullable Throwable cause) { super(msg, cause); } } diff --git a/sdk/src/main/java/com/bugsnag/android/Notifier.java b/sdk/src/main/java/com/bugsnag/android/Notifier.java index b6b00c3ba2..261432e1d2 100644 --- a/sdk/src/main/java/com/bugsnag/android/Notifier.java +++ b/sdk/src/main/java/com/bugsnag/android/Notifier.java @@ -10,7 +10,7 @@ public class Notifier implements JsonStream.Streamable { private static final String NOTIFIER_NAME = "Android Bugsnag Notifier"; - private static final String NOTIFIER_VERSION = "4.9.3"; + private static final String NOTIFIER_VERSION = "4.10.0"; private static final String NOTIFIER_URL = "https://bugsnag.com"; @NonNull diff --git a/sdk/src/main/java/com/bugsnag/android/NotifyType.java b/sdk/src/main/java/com/bugsnag/android/NotifyType.java index 9a9035c31c..f1f19e06ac 100644 --- a/sdk/src/main/java/com/bugsnag/android/NotifyType.java +++ b/sdk/src/main/java/com/bugsnag/android/NotifyType.java @@ -1,5 +1,6 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; /** @@ -23,6 +24,7 @@ public enum NotifyType { this.intValue = intValue; } + @NonNull public Integer getValue() { return intValue; } diff --git a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java index 43f44b8d21..07d72dabd3 100644 --- a/sdk/src/main/java/com/bugsnag/android/SessionTracker.java +++ b/sdk/src/main/java/com/bugsnag/android/SessionTracker.java @@ -30,10 +30,11 @@ class SessionTracker extends Observable implements Application.ActivityLifecycle private final Collection foregroundActivities = new ConcurrentLinkedQueue<>(); - private final Configuration configuration; private final long timeoutMs; - private final Client client; - private final SessionStore sessionStore; + + final Configuration configuration; + final Client client; + final SessionStore sessionStore; // This most recent time an Activity was stopped. private AtomicLong lastExitedForegroundMs = new AtomicLong(0); @@ -58,7 +59,7 @@ class SessionTracker extends Observable implements Application.ActivityLifecycle /** * Starts a new session with the given date and user. *

- * A session will only be created if {@link Configuration#shouldAutoCaptureSessions()} returns + * A session will only be created if {@link Configuration#getAutoCaptureSessions()} returns * true. * * @param date the session start date @@ -87,7 +88,7 @@ private void trackSessionIfNeeded(final Session session) { boolean notifyForRelease = configuration.shouldNotifyForReleaseStage(getReleaseStage()); if (notifyForRelease - && (configuration.shouldAutoCaptureSessions() || !session.isAutoCaptured()) + && (configuration.getAutoCaptureSessions() || !session.isAutoCaptured()) && session.isTracked().compareAndSet(false, true)) { try { final String endpoint = configuration.getSessionEndpoint(); @@ -289,7 +290,7 @@ void updateForegroundTracker(String activityName, boolean activityStarting, long lastEnteredForegroundMs.set(nowMs); if (noActivityRunningForMs >= timeoutMs - && configuration.shouldAutoCaptureSessions()) { + && configuration.getAutoCaptureSessions()) { startNewSession(new Date(nowMs), client.getUser(), true); } } diff --git a/sdk/src/main/java/com/bugsnag/android/SessionTrackingApiClient.java b/sdk/src/main/java/com/bugsnag/android/SessionTrackingApiClient.java index 173cdb0f1f..d270df90a6 100644 --- a/sdk/src/main/java/com/bugsnag/android/SessionTrackingApiClient.java +++ b/sdk/src/main/java/com/bugsnag/android/SessionTrackingApiClient.java @@ -1,5 +1,7 @@ package com.bugsnag.android; +import android.support.annotation.NonNull; + import java.util.Map; /** @@ -22,9 +24,9 @@ public interface SessionTrackingApiClient { * @throws NetworkException if the client was unable to complete the request * @throws BadResponseException when a non-202 response code is received from the server */ - void postSessionTrackingPayload(String urlString, - SessionTrackingPayload payload, - Map headers) + void postSessionTrackingPayload(@NonNull String urlString, + @NonNull SessionTrackingPayload payload, + @NonNull Map headers) throws NetworkException, BadResponseException; } diff --git a/sdk/src/main/java/com/bugsnag/android/Severity.java b/sdk/src/main/java/com/bugsnag/android/Severity.java index 09bfb3da52..5d300875dc 100644 --- a/sdk/src/main/java/com/bugsnag/android/Severity.java +++ b/sdk/src/main/java/com/bugsnag/android/Severity.java @@ -39,6 +39,7 @@ static Severity fromString(String input) { } } + @NonNull public String getName() { return name; }