# Android (Java) to Android (Kotlin) SDK Breaking Changes

<p>This guide walks you through the breaking changes introduced in the <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/kotlin-sdk/" >Android (Kotlin)</a> SDK.</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="overview">Overview</h2><p>The Android (Kotlin) SDK is built from scratch while retaining the core functionalities of the legacy Android (Java) SDKAndroid (Java) refers to the legacy RudderStack Android SDK. <b>Note that it will be deprecated soon.</b><br /><br />For new implementations, use the Android (Kotlin) SDK instead.
  
  .</p>
<p>Note the following before upgrading your SDK:</p>
<ul>
<li>This SDK does not support automatic data migration from the legacy <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/" >Android (Java) SDK</a>.</li>
<li>Any data persisted by the Android (Java) SDK is not carried over automatically.</li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="sdk-initialization">SDK initialization</h2><p>The way of initializing the Android (Kotlin) SDK has changed. See the following snippets for comparison:</p>
<div class="rs-tabs">
	<div class="rs-tabs__list">
		<button type="button" class="rs-tabs__tab"
			id="tab-fdcbae"
		
		>Android (Java) — Legacy</button>
		<button type="button" class="rs-tabs__tab"
			id="tab-fceadb"
		
		>Android (Kotlin)</button>
	</div>
	
<div class="rs-tabs__panel" id="panel-fdcbae">

<div class="rs-code">
  <div class="rs-code__head">kotlin<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-kotlin" data-lang="kotlin">RudderClient rudderClient = RudderClient.getInstance(
    this,
    WRITE_KEY,
    RudderConfig.Builder()
        .withDataPlaneUrl(DATA_PLANE_URL)
        .build()
)</code></pre></div>
</div>

</div>

<div class="rs-tabs__panel" id="panel-fceadb" hidden>

<div class="rs-code">
  <div class="rs-code__head">kotlin<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-kotlin" data-lang="kotlin">val analytics: Analytics = Analytics(
    configuration = Configuration(
        writeKey = BuildConfig.WRITE_KEY,
        application = application,
        dataPlaneUrl = BuildConfig.DATA_PLANE_URL,
    )
)</code></pre></div>
</div>
<p>The Java snippet for SDK initialization is shown below:</p>
<div class="rs-code">
  <div class="rs-code__head">java<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-java" data-lang="java">Configuration configuration = new ConfigurationBuilder(this, &#34;WRITE_KEY&#34;, &#34;DATA_PLANE_URL&#34;)
        .build();

JavaAnalytics analytics = new JavaAnalytics(configuration);</code></pre></div>
</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="event-api-changes">Event API changes</h2><ul>
<li>The following fields are updated in the Android (Kotlin) SDK:</li>
</ul>
<table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>RudderTraits</code></td>
          <td><code>Traits</code></td>
      </tr>
      <tr>
          <td><code>RudderProperty</code></td>
          <td><code>Properties</code></td>
      </tr>
  </tbody>
</table>

<blockquote class="warning">
  <div class="tip-quote">
    
    <div class="tip-text"><code>RudderMessageBuilder</code> and <code>RudderMessage</code> are no longer used in the Android (Kotlin) SDK.</div>
  </div>
</blockquote>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="rudderoption-changes"><code>RudderOption</code> changes</h2><p>The way for creating a <code>RudderOption</code> instance has changed in the Android (Kotlin) SDK:</p>
<div class="rs-tabs">
	<div class="rs-tabs__list">
		<button type="button" class="rs-tabs__tab"
			id="tab-bfcade"
		
		>Android (Java) — Legacy</button>
		<button type="button" class="rs-tabs__tab"
			id="tab-efbcda"
		
		>Android (Kotlin)</button>
	</div>
	
<div class="rs-tabs__panel" id="panel-bfcade">

