# Migration Guide

## Migrating between versions of Sentry's SDK for Android.

## [Migrating from `io.sentry:sentry` `7.x` to `io.sentry:sentry` `8.0.0`](#migrating-from-iosentrysentry-7x-to-iosentrysentry-800)

### [Breaking Changes](#breaking-changes)

* `Contexts` no longer extends `ConcurrentHashMap`, instead we offer a selected set of methods.

* `sentry-android-okhttp` has been removed in favor of `sentry-okhttp`, making the module independent from Android ([#3510](https://github.com/getsentry/sentry-java/pull/3510))

* Calling `Sentry.init()` on Android now throws a `IllegalArgumentException`, please use `SentryAndroid.init()` instead ([#3596](https://github.com/getsentry/sentry-java/pull/3596))

* Metrics have been removed from the SDK ([#3774](https://github.com/getsentry/sentry-java/pull/3774))
  * Metrics will return but we don't know in what exact form yet

* `enableTracing` option (a.k.a `enable-tracing`) has been removed from the SDK ([#3776](https://github.com/getsentry/sentry-java/pull/3776))
  * Please set `tracesSampleRate` to a value >= 0.0 for enabling performance instead. The default value is `null` which means performance is disabled.

* Change OkHttp sub-spans to span attributes ([#3556](https://github.com/getsentry/sentry-java/pull/3556))
  * This will reduce the number of spans created by the SDK

* Replace `synchronized` methods and blocks with `ReentrantLock` (`AutoClosableReentrantLock`) ([#3715](https://github.com/getsentry/sentry-java/pull/3715))
  * If you are subclassing any Sentry classes, please check if the parent class used `synchronized` before. Please make sure to use the same lock object as the parent class in that case.

* `traceOrigins` option (`io.sentry.traces.tracing-origins` in manifest) has been removed, please use `tracePropagationTargets` (`io.sentry.traces.trace-propagation-targets` in manifest\`) instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `profilingEnabled` option (`io.sentry.traces.profiling.enable` in manifest) has been removed, please use `profilesSampleRate` (`io.sentry.traces.profiling.sample-rate` in manifest) instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))
  * Please set `profileSampleRate` to a value >= 0.0 for enabling profiling instead. The default value is `null` which means profiling is disabled.

* `shutdownTimeout` option has been removed, please use `shutdownTimeoutMillis` instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `profilingTracesIntervalMillis` option for Android has been removed ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `io.sentry.session-tracking.enable` manifest option has been removed ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `Sentry.traceHeaders()` method has been removed, please use `Sentry.getTraceparent()` instead ([#3718](https://github.com/getsentry/sentry-java/pull/3718))

* `Sentry.reportFullDisplayed()` method has been removed, please use `Sentry.reportFullyDisplayed()` instead ([#3717](https://github.com/getsentry/sentry-java/pull/3717))

* `User.other` has been removed, please use `data` instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `SdkVersion.getIntegrations()` has been removed, please use `getIntegrationSet` instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `SdkVersion.getPackages()` has been removed, please use `getPackageSet()` instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `Device.language` has been removed, please use `locale` instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `TraceContext.user` and `TraceContextUser` class have been removed, please use `userId` on `TraceContext` instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `TransactionContext.fromSentryTrace()` has been removed, please use `Sentry.continueTrace()` instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* `SentryDataFetcherExceptionHandler` has been removed, please use `SentryGenericDataFetcherExceptionHandler` in combination with `SentryInstrumentation` instead ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* One of the `AndroidTransactionProfiler` constructors has been removed, please use a different one ([#3780](https://github.com/getsentry/sentry-java/pull/3780))

* Use String instead of UUID for SessionId ([#3834](https://github.com/getsentry/sentry-java/pull/3834))

  * The `Session` constructor now takes a `String` instead of a `UUID` for the `sessionId` parameter.
  * `Session.getSessionId()` now returns a `String` instead of a `UUID`.

* The Android minSdk level for all Android modules is now 21 ([#3852](https://github.com/getsentry/sentry-java/pull/3852)) ([#3851](https://github.com/getsentry/sentry-java/pull/3851))

* All status codes below 400 are now mapped to `SpanStatus.OK` ([#3869](https://github.com/getsentry/sentry-java/pull/3869))

* `transaction.data` has moved from `extra` to `contexts.trace.data` (#3735)
  * If you were filtering data in e.g. `beforeSendTransaction` please update accordingly

### [Deprecations](#deprecations)

* `Hub` has been deprecated, we're replacing the following:

  * `IHub` has been replaced by `IScopes`, however you should be able to simply pass `IHub` instances to code expecting `IScopes`, allowing for an easier migration.
  * `HubAdapter.getInstance()` has been replaced by `ScopesAdapter.getInstance()`
  * The `.clone()` method on `IHub`/`IScopes` has been deprecated, please use `.pushScope()` or `.pushIsolationScope()` instead
  * Some internal methods like `.getCurrentHub()` and `.setCurrentHub()` have also been replaced.

* `Sentry.popScope` has been replaced by calling `.close()` on the token returned by `Sentry.pushScope()` and `Sentry.pushIsolationScope()`. The token can also be used in a `try-with-resource` block like this:

```bash
try (final @NotNull ISentryLifecycleToken ignored = Sentry.pushScope()) {
  // this block has its separate current scope
}
```

as well as:

```bash
try (final @NotNull ISentryLifecycleToken ignored = Sentry.pushIsolationScope()) {
  // this block has its separate isolation scope
}
```

You may also use `LifecycleHelper.close(token)`, e.g. in case you need to pass the token around for closing later.

### [Behavioral Changes](#behavioral-changes)

* We're introducing some new `Scope` types in the SDK, allowing for better control over what data is attached where. Previously there was a stack of scopes that was pushed and popped. Instead we now fork scopes for a given lifecycle and then restore the previous scopes. Since `Hub` is gone, it is also never cloned anymore. Separation of data now happens through the different scope types while making it easier to manipulate exactly what you need without having to attach data at the right time to have it apply where wanted.

  * Global scope is attached to all events created by the SDK. It can also be modified before `Sentry.init` has been called. It can be manipulated using `Sentry.configureScope(ScopeType.GLOBAL, (scope) -> { ... })`.
  * Isolation scope can be used e.g. to attach data to all events that come up while handling an incoming request. It can also be used for other isolation purposes. It can be manipulated using `Sentry.configureScope(ScopeType.ISOLATION, (scope) -> { ... })`. The SDK automatically forks isolation scope in certain cases like incoming requests, CRON jobs, Spring `@Async` and more.
  * Current scope is forked often and data added to it is only added to events that are created while this scope is active. Data is also passed on to newly forked child scopes but not to parents.

* `Sentry.popScope` has been deprecated, please call `.close()` on the token returned by `Sentry.pushScope` instead or use it in a way described in more detail in "Migration Guide".

* We have chosen a default scope that is used for `Sentry.configureScope()` as well as for APIs like `Sentry.setTag()`

  * For Android the type defaults to `CURRENT` scope
  * For Backend and other JVM applicatons it defaults to `ISOLATION` scope

* Event processors on `Scope` can now be ordered by overriding the `getOrder` method on implementations of `EventProcessor`. NOTE: This order only applies to event processors on `Scope` but not `SentryOptions` at the moment. Feel free to request this if you need it.

* `Hub` is deprecated in favor of `Scopes`, alongside some `Hub` relevant APIs. More details can be found in the "Migration Guide" section.

* (Android) The JNI layer for sentry-native has now been moved from sentry-java to sentry-native ([#3189](https://github.com/getsentry/sentry-java/pull/3189))

  * This now includes prefab support for sentry-native, allowing you to link and access the sentry-native API within your native app code
  * Checkout the `sentry-samples/sentry-samples-android` example on how to configure CMake and consume `sentry.h`

* (Android) Replace thread id with kernel thread id in span data ([#3706](https://github.com/getsentry/sentry-java/pull/3706))

* (Android) Enable Performance V2 by default ([#3824](https://github.com/getsentry/sentry-java/pull/3824))
  * With this change cold app start spans will include spans for ContentProviders, Application and Activity load.

### [Sentry Self-hosted Compatibility](#sentry-self-hosted-compatibility)

* The required Sentry version in version `8.0.0` of the SDK remains unchanged. [Sentry's version >= v22.12.0](https://github.com/getsentry/self-hosted/releases) is required. This only applies to self-hosted Sentry. If you are using [sentry.io](https://sentry.io), no action is needed.

### [Sentry Android SDK Compatibility](#sentry-android-sdk-compatibility)

You must use Sentry Gradle plugin 5.+ together with the Sentry Android SDK 8.+ otherwise, it might crash at runtime due to missing dependencies.

## [Migration from `io.sentry:sentry-android-gradle-plugin:3.x.x` to `io.sentry:sentry-android-gradle-plugin:4.0.0`](#migration-from-iosentrysentry-android-gradle-plugin3xx-to-iosentrysentry-android-gradle-plugin400)

### [Breaking Changes](#breaking-changes-1)

* Bumped Sentry Android SDK to `7.0.0`. Refer to the [section below](#migrating-from-iosentrysentry-android-6x-to-iosentrysentry-android-700) for details about changes to the SDK.
* Renamed `experimentalGuardsquareSupport` flag to `dexguardEnabled`.

### [Sentry Android SDK Compatibility](#sentry-android-sdk-compatibility-1)

You must use Sentry Gradle plugin 4.+ together with the Sentry Android SDK 7.+ otherwise, it might crash at runtime due to binary incompatibility. If you can't do that for some reason, you can specify the Sentry version via the plugin config block:

```kotlin
sentry {
  autoInstallation {
    sentryVersion.set("7.0.0")
  }
}
```

Similarly, if you have a Sentry SDK (e.g. `sentry-android-core`) dependency on one of your Gradle modules and you're updating it to 7.+, make sure the Gradle plugin is at 4.+, or specify the SDK version as shown in the snippet above.

## [Migrating from `io.sentry:sentry-android 6.x` to `io.sentry:sentry-android 7.0.0`](#migrating-from-iosentrysentry-android-6x-to-iosentrysentry-android-700)

### [Breaking Changes](#breaking-changes-2)

* The minimum supported API level was updated to 19 (`minSdk`).
* The `sentry-android-okhttp` classes were deprecated in favor of `sentry-okhttp`, which is a pure Java module and can be used in non-Android projects.
  * The `SentryOkHttpUtils` class was removed from the public API. If you were using it, consider filing a [feature request](https://github.com/getsentry/sentry-java/issues).
* If you're using `sentry-kotlin-extensions`, it now requires `kotlinx-coroutines-core` version `1.6.1` or higher.
* Moved `enableNdk` and `enableScopeSync` from `SentryOptions` to `SentryAndroidOptions`.
* Changed the return type of `SentryApolloInterceptor.BeforeSpanCallback` from `ISpan` to `ISpan?`.
* `Scope` now implements the `IScope` interface, therefore some methods like `ScopeCallback.run` accept `IScope` now.
* Some `Sentry.startTransaction` overloads do not exist anymore, and instead, you can set old options by passing a `TransactionOptions` object in.

For example:

```kotlin
// old
val transaction = Sentry.startTransaction("name", "op", bindToScope = true)
// new
val transaction = Sentry.startTransaction("name", "op", TransactionOptions().apply { isBindToScope = true })
```

### [Behavioral Changes](#behavioral-changes-1)

* `Sentry.getSpan()` now returns the root span/transaction instead of the latest span.
  * This will make the span hierarchy leaner and more readable.
* The SDK now captures failed HTTP and GraphQL (Apollo) requests by default.
  * This can increase your event consumption and may affect your quota, because we will report failed network requests as Sentry events if you're using the `sentry-android-okhttp` or `sentry-apollo-3` integrations by default. You can customize what errors you want/don't want to have reported for [OkHttp](/platforms/android/integrations/okhttp/#http-client-errors) and [Apollo3](/platforms/android/integrations/apollo3/#graphql-client-errors) respectively.
* Added a deadline timeout for automatic transactions.
  * This affects all automatically generated transactions on Android (UI, clicks). The default timeout is 30s, meaning the automatic transaction will be force-finished with the status `deadline_exceeded` when it reaches the deadline.
* The SDK now sets `ip_address` to {{auto}} by default, even if sendDefaultPII is disabled.
  * We recommend you instead use the "Prevent Storing of IP Addresses" option in the "Security & Privacy" project settings on [sentry.io](https://sentry.io/).
* The `maxSpans` setting (defaults to 1000) is now enforced for nested child spans. This means a single transaction can have `maxSpans` number of children (nested or not) at most.

### [Sentry Integrations Version Compatibility](#sentry-integrations-version-compatibility)

Make sure to align *all* Sentry dependencies (like `-timber`, `-okhttp` or other packages) to the same version when bumping the SDK to 7.+, otherwise, it will crash at runtime due to binary incompatibility.

For example, if you're using the [Sentry Android Gradle plugin](https://github.com/getsentry/sentry-android-gradle-plugin) with the `autoInstallation` [feature](/platforms/android/configuration/gradle/#auto-installation) (enabled by default), make sure to use version 4.+ of the Gradle plugin together with version 7.+ of the SDK. If you can't do that for some reason, you can specify the Sentry version via the plugin config block:

```kotlin
sentry {
  autoInstallation {
    sentryVersion.set("7.0.0")
  }
}
```

Similarly, if you have a Sentry SDK (e.g. `sentry-android-core`) dependency on one of your Gradle modules and you're updating it to 7.+, make sure the Gradle plugin is at 4.+ or specify the SDK version as shown in the snippet above.

### [Sentry Self-hosted Compatibility](#sentry-self-hosted-compatibility-1)

* Starting with version `7.0.0` of `sentry`, [Sentry's version >= v22.12.0](https://github.com/getsentry/self-hosted/releases) is required to properly ingest transactions with unfinished spans. This only applies to self-hosted Sentry. If you are using [sentry.io](https://sentry.io), no action is needed.

## [Migrating from `io.sentry:sentry-android 6.14.x` to `io.sentry:sentry-android 6.15.0`](#migrating-from-iosentrysentry-android-614x-to-iosentrysentry-android-6150)

The `sentry-compose-android` and `sentry-compose` integrations now declare their upstream dependencies as `compileOnly`. Make sure to have the `androidx.navigation:navigation-compose`, `androidx.compose.runtime:runtime`, and `androidx.compose.ui:ui` dependencies on the classpath if you're using those integrations. Otherwise, the application will crash with a `NoClassDefFoundError` exception.

## [Migrating from `io.sentry:sentry-android 6.2.x` to `io.sentry:sentry-android 6.3.0`](#migrating-from-iosentrysentry-android-62x-to-iosentrysentry-android-630)

The `sentry-android-okhttp`, `sentry-android-fragment`, and `sentry-android-timber` integrations now declare their upstream dependencies as `compileOnly`. Make sure to have the `okhttp`, `fragment`, and `timber` dependencies on the classpath if you're using those integrations or the application will crash with a `NoClassDefFoundError` exception.

## [Migrating from `io.sentry:sentry-android 6.x` to `io.sentry:sentry-android 6.2.0`](#migrating-from-iosentrysentry-android-6x-to-iosentrysentry-android-620)

* Kotlin plugin is upgraded to `1.6.10`.

This version is still compatible with Kotlin `1.4`.

This only affects integrations that are written in Kotlin, such as `timber`, `fragment`, `okhttp`, `navigation` and `compose`.

## [Migrating from `io.sentry:sentry-android 5.x` to `io.sentry:sentry-android 6.0.0`](#migrating-from-iosentrysentry-android-5x-to-iosentrysentry-android-600)

* Kotlin plugin is upgraded to `1.5`.

* Kotlin `languageVersion` is upgraded to `1.4`.

* `Gson` is removed as a transitive dependency and vendored in the SDK.

  * Protocol classes now implement the `JsonSerializable` and `JsonDeserializer` interfaces.

* `SentryOptions#shutdownTimeout` is renamed to `shutdownTimeoutMillis`.

* Removed `@Deprecated` and `@ApiStatus.ScheduledForRemoval` methods

  * `ITransaction#setRequest`
  * `ITransaction#getRequest`
  * `ITransaction#getContexts`
  * `SentryBaseEvent#getOriginThrowable`
  * `SentryOptions#getCacheDirSize`
  * `SentryOptions#setCacheDirSize`
  * `SentryOptions#isEnableSessionTracking`
  * `SentryOptions#setEnableSessionTracking`

* Removed unnecessary abstractions

  * `IBuildInfoProvider` is now `BuildInfoProvider` only.
  * `IHandler` is now `MainLooperHandler` only.

* `ISpan` now has higher precision using the `System#nanoTime` instead of milliseconds.

* Hints changed its type from `Object` to `io.sentry.Hint`

*Old*:

```kotlin
Sentry.captureException(RuntimeException("exception"), "myStringHint")
```

*New*:

```kotlin
val hints = mutableMapOf<String, Any>("myHint" to "myStringHint")
Sentry.captureException(RuntimeException("exception"), hints)
```

* `SentryOptions#enableScopeSync` is now enabled by default, to disable it, see the code snippet below.

`AndroidManifest.xml`

```xml
<meta-data
  android:name="io.sentry.ndk.scope-sync.enable"
  android:value="false"
/>
```

* `SentryOptions#sendClientReports` is now enabled by default. To disable it, use the code snippet below:

`AndroidManifest.xml`

```xml
<meta-data
  android:name="io.sentry.send-client-reports"
  android:value="false"
/>
```

### [Sentry Self-hosted Compatibility](#sentry-self-hosted-compatibility-2)

* Starting with version `6.0.0` of `sentry`, [Sentry's version >= v21.9.0](https://github.com/getsentry/self-hosted/releases) is required or you have to manually disable sending client reports via the `sendClientReports` option. This only applies to self-hosted Sentry. If you are using [sentry.io](https://sentry.io), no action is needed.

There are more changes and refactors, but they are not user breaking changes.

## [Migrating to `io.sentry:sentry-android-timber 5.6.2`](#migrating-to-iosentrysentry-android-timber-562)

Starting from version `5.6.2`, the `Timber.tag` usage is no longer supported by our SDK (the tag will not be captured and reflected on Sentry). Please, vote on this [GitHub issue](https://github.com/getsentry/sentry-java/issues/1900) to let us know if we should provide support for that.

Support for `Timber.tag` has been brought back in version `5.7.2`.

## [Migrating from `io.sentry:sentry-android-gradle-plugin 2.x` to `io.sentry:sentry-android-gradle-plugin 3.0.0`](#migrating-from-iosentrysentry-android-gradle-plugin-2x-to-iosentrysentry-android-gradle-plugin-300)

The `io.sentry.android.gradle` >= `3.0.0` requires [Android Gradle Plugin >= 7.0.0](https://developer.android.com/studio/releases/gradle-plugin#7-0-0). For older versions of the Android Gradle Plugin, use `io.sentry.android.gradle:2.+`.

### [includeProguardMapping](#includeproguardmapping)

The `autoUpload` flag has been deprecated in favor of two new options:

* `includeProguardMapping` - Disables/enables Proguard mapping functionality. When enabled, generates a UUID and attempts to upload a Proguard mapping associated with that UUID to Sentry. When `autoUploadProguardMapping` is disabled, the plugin will only generate a `sentry-debug-meta.properties` file containing UUID, which can later be used to manually upload the mapping using, for example [sentry-cli](/cli/dif/#proguard-mapping-upload).
* `autoUploadProguardMapping` - Defines whether the gradle plugin should attempt to auto-upload the mapping file to Sentry. When `includeProguardMapping` is disabled, this flag has no effect.

*Old*:

```groovy
sentry {
    autoUpload = false
}
```

*New*:

```groovy
sentry {
  includeProguardMapping = true
  autoUploadProguardMapping = false
}
```

### [tracingInstrumentation](#tracinginstrumentation)

The `io.sentry.android.gradle` enables the tracing instrumentation (via bytecode manipulation) for `androidx.sqlite` and `androidx.room` libraries by default, to disable it, see the code snippet below.

```groovy
sentry {
    // Enable or disable the tracing instrumentation.
    // Does auto instrumentation for 'androidx.sqlite' and 'androidx.room' libraries.
    // It starts and finishes a Span within any CRUD operation.
    // Default is enabled.
    // Only available v3.0.0 and above.
    tracingInstrumentation {
      enabled = false
    }
}
```

## [Migrating from `io.sentry:sentry-android-gradle-plugin 1.x` to `io.sentry:sentry-android-gradle-plugin 2.0.0`](#migrating-from-iosentrysentry-android-gradle-plugin-1x-to-iosentrysentry-android-gradle-plugin-200)

The `io.sentry.android.gradle` >= `2.0.0` requires [Android Gradle Plugin >= 4.0.0](https://developer.android.com/studio/releases/gradle-plugin#4-0-0).

The `io.sentry.android.gradle` >= `2.0.0` must be applied to the `app/build.gradle` module (or the module that has `com.android.application` plugin applied).

The `io.sentry.android.gradle` >= `2.0.0` publishes the Gradle Plugin Marker to Maven Central. As a result, you no longer need to set the `classpath`.

*Old*:

```groovy
buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'io.sentry:sentry-android-gradle-plugin:{version}'
    }
}

apply plugin: 'io.sentry.android.gradle'
```

*New*:

```groovy
plugins {
    id "io.sentry.android.gradle" version "{version}"
}

buildscript {
    repositories {
        mavenCentral()
    }
}
```

The `io.sentry.android.gradle` has been rewritten in Kotlin. As a result, the Groovy or Kotlin DSL syntax has slightly changed.

The `autoProguardConfig` flag has been removed, the Android SDK >= `2.0.0` version already merges the ProGuard rules automatically.

*Old*:

```groovy
sentry {
    autoProguardConfig false
    autoUpload true
    uploadNativeSymbols false
    includeNativeSources false
}
```

*New*:

```groovy
sentry {
    autoUpload = true
    uploadNativeSymbols = false
    includeNativeSources = false
}
```

## [Migrating from `io.sentry:sentry-android 4.3.0` to `io.sentry:sentry-android 5.0.0`](#migrating-from-iosentrysentry-android-430-to-iosentrysentry-android-500)

You may remove `android:extractNativeLibs="true"` meta-data in the `AndroidManifest` file or `android.bundle.enableUncompressedNativeLibs=false` in the `gradle.properties` file if you're using the [Android Native Development Kit](/platforms/android/configuration/using-ndk/). Sentry can now symbolicate events with the default value of [extractNativeLibs](https://developer.android.com/studio/releases/gradle-plugin#extractNativeLibs) and [android.bundle.enableUncompressedNativeLibs](https://developer.android.com/studio/releases/gradle-plugin#behavior-changes).

`Sentry#startTransaction` by default does not bind created transaction to the scope. To start transaction with binding to the scope, use one of the new overloaded `startTransaction` methods taking `bindToScope` parameter and set it to `true`. Bound transaction can be retrieved with `Sentry#getSpan`.

All SDK methods have been annotated with [JetBrains Annotations](https://github.com/JetBrains/java-annotations): `@Nullable` and `@NotNull`. Kotlin compiler respects these annotations, so in Kotlin code, some fields that were recognized as not-null, are now nullable, and the other way around.

`SentryBaseEvent#getOriginThrowable` has been deprecated in favor of `SentryBaseEvent#getThrowable`, and `SentryBaseEvent#getThrowable` now returns the unwrapped throwable.

`SentryOptions#getCacheDirSize` has been deprecated in favor of `SentryOptions#getMaxCacheItems`.

`InvalidDsnException` has been removed. It is replaced by `IllegalArgumentException`.

`EventProcessor` interface has a new `default` method which could break the instantiation when using trailing lambdas.

*Old*:

```kotlin
SentryOptions#addEventProcessor { event, _ -> event }
```

*New*:

```kotlin
SentryOptions#addEventProcessor(object : EventProcessor {
    override fun process(event: SentryEvent, hint: Hint): SentryEvent? {
        return event
    }
})
```

A random generated `installationId` replaces `Settings.Secure.ANDROID_ID`, which has been removed. This may affect the number of unique users displayed on the Issues page and Alerts. If you always set a custom user using `Sentry.setUser(customUser)`, the behavior has not changed. While you don't have to make any update, if you want to maintain the old behavior, use the following code snippet:

```java
User user = new User();
user.setId(Settings.Secure.ANDROID_ID);

Sentry.setUser(user);
```

`SentryOptions#setEnableSessionTracking(boolean)` is deprecated in favor of `SentryOptions#setEnableAutoSessionTracking(boolean)`. It will be removed in future.

*Old*:

```java
SentryAndroid.init(this, options -> {
    options.setEnableSessionTracking(false);
});
```

*New*:

```java
SentryAndroid.init(this, options -> {
    options.setEnableAutoSessionTracking(false);
});
```

`io.sentry.session-tracking.enable` AndroidManifest meta-data is deprecated in favor of `io.sentry.auto-session-tracking.enable`. It will be removed in future.

*Old*:

`AndroidManifest.xml`

```xml
<application>
    <meta-data
    android:name="io.sentry.session-tracking.enable"
    android:value="false"
  />
</application>
```

*New*:

`AndroidManifest.xml`

```xml
<application>
    <meta-data
    android:name="io.sentry.auto-session-tracking.enable"
    android:value="false"
  />
</application>
```

## [Migrating from `io.sentry:sentry-android 4.1.0` to `io.sentry:sentry-android 4.2.0`](#migrating-from-iosentrysentry-android-410-to-iosentrysentry-android-420)

`operation` is now a required property of the `SentryTransaction` and `SentrySpan`. Whenever a transaction or span is started, the value for `operation` must be provided:

```java
Sentry.startTransaction("transaction-name", "operation-name");
```

## [Migrating from `io.sentry:sentry-android 2.x` to `io.sentry:sentry-android 3.x`](#migrating-from-iosentrysentry-android-2x-to-iosentrysentry-android-3x)

### [Package changes](#package-changes)

The package `io.sentry.core` has been renamed to `io.sentry`. To compile correctly, replace the strings on all the usages from `io.sentry.core.` to `io.sentry.`

Other than that, the APIs didn't change. Release Heath sets by default. If you prefer not to track the health of your releases, disable it with:

```xml
<application>
  <meta-data
    android:name="io.sentry.session-tracking.enable"
    android:value="false"
  />
</application>
```

## [Migrating from `io.sentry:sentry-android 1.x` to `io.sentry:sentry-android 2.x`](#migrating-from-iosentrysentry-android-1x-to-iosentrysentry-android-2x)

With Sentry Android, we've updated the API to resemble the [Unified API](https://develop.sentry.dev/sdk/miscellaneous/unified-api/) more closely. And now that the SDK isn't built on top of `io.sentry:sentry-java`, Sentry Android has more Android-specific features.

If you want to upgrade from the previous version of the SDK, please check the following sections of changes that may need updating in your code.

### [Configuration](#configuration)

The file `sentry.properties` used by the previous version of the SDK has been discontinued. Configurations for the new SDK are in `AndroidManifest.xml` or directly in the code.

Example of the configuration in the Manifest:

```xml
<application>
    <!-- Example of the Sentry DSN setting -->
    <meta-data
    android:name="io.sentry.dsn"
    android:value="https://examplePublicKey@o0.ingest.sentry.io/0"
  />
</application>
```

If you want to set the configuration manually in the code, you need to initialize the SDK with `SentryAndroid.init()` --- described in [Installation](#installation) --- in the same file as `SentryAndroidOptions`, which holds configuration items.

### [Installation](#installation)

The new SDK can initialize automatically, all you need to do is provide the DSN in your Manifest file, as shown in the previous example in [Configuration](#configuration).

#### [Manual Installation](#manual-installation)

If you want to register any callback to filter and modify events and/or breadcrumbs, or if you want to provide the configuration values via code, you need to initialize the SDK using the `SentryAndroid.init()`.

To initialize the SDK manually:

* Disable the `auto-init` feature by providing the following line in the manifest:

  ```xml
  <application>
      <meta-data android:name="io.sentry.auto-init" android:value="false" />
  </application>
  ```

* Initialize the SDK directly in your application:

```java
SentryAndroid.init(this, options -> {
  options.setDsn("https://examplePublicKey@o0.ingest.sentry.io/0");
});
```

### [Releases](#releases)

Please note that the new SDK will send with each event a release version in a different format than the previous SDK.

If you are using the [GitHub](/organization/integrations/source-code-mgmt/github/) or [GitLab](/organization/integrations/source-code-mgmt/gitlab/) integrations, you need to do one of the following:

* [Use the new format](/platforms/android/configuration/releases/)
* Set the release in your `AndroidManifest.xml`
* Change your code as described in the configuration section

### [API](#api)

#### [Set tag](#set-tag)

*Old*:

```java
Sentry.getContext().addTag("tagName", "tagValue");
```

*New*:

```java
Sentry.setTag("tagName", "tagValue");
```

#### [Capture custom exception](#capture-custom-exception)

*Old*:

```java
try {
  int x = 1 / 0;
} catch (Exception e) {
  Sentry.capture(e);
}
```

*New*:

```java
try {
  int x = 1 / 0;
} catch (Exception e) {
  Sentry.captureException(e);
}
```

#### [Capture a message](#capture-a-message)

*Old*:

```java
Sentry.capture("This is a test");
```

*New*:

```java
Sentry.captureMessage("This is a test"); // SentryLevel.INFO by default
Sentry.captureMessage("This is a test", SentryLevel.WARNING); // or specific level
```

#### [Breadcrumbs](#breadcrumbs)

*Old*:

```java
Sentry.getContext().recordBreadcrumb(
  new BreadcrumbBuilder().setMessage("User made an action").build()
);
```

*New*:

```java
Sentry.addBreadcrumb("User made an action");
```

#### [User](#user)

*Old*:

```java
Sentry.getContext().setUser(
  new UserBuilder().setEmail("hello@sentry.io").build()
);
```

*New*:

```java
User user = new User();
user.setEmail("hello@sentry.io");
Sentry.setUser(user);
```

#### [Set extra](#set-extra)

*Old*:

```java
Sentry.getContext().addExtra("extra", "thing");
```

*New*:

```java
Sentry.setExtra("extra", "thing");
```

#### [Clear the Context/Scope](#clear-the-contextscope)

*Old*:

```java
Sentry.clearContext();
```

*New*:

```java
Sentry.configureScope(s -> s.clear());
```

### [Sentry Gradle Plugin](#sentry-gradle-plugin)

Disable the `autoProguardConfig` flag from the Sentry Gradle Plugin since `io.sentry:sentry-android` >= `2.0.0` does this automatically.

```groovy
sentry {
    autoProguardConfig false
}
```
