Updated Bugsnag to v5.30.0

pull/213/head
M66B 1 year ago
parent 03de3b55c9
commit 21c71ffcc8

@ -3,47 +3,56 @@ package com.bugsnag.android
import android.app.Activity import android.app.Activity
import android.app.Application import android.app.Application
import android.os.Bundle import android.os.Bundle
import java.util.WeakHashMap
internal class ActivityBreadcrumbCollector( internal class ActivityBreadcrumbCollector(
private val cb: (message: String, method: Map<String, Any>) -> Unit private val cb: (message: String, method: Map<String, Any>) -> Unit
) : Application.ActivityLifecycleCallbacks { ) : Application.ActivityLifecycleCallbacks {
var prevState: String? = null private val prevState = WeakHashMap<Activity, String>()
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) = override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) =
leaveBreadcrumb(getActivityName(activity), "onCreate()", savedInstanceState != null) leaveBreadcrumb(activity, "onCreate()", savedInstanceState != null)
override fun onActivityStarted(activity: Activity) = override fun onActivityStarted(activity: Activity) =
leaveBreadcrumb(getActivityName(activity), "onStart()") leaveBreadcrumb(activity, "onStart()")
override fun onActivityResumed(activity: Activity) = override fun onActivityResumed(activity: Activity) =
leaveBreadcrumb(getActivityName(activity), "onResume()") leaveBreadcrumb(activity, "onResume()")
override fun onActivityPaused(activity: Activity) = override fun onActivityPaused(activity: Activity) =
leaveBreadcrumb(getActivityName(activity), "onPause()") leaveBreadcrumb(activity, "onPause()")
override fun onActivityStopped(activity: Activity) = override fun onActivityStopped(activity: Activity) =
leaveBreadcrumb(getActivityName(activity), "onStop()") leaveBreadcrumb(activity, "onStop()")
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) =
leaveBreadcrumb(getActivityName(activity), "onSaveInstanceState()") leaveBreadcrumb(activity, "onSaveInstanceState()")
override fun onActivityDestroyed(activity: Activity) = override fun onActivityDestroyed(activity: Activity) {
leaveBreadcrumb(getActivityName(activity), "onDestroy()") leaveBreadcrumb(activity, "onDestroy()")
prevState.remove(activity)
}
private fun getActivityName(activity: Activity) = activity.javaClass.simpleName private fun getActivityName(activity: Activity) = activity.javaClass.simpleName
private fun leaveBreadcrumb(activityName: String, lifecycleCallback: String, hasBundle: Boolean? = null) { private fun leaveBreadcrumb(
activity: Activity,
lifecycleCallback: String,
hasBundle: Boolean? = null
) {
val metadata = mutableMapOf<String, Any>() val metadata = mutableMapOf<String, Any>()
if (hasBundle != null) { if (hasBundle != null) {
metadata["hasBundle"] = hasBundle metadata["hasBundle"] = hasBundle
} }
val previousVal = prevState val previousVal = prevState[activity]
if (previousVal != null) { if (previousVal != null) {
metadata["previous"] = previousVal metadata["previous"] = previousVal
} }
val activityName = getActivityName(activity)
cb("$activityName#$lifecycleCallback", metadata) cb("$activityName#$lifecycleCallback", metadata)
prevState = lifecycleCallback prevState[activity] = lifecycleCallback
} }
} }