<p>In this SDK, a <code>RudderOption</code> instance was created using method chaining:</p>
<div class="rs-code">
  <div class="rs-code__head">kotlin<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-kotlin" data-lang="kotlin">val option = RudderOption()
          .putIntegration(CustomFactory.FACTORY, false)
          .putIntegration(&#34;Amplitude&#34;, false)
          .putExternalId(&#34;brazeExternalId&#34;, &#34;&lt;id&gt;&#34;)

val traits = RudderTraits()
          .put(&#34;key&#34;, &#34;value&#34;)

// Identify event is used just for demonstration purposes.
rudderClient.identify(&#34;user 1&#34;, traits, option)</code></pre></div>
</div>

</div>

<div class="rs-tabs__panel" id="panel-efbcda" hidden>

<p>In Android (Kotlin) SDK, <code>RudderOption</code> is instantiated using the constructor arguments instead of method chaining:</p>
<div class="rs-code">
  <div class="rs-code__head">kotlin<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-kotlin" data-lang="kotlin">val option = RudderOption(
    customContext = buildJsonObject {
        put(&#34;key&#34;, &#34;value&#34;)
    },
    integrations = buildJsonObject {
        put(&#34;Amplitude&#34;, true)
        put(&#34;INTERCOM&#34;, buildJsonObject {
            put(&#34;lookup&#34;, &#34;phone&#34;)
        })
    },
    externalIds = listOf(
        ExternalId(type = &#34;brazeExternalId&#34;, id = &#34;&lt;id&gt;&#34;),
    )
)

val traits = buildJsonObject {
    put(&#34;key-1&#34;, &#34;value-1&#34;)
}

// Identify event is used just for demonstration purposes.
RudderAnalyticsUtils.analytics.identify(
    userId = &#34;User1&#34;,
    traits = traits,
    options = option
)</code></pre></div>
</div>
<p>The corresponding Java snippet is shown below:</p>
<div class="rs-code">
  <div class="rs-code__head">java<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-java" data-lang="java">Map&lt;String, Object&gt; customContext = new HashMap&lt;&gt;();
customContext.put(&#34;key&#34;, &#34;value&#34;);

Map&lt;String, Object&gt; nestedIntegrations = new HashMap&lt;&gt;();
nestedIntegrations.put(&#34;lookup&#34;, &#34;phone&#34;);
Map&lt;String, Object&gt; integrations = new HashMap&lt;&gt;();
integrations.put(&#34;Amplitude&#34;, true);
integrations.put(&#34;INTERCOM&#34;, nestedIntegrations);

List&lt;ExternalId&gt; externalIds = new ArrayList&lt;&gt;();
externalIds.add(new ExternalId(&#34;brazeExternalId&#34;, &#34;&lt;id&gt;&#34;));

RudderOption option = new RudderOptionBuilder()
        .setIntegrations(integrations)
        .setExternalId(externalIds)
        .setCustomContext(customContext)
        .build();
        
HashMap&lt;String, Object&gt; traits = new HashMap&lt;&gt;();
traits.put(&#34;name&#34;, &#34;Alex Keener&#34;);
traits.put(&#34;email&#34;, &#34;alex@example.com&#34;);

analytics.identify(&#34;User1&#34;, traits, option);</code></pre></div>
</div>

</div>

</div>

<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="other-api-changes">Other API changes</h2><table>
  <thead>
      <tr>
          <th>Method</th>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>putIntegration</code></td>
          <td>Accepted two arguments - <code>type</code> (String) and <code>enabled</code> (Boolean).</td>
          <td>Converted into constructor arguments and renamed to <code>integrations</code> of a single <code>JsonObject</code> type.</td>
      </tr>
      <tr>
          <td><code>putCustomContext</code></td>
          <td>Accepted two arguments - <code>type</code> (String) and <code>context</code> (Map).</td>
          <td>Converted into constructor arguments and renamed to <code>customContext</code> of a single <code>JsonObject</code> type.</td>
      </tr>
      <tr>
          <td><code>putExternalId</code></td>
          <td>Accepted two arguments - <code>type</code> (String) and <code>id</code> (String).</td>
          <td>Converted into constructor arguments and renamed to <code>externalIds</code> of type <code>List&lt;ExternalId&gt;</code>, where <code>&lt;ExternalId&gt;</code> is a data class with a <code>type</code> (String) and <code>id</code> (String).</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="sdk-configuration-changes">SDK configuration changes</h2><p>The following table maps the SDK configuration options  available in the Android (Java) SDKAndroid (Java) refers to the legacy RudderStack Android SDK. <b>Note that it will be deprecated soon.</b><br /><br />For new implementations, use the Android (Kotlin) SDK instead.
  
   to the new Android (Kotlin) SDK:</p>
<table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>withLogLevel</code></td>
          <td>Set it directly using the <code>LoggerAnalytics</code> class. <br /><br />See <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/mobile-sdk-apis/logging-apis/" >Logging APIs in Android (Kotlin) SDK</a> for more information.</td>
      </tr>
      <tr>
          <td><code>withDataPlaneUrl</code></td>
          <td><code>dataPlaneUrl</code></td>
      </tr>
      <tr>
          <td><code>withTrackLifecycleEvents</code></td>
          <td><code>trackApplicationLifecycleEvents</code></td>
      </tr>
      <tr>
          <td><code>withNewLifecycleEvents</code></td>
          <td><code>trackApplicationLifecycleEvents</code></td>
      </tr>
      <tr>
          <td><code>withTrackDeepLinks</code></td>
          <td><code>trackDeepLinks</code></td>
      </tr>
      <tr>
          <td><code>withAutoSessionTracking</code></td>
          <td><code>sessionConfiguration</code></td>
      </tr>
      <tr>
          <td><code>withSessionTimeoutMillis</code></td>
          <td><code>sessionConfiguration</code></td>
      </tr>
      <tr>
          <td><code>withRecordScreenViews</code></td>
          <td><code>trackActivities</code></td>
      </tr>
      <tr>
          <td><code>withGzip</code></td>
          <td><code>gzipEnabled</code></td>
      </tr>
      <tr>
          <td><code>withCollectDeviceId</code></td>
          <td><code>collectDeviceId</code></td>
      </tr>
      <tr>
          <td><code>withFactory</code></td>
          <td>Handled via plugins. For example, <code>analytics.add(BrazeIntegration())</code></td>
      </tr>
      <tr>
          <td><code>withControlPlaneUrl</code></td>
          <td><code>controlPlaneUrl</code></td>
      </tr>
      <tr>
          <td><code>withFlushQueueSize</code></td>
          <td><code>CountFlushPolicy</code></td>
      </tr>
      <tr>
          <td><code>withSleepcount</code></td>
          <td><code>FrequencyFlushPolicy</code></td>
      </tr>
      <tr>
          <td><code>withEventDispatchSleepInterval</code></td>
          <td><code>FrequencyFlushPolicy</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="removed-features">Removed features</h2><p>The following features are removed in the Android (Kotlin) SDK:</p>
<ul>
<li><a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/#dbencryption" >Database encryption</a></li>
<li><a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/flushing-events-periodically/" >Worker manager support</a>: The <code>withFlushPeriodically</code> configuration option is no longer available.</li>
<li><a href="https://www.rudderstack.com/docs/transformations/usage/#device-mode" >Device Mode Transformations</a> (DMT): Not supported in the Android (Kotlin) SDK.</li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="feature-updates">Feature updates</h2><p>This section covers the different feature updates introduced in the Android (Kotlin) SDK:</p>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="reset-api">Reset API</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>reset(true)</code> clears <code>anonymousId</code></td>
          <td><code>analytics.reset()</code> clears <code>anonymousId</code></td>
      </tr>
      <tr>
          <td><code>reset(false)</code> retains <code>anonymousId</code></td>
          <td>You can also use the <code>reset</code> API to perform a selective reset, that is, specify which values to reset. <br /><br />See the <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/mobile-sdk-apis/reset/#selective-reset" >Reset API</a> guide for more information.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="flush-configuration">Flush configuration</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>The following configuration options are available:<br /><br /><ul><li><code>withSleepcount</code></li><li><code>withFlushQueueSize</code></li><li><code>withEventDispatchSleepInterval</code></li></ul></td>
          <td>The following <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/mobile-sdk-apis/flush-api/#flush-policies" >flush policies</a> are available:<br /><br /><ul><li><code>FrequencyFlushPolicy</code></li><li><code>CountFlushPolicy</code></li><li><code>StartupFlushPolicy</code></li></ul></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="gzip-event-requests">Gzip event requests</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Enabled by default</td>
          <td>Disabled by default</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="override-anonymous-id">Override anonymous ID</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Use the <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/#overriding-anonymous-id" ><code>putAnonymousId</code> method</a>.</td>
          <td>Use a <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/client-side-features/plugin-architecture/#custom-plugins" >custom plugin</a>. <br /><br />See this <a href="https://github.com/rudderlabs/rudder-sdk-kotlin/blob/develop/app/src/main/java/com/rudderstack/sampleapp/analytics/customplugins/SetAnonymousIdPlugin.kt" >Sample plugin</a> for more information.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="get-user-traits-after-identify-call">Get user traits after <code>identify</code> call</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Use the following snippet: <code>val traits =</code><br /><br /><code>rudderClient!!.getRudderContext().getTraits()</code></td>
          <td>Use the following snippet: <code>val traits = analytics.traits</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="set-external-id--custom-id">Set external ID / custom ID</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Use the <code>identify</code> call to set <code>externalId</code>.</td>
          <td>You can set <code>externalId</code> for all events including the application lifecycle events by leveraging a <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/client-side-features/plugin-architecture/#custom-plugins" >custom plugin</a>. <br /><br />See this <a href="https://github.com/rudderlabs/rudder-sdk-kotlin/blob/develop/app/src/main/java/com/rudderstack/sampleapp/analytics/customplugins/OptionPlugin.kt" >Sample plugin</a> for more information.</td>
      </tr>
      <tr>
          <td>The SDK persisted the <code>externalId</code>.</td>
          <td>You must persist the <code>externalId</code> manually.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="set-the-android-device-token">Set the Android device token</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Use the <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/#setting-the-android-device-token" ><code>putDeviceToken</code> method</a>.</td>
          <td>Use a <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/client-side-features/plugin-architecture/#custom-plugins" >custom plugin</a>. <br /><br />See this <a href="https://github.com/rudderlabs/rudder-sdk-kotlin/blob/develop/app/src/main/java/com/rudderstack/sampleapp/analytics/customplugins/SetPushTokenPlugin.kt" >Sample plugin</a> for more information.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="set-custom-context">Set custom context</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>You can pass custom context during the SDK initialization.</td>
          <td>Support for this feature is removed. Use a <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/client-side-features/plugin-architecture/#custom-plugins" >custom plugin</a> to set custom context for all events including automatically-tracked events (for example, lifecycle events). <br /><br />See this <a href="https://github.com/rudderlabs/rudder-sdk-kotlin/blob/develop/app/src/main/java/com/rudderstack/sampleapp/analytics/customplugins/OptionPlugin.kt" >Sample plugin</a> for more information.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="set-advertising-id">Set advertising ID</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Use the <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/#setting-the-advertisement-id" ><code>putAdvertisingId</code> method</a> to set the advertisement ID.</td>
          <td>Use a <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/client-side-features/plugin-architecture/#custom-plugins" >custom plugin</a> to automatically collect and set the advertisement ID. <br /><br />See this <a href="https://github.com/rudderlabs/rudder-sdk-kotlin/blob/main/app/src/main/java/com/rudderstack/sampleapp/analytics/customplugins/AndroidAdvertisingIdPlugin.kt" >Sample plugin</a> for more information.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="enabledisable-events-for-specific-destinations">Enable/disable events for specific destinations</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>You can enable or disable event delivery for specific destination across all events while <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/#1-while-initializing-the-sdk" >initializing the SDK</a> or while <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/#2-while-sending-events" >sending events</a>.</td>
          <td>Use a custom plugin to enable or disable event delivery for specific destinations across all event calls, including automatically tracked events (like lifecycle events) using the SDK. <br /><br />See this <a href="https://github.com/rudderlabs/rudder-sdk-kotlin/blob/main/app/src/main/java/com/rudderstack/sampleapp/analytics/customplugins/OptionPlugin.kt" >Sample plugin</a> for more information.</td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="session-tracking-and-lifecycle-events-dependency">Session tracking and lifecycle events dependency</h3><table>
  <thead>
      <tr>
          <th>Android (Java) — <strong>Legacy</strong></th>
          <th>Android (Kotlin)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Session tracking is <a href="https://www.rudderstack.com/docs/sources/event-streams/sdks/rudderstack-android-sdk/#tracking-user-sessions" >tightly coupled</a> with automatic tracking of lifecycle events. That means you cannot use session tracking if automatic lifecycle tracking is disabled.</td>
          <td>Session tracking is decoupled with automatic tracking of lifecycle events. That means you can use the session tracking and automatic lifecycle event tracking mechanisms independently.</td>
      </tr>
  </tbody>
</table>
<br />