@ -2,11 +2,13 @@ package com.bugsnag.android;
import static com.bugsnag.android.SeverityReason.REASON_HANDLED_EXCEPTION; import static com.bugsnag.android.SeverityReason.REASON_HANDLED_EXCEPTION;
import com.bugsnag.android.internal.BackgroundTaskService;
import com.bugsnag.android.internal.ImmutableConfig; import com.bugsnag.android.internal.ImmutableConfig;
import com.bugsnag.android.internal.InternalMetrics; import com.bugsnag.android.internal.InternalMetrics;
import com.bugsnag.android.internal.InternalMetricsImpl; import com.bugsnag.android.internal.InternalMetricsImpl;
import com.bugsnag.android.internal.InternalMetricsNoop; import com.bugsnag.android.internal.InternalMetricsNoop;
import com.bugsnag.android.internal.StateObserver; import com.bugsnag.android.internal.StateObserver;
import com.bugsnag.android.internal.TaskType;
import com.bugsnag.android.internal.dag.ConfigModule; import com.bugsnag.android.internal.dag.ConfigModule;
import com.bugsnag.android.internal.dag.ContextModule; import com.bugsnag.android.internal.dag.ContextModule;
import com.bugsnag.android.internal.dag.SystemServiceModule; import com.bugsnag.android.internal.dag.SystemServiceModule;
@ -303,7 +305,7 @@ public class Client implements MetadataAware, CallbackAware, UserAware, FeatureF
registerListenersInBackground(); registerListenersInBackground();
// Leave auto breadcrumb // Leave auto breadcrumb
Map<String, Object> data = Collections.emptyMap(); Map<String, Object> data = new HashMap<>();
leaveAutoBreadcrumb("Bugsnag loaded", BreadcrumbType.STATE, data); leaveAutoBreadcrumb("Bugsnag loaded", BreadcrumbType.STATE, data);
logger.d("Bugsnag loaded"); logger.d("Bugsnag loaded");

@ -2,6 +2,7 @@ package com.bugsnag.android;
import android.content.Context; import android.content.Context;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@ -305,7 +306,7 @@ public class Configuration implements CallbackAware, MetadataAware, UserAware, F
* By default, this value is set at 5,000ms. Setting the value to 0 will count all crashes * By default, this value is set at 5,000ms. Setting the value to 0 will count all crashes
* as launch crashes until markLaunchCompleted() is called. * as launch crashes until markLaunchCompleted() is called.
*/ */
public void setLaunchDurationMillis(long launchDurationMillis) { public void setLaunchDurationMillis(@IntRange(from = 0) long launchDurationMillis) {
if (launchDurationMillis >= MIN_LAUNCH_CRASH_THRESHOLD_MS) { if (launchDurationMillis >= MIN_LAUNCH_CRASH_THRESHOLD_MS) {
impl.setLaunchDurationMillis(launchDurationMillis); impl.setLaunchDurationMillis(launchDurationMillis);
} else { } else {
@ -524,12 +525,12 @@ public class Configuration implements CallbackAware, MetadataAware, UserAware, F
* *
* By default, 100 breadcrumbs are stored: this can be amended up to a maximum of 500. * By default, 100 breadcrumbs are stored: this can be amended up to a maximum of 500.
*/ */
public void setMaxBreadcrumbs(int maxBreadcrumbs) { public void setMaxBreadcrumbs(@IntRange(from = 0, to = 500) int maxBreadcrumbs) {
if (maxBreadcrumbs >= MIN_BREADCRUMBS && maxBreadcrumbs <= MAX_BREADCRUMBS) { if (maxBreadcrumbs >= MIN_BREADCRUMBS && maxBreadcrumbs <= MAX_BREADCRUMBS) {
impl.setMaxBreadcrumbs(maxBreadcrumbs); impl.setMaxBreadcrumbs(maxBreadcrumbs);
} else { } else {
getLogger().e("Invalid configuration value detected. " getLogger().e("Invalid configuration value detected. "
+ "Option maxBreadcrumbs should be an integer between 0-100. " + "Option maxBreadcrumbs should be an integer between 0-500. "
+ "Supplied value is " + maxBreadcrumbs); + "Supplied value is " + maxBreadcrumbs);
} }
} }
@ -550,7 +551,7 @@ public class Configuration implements CallbackAware, MetadataAware, UserAware, F
* *
* By default, 32 events are persisted. * By default, 32 events are persisted.
*/ */
public void setMaxPersistedEvents(int maxPersistedEvents) { public void setMaxPersistedEvents(@IntRange(from = 0) int maxPersistedEvents) {
if (maxPersistedEvents >= 0) { if (maxPersistedEvents >= 0) {
impl.setMaxPersistedEvents(maxPersistedEvents); impl.setMaxPersistedEvents(maxPersistedEvents);
} else { } else {
@ -576,7 +577,7 @@ public class Configuration implements CallbackAware, MetadataAware, UserAware, F
* *
* By default, up to 200 threads are reported. * By default, up to 200 threads are reported.
*/ */
public void setMaxReportedThreads(int maxReportedThreads) { public void setMaxReportedThreads(@IntRange(from = 0) int maxReportedThreads) {
if (maxReportedThreads >= 0) { if (maxReportedThreads >= 0) {
impl.setMaxReportedThreads(maxReportedThreads); impl.setMaxReportedThreads(maxReportedThreads);
} else { } else {
@ -602,7 +603,7 @@ public class Configuration implements CallbackAware, MetadataAware, UserAware, F
* *
* By default, 128 sessions are persisted. * By default, 128 sessions are persisted.
*/ */
public void setMaxPersistedSessions(int maxPersistedSessions) { public void setMaxPersistedSessions(@IntRange(from = 0) int maxPersistedSessions) {
if (maxPersistedSessions >= 0) { if (maxPersistedSessions >= 0) {
impl.setMaxPersistedSessions(maxPersistedSessions); impl.setMaxPersistedSessions(maxPersistedSessions);
} else { } else {
@ -628,7 +629,7 @@ public class Configuration implements CallbackAware, MetadataAware, UserAware, F
* *
* By default, the limit is 10,000. * By default, the limit is 10,000.
*/ */
public void setMaxStringValueLength(int maxStringValueLength) { public void setMaxStringValueLength(@IntRange(from = 0) int maxStringValueLength) {
if (maxStringValueLength >= 0) { if (maxStringValueLength >= 0) {
impl.setMaxStringValueLength(maxStringValueLength); impl.setMaxStringValueLength(maxStringValueLength);
} else { } else {

@ -1,6 +1,7 @@
package com.bugsnag.android package com.bugsnag.android
import android.os.Environment import android.os.Environment
import com.bugsnag.android.internal.BackgroundTaskService
import com.bugsnag.android.internal.dag.ConfigModule import com.bugsnag.android.internal.dag.ConfigModule
import com.bugsnag.android.internal.dag.ContextModule import com.bugsnag.android.internal.dag.ContextModule
import com.bugsnag.android.internal.dag.DependencyModule import com.bugsnag.android.internal.dag.DependencyModule

@ -2,7 +2,9 @@ package com.bugsnag.android;
import static com.bugsnag.android.SeverityReason.REASON_PROMISE_REJECTION; import static com.bugsnag.android.SeverityReason.REASON_PROMISE_REJECTION;
import com.bugsnag.android.internal.BackgroundTaskService;
import com.bugsnag.android.internal.ImmutableConfig; import com.bugsnag.android.internal.ImmutableConfig;
import com.bugsnag.android.internal.TaskType;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;

@ -11,6 +11,8 @@ import android.content.res.Resources
import android.os.BatteryManager import android.os.BatteryManager
import android.os.Build import android.os.Build
import android.provider.Settings import android.provider.Settings
import com.bugsnag.android.internal.BackgroundTaskService
import com.bugsnag.android.internal.TaskType
import java.io.File import java.io.File
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale

@ -1,5 +1,6 @@
package com.bugsnag.android package com.bugsnag.android
import com.bugsnag.android.internal.BackgroundTaskService
import com.bugsnag.android.internal.dag.ConfigModule import com.bugsnag.android.internal.dag.ConfigModule
import com.bugsnag.android.internal.dag.ContextModule import com.bugsnag.android.internal.dag.ContextModule
import com.bugsnag.android.internal.dag.DependencyModule import com.bugsnag.android.internal.dag.DependencyModule

@ -1,6 +1,8 @@
package com.bugsnag.android; package com.bugsnag.android;
import com.bugsnag.android.internal.BackgroundTaskService;
import com.bugsnag.android.internal.ImmutableConfig; import com.bugsnag.android.internal.ImmutableConfig;
import com.bugsnag.android.internal.TaskType;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;

@ -3,8 +3,10 @@ package com.bugsnag.android;
import static com.bugsnag.android.DeliveryHeadersKt.HEADER_INTERNAL_ERROR; import static com.bugsnag.android.DeliveryHeadersKt.HEADER_INTERNAL_ERROR;
import static com.bugsnag.android.SeverityReason.REASON_UNHANDLED_EXCEPTION; import static com.bugsnag.android.SeverityReason.REASON_UNHANDLED_EXCEPTION;
import com.bugsnag.android.internal.BackgroundTaskService;
import com.bugsnag.android.internal.ImmutableConfig; import com.bugsnag.android.internal.ImmutableConfig;
import com.bugsnag.android.internal.JsonHelper; import com.bugsnag.android.internal.JsonHelper;
import com.bugsnag.android.internal.TaskType;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;

@ -1,5 +1,7 @@
package com.bugsnag.android; package com.bugsnag.android;
import com.bugsnag.android.internal.TaskType;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
class LibraryLoader { class LibraryLoader {

@ -265,6 +265,14 @@ public class NativeInterface {
getClient().addMetadata(tab, key, value); getClient().addMetadata(tab, key, value);
} }
/**
* Add metadata to subsequent exception reports with a Hashmap
*/
public static void addMetadata(@NonNull final String tab,
@NonNull final Map<String, ?> metadata) {
getClient().addMetadata(tab, metadata);
}
/** /**
* Return the client report release stage * Return the client report release stage
*/ */

@ -7,7 +7,7 @@ import java.io.IOException
*/ */
class Notifier @JvmOverloads constructor( class Notifier @JvmOverloads constructor(
var name: String = "Android Bugsnag Notifier", var name: String = "Android Bugsnag Notifier",
var version: String = "5.28.2", var version: String = "5.30.0",
var url: String = "https://bugsnag.com" var url: String = "https://bugsnag.com"
) : JsonStream.Streamable { ) : JsonStream.Streamable {

@ -15,10 +15,9 @@ internal class PluginClient(
} }
private val plugins: Set<Plugin> private val plugins: Set<Plugin>
private val ndkPlugin = instantiatePlugin(NDK_PLUGIN, immutableConfig.enabledErrorTypes.ndkCrashes)
private val ndkPlugin = instantiatePlugin(NDK_PLUGIN) private val anrPlugin = instantiatePlugin(ANR_PLUGIN, immutableConfig.enabledErrorTypes.anrs)
private val anrPlugin = instantiatePlugin(ANR_PLUGIN) private val rnPlugin = instantiatePlugin(RN_PLUGIN, immutableConfig.enabledErrorTypes.unhandledRejections)
private val rnPlugin = instantiatePlugin(RN_PLUGIN)
init { init {
val set = mutableSetOf<Plugin>() val set = mutableSetOf<Plugin>()
@ -32,12 +31,14 @@ internal class PluginClient(
plugins = set.toSet() plugins = set.toSet()
} }
private fun instantiatePlugin(clz: String): Plugin? { private fun instantiatePlugin(clz: String, isWarningEnabled: Boolean): Plugin? {
return try { return try {
val pluginClz = Class.forName(clz) val pluginClz = Class.forName(clz)
pluginClz.newInstance() as Plugin pluginClz.newInstance() as Plugin
} catch (exc: ClassNotFoundException) { } catch (exc: ClassNotFoundException) {
logger.d("Plugin '$clz' is not on the classpath - functionality will not be enabled.") if (isWarningEnabled) {
logger.d("Plugin '$clz' is not on the classpath - functionality will not be enabled.")
}
null null
} catch (exc: Throwable) { } catch (exc: Throwable) {
logger.e("Failed to load plugin '$clz'", exc) logger.e("Failed to load plugin '$clz'", exc)

@ -1,10 +1,9 @@
package com.bugsnag.android package com.bugsnag.android
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean import java.io.Reader
/** /**
* Attempts to detect whether the device is rooted. Root detection errs on the side of false * Attempts to detect whether the device is rooted. Root detection errs on the side of false
@ -41,12 +40,13 @@ internal class RootDetector @JvmOverloads constructor(
) )
} }
private val libraryLoaded = AtomicBoolean(false) @Volatile
private var libraryLoaded = false
init { init {
try { try {
System.loadLibrary("bugsnag-root-detection") System.loadLibrary("bugsnag-root-detection")
libraryLoaded.set(true) libraryLoaded = true
} catch (ignored: UnsatisfiedLinkError) { } catch (ignored: UnsatisfiedLinkError) {
// library couldn't load. This could be due to root detection countermeasures, // library couldn't load. This could be due to root detection countermeasures,
// or down to genuine OS level bugs with library loading - in either case // or down to genuine OS level bugs with library loading - in either case
@ -107,7 +107,7 @@ internal class RootDetector @JvmOverloads constructor(
line.replace("\\s".toRegex(), "") line.replace("\\s".toRegex(), "")
}.filter { line -> }.filter { line ->
line.startsWith("ro.debuggable=[1]") || line.startsWith("ro.secure=[0]") line.startsWith("ro.debuggable=[1]") || line.startsWith("ro.secure=[0]")
}.count() > 0 }.any()
} }
} }
return false return false
@ -120,8 +120,7 @@ internal class RootDetector @JvmOverloads constructor(
var process: Process? = null var process: Process? = null
return try { return try {
process = processBuilder.start() process = processBuilder.start()
val output = process.inputStream.bufferedReader().use(BufferedReader::readText) process.inputStream.bufferedReader().use { it.isNotBlank() }
output.isNotBlank()
} catch (ignored: IOException) { } catch (ignored: IOException) {
false false
} finally { } finally {
@ -131,11 +130,21 @@ internal class RootDetector @JvmOverloads constructor(
private external fun performNativeRootChecks(): Boolean private external fun performNativeRootChecks(): Boolean
private fun Reader.isNotBlank(): Boolean {
while (true) {
val ch = read()
when {
ch == -1 -> return false
!ch.toChar().isWhitespace() -> return true
}
}
}
/** /**
* Performs root checks which require native code. * Performs root checks which require native code.
*/ */
private fun nativeCheckRoot(): Boolean = when { private fun nativeCheckRoot(): Boolean = when {
libraryLoaded.get() -> performNativeRootChecks() libraryLoaded -> performNativeRootChecks()
else -> false else -> false
} }
} }

@ -1,7 +1,9 @@
package com.bugsnag.android; package com.bugsnag.android;
import com.bugsnag.android.internal.BackgroundTaskService;
import com.bugsnag.android.internal.DateUtils; import com.bugsnag.android.internal.DateUtils;
import com.bugsnag.android.internal.ImmutableConfig; import com.bugsnag.android.internal.ImmutableConfig;
import com.bugsnag.android.internal.TaskType;
import android.os.SystemClock; import android.os.SystemClock;
@ -10,22 +12,21 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import java.io.File; import java.io.File;
import java.util.Collection; import java.util.ArrayDeque;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Deque;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
class SessionTracker extends BaseObservable { class SessionTracker extends BaseObservable {
private static final int DEFAULT_TIMEOUT_MS = 30000; private static final int DEFAULT_TIMEOUT_MS = 30000;
private final Collection<String> private final Deque<String>
foregroundActivities = new ConcurrentLinkedQueue<>(); foregroundActivities = new ArrayDeque<>();
private final long timeoutMs; private final long timeoutMs;
private final ImmutableConfig configuration; private final ImmutableConfig configuration;
@ -132,7 +133,7 @@ class SessionTracker extends BaseObservable {
private void notifySessionStartObserver(final Session session) { private void notifySessionStartObserver(final Session session) {
final String startedAt = DateUtils.toIso8601(session.getStartedAt()); final String startedAt = DateUtils.toIso8601(session.getStartedAt());
updateState(new StateEvent.StartSession(session.getId(), startedAt, updateState(new StateEvent.StartSession(session.getId(), startedAt,
session.getHandledCount(), session.getUnhandledCount())); session.getHandledCount(), session.getUnhandledCount()));
} }
/** /**
@ -358,22 +359,23 @@ class SessionTracker extends BaseObservable {
void updateForegroundTracker(String activityName, boolean activityStarting, long nowMs) { void updateForegroundTracker(String activityName, boolean activityStarting, long nowMs) {
if (activityStarting) { if (activityStarting) {
long noActivityRunningForMs = nowMs - lastExitedForegroundMs.get(); long noActivityRunningForMs = nowMs - lastExitedForegroundMs.get();
synchronized (foregroundActivities) {
//FUTURE:SM Race condition between isEmpty and put if (foregroundActivities.isEmpty()) {
if (foregroundActivities.isEmpty()) { lastEnteredForegroundMs.set(nowMs);
lastEnteredForegroundMs.set(nowMs);
if (noActivityRunningForMs >= timeoutMs
if (noActivityRunningForMs >= timeoutMs && configuration.getAutoTrackSessions()) {
&& configuration.getAutoTrackSessions()) { startNewSession(new Date(), client.getUser(), true);
startNewSession(new Date(), client.getUser(), true); }
} }
foregroundActivities.add(activityName);
} }
foregroundActivities.add(activityName);
} else { } else {
foregroundActivities.remove(activityName); synchronized (foregroundActivities) {
foregroundActivities.removeLastOccurrence(activityName);
if (foregroundActivities.isEmpty()) { if (foregroundActivities.isEmpty()) {
lastExitedForegroundMs.set(nowMs); lastExitedForegroundMs.set(nowMs);
}
} }
} }
client.getContextState().setAutomaticContext(getContextActivity()); client.getContextState().setAutomaticContext(getContextActivity());
@ -397,14 +399,8 @@ class SessionTracker extends BaseObservable {
@Nullable @Nullable
String getContextActivity() { String getContextActivity() {
if (foregroundActivities.isEmpty()) { synchronized (foregroundActivities) {
return null; return foregroundActivities.peekLast();
} else {
// linked hash set retains order of added activity and ensures uniqueness
// therefore obtain the most recently added
int size = foregroundActivities.size();
String[] activities = foregroundActivities.toArray(new String[size]);
return activities[size - 1];
} }
} }
} }

@ -1,5 +1,6 @@
package com.bugsnag.android package com.bugsnag.android
import com.bugsnag.android.internal.BackgroundTaskService
import com.bugsnag.android.internal.dag.ConfigModule import com.bugsnag.android.internal.dag.ConfigModule
import com.bugsnag.android.internal.dag.DependencyModule import com.bugsnag.android.internal.dag.DependencyModule

@ -1,4 +1,4 @@
package com.bugsnag.android package com.bugsnag.android.internal
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import java.util.concurrent.BlockingQueue import java.util.concurrent.BlockingQueue
@ -18,7 +18,7 @@ import java.lang.Thread as JThread
* The type of task which is being submitted. This determines which execution queue * The type of task which is being submitted. This determines which execution queue
* the task will be added to. * the task will be added to.
*/ */
internal enum class TaskType { enum class TaskType {
/** /**
* A task that sends an error request. Any filesystem operations * A task that sends an error request. Any filesystem operations
@ -91,7 +91,7 @@ internal fun createExecutor(name: String, type: TaskType, keepAlive: Boolean): E
* It also avoids short-running operations being held up by long-running operations submitted * It also avoids short-running operations being held up by long-running operations submitted
* to the same executor. * to the same executor.
*/ */
internal class BackgroundTaskService( class BackgroundTaskService(
// these executors must remain single-threaded - the SDK makes assumptions // these executors must remain single-threaded - the SDK makes assumptions
// about synchronization based on this. // about synchronization based on this.
@get:VisibleForTesting @get:VisibleForTesting

@ -1,7 +1,7 @@
package com.bugsnag.android.internal.dag package com.bugsnag.android.internal.dag
import com.bugsnag.android.BackgroundTaskService import com.bugsnag.android.internal.BackgroundTaskService
import com.bugsnag.android.TaskType import com.bugsnag.android.internal.TaskType
internal abstract class DependencyModule { internal abstract class DependencyModule {

@ -10,7 +10,7 @@ buildscript {
classpath 'com.android.tools.build:gradle:8.0.1' classpath 'com.android.tools.build:gradle:8.0.1'
// https://github.com/bugsnag/bugsnag-android-gradle-plugin // https://github.com/bugsnag/bugsnag-android-gradle-plugin
// https://mvnrepository.com/artifact/com.bugsnag/bugsnag-android-gradle-plugin // https://mvnrepository.com/artifact/com.bugsnag/bugsnag-android-gradle-plugin
classpath "com.bugsnag:bugsnag-android-gradle-plugin:7.3.1" classpath "com.bugsnag:bugsnag-android-gradle-plugin:8.0.1"
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-gradle-plugin // https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-gradle-plugin
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:1.8.20" classpath "org.jetbrains.kotlin:kotlin-android-extensions:1.8.20"

Loading…
Cancel
Save