# Migrating from v2

Batch SDK v3 is a major release, which introduces breaking changes from 2.x. This guide describes how to update your application when using a previous version.

{% hint style="danger" %}
If your application is still using Batch SDK v1 please follow our [migration guide from V1](/developer/sdk/android/advanced/2x-migration.md) beforehand.
{% endhint %}

## Upgrading the SDK version

***

To upgrade from v2 to v3, you need to change the SDK version in your `build.gradle`:

{% tabs %}
{% tab title="Kotlin" %}

```kts
implementation("com.batch.android:batch-sdk:3.0.0")
```

{% endtab %}

{% tab title="Groovy" %}

```groovy
implementation 'com.batch.android:batch-sdk:3.0.0'
```

{% endtab %}
{% endtabs %}

## Core migration

***

### Compile and Target SDK

Batch SDK v3 now compiles with Android SDK 36 (Android 16 'Baklava').&#x20;

Even this is not mandatory we recommend you to ensure your project's `compileSdk` and `targetSdk` are updated accordingly in your `build.gradle` file.

{% tabs %}
{% tab title="Kotlin" %}
{% code title="build.gradle.kts" %}

```kts
android {
  ...
  compileSdk = 36
  ...
  defaultConfig {
    ...
    targetSdk = 36
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="Groovy" %}
{% code title="build.gradle" %}

```groovy
android {
    ...
    compileSdk 36
    
    defaultConfig {
        ...
        targetSdk 36
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Internal Kotlin Usage

Batch now uses Kotlin (1.9.0) internally. This should not affect your existing Java-based integrations as public APIs remain in Java. However, be aware of this change if you are inspecting the SDK's internals or if you encounter any unexpected behavior related to Kotlin interoperability.

## Push migration

***

### Managing notification display

Methods `setNotificationsType` and `getNotificationsType` in `Batch.Push` have been removed.&#x20;

Please replace their usage with the following methods:

* `Batch.Push.setShowNotifications(show: boolean)`: Use this to control whether Batch should display push notifications.
* `Batch.Push.shouldShowNotifications():` Use this to check if Batch is configured to show push notifications.

{% hint style="info" %}
Batch will preserve your previous settings, and shouldShowNotifications() will reflect them.&#x20;
{% endhint %}

So, if you were doing something like this in your application :

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// Disable notifications
val set = EnumSet.of(PushNotificationType.NONE) 
Batch.Push.setNotificationsType(set)

// or

// Enable notifications
val set = EnumSet.allOf(PushNotificationType::class.java) 
set.remove(PushNotificationType.NONE)
Batch.Push.setNotificationsType(set)
```

{% endtab %}

{% tab title="Java" %}

```java
// Disable notifications
EnumSet<PushNotificationType> set = EnumSet.of(PushNotificationType.NONE); 

// or

// Enable notifications
EnumSet<PushNotificationType> set = EnumSet.allOf(PushNotificationType.class); 
set.remove(PushNotificationType.NONE);-
Batch.Push.setNotificationsType(set);
```

{% endtab %}
{% endtabs %}

You should now do:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// Disable notifications
Batch.Push.setShowNotifications(false)

// or

// Enable notifications
Batch.Push.setShowNotifications(true)
```

{% endtab %}

{% tab title="Java" %}

```java
// Disable notifications
Batch.Push.setShowNotifications(false);

// or

// Enable notifications
Batch.Push.setShowNotifications(true);
```

{% endtab %}
{% endtabs %}

For more information, please visit the [managing notification display](/developer/sdk/android/advanced/customizing-notifications.md#managing-notification-display) section.

## Messaging migration

***

Batch SDK v3 adds compatibility for Mobile Landings with Push v2 which can be created from the Batch Dashboard's drag & drop composer.

### In-App Message Interception

The interface `Batch.Messaging.LifecycleListener2` has been removed. Please replace its usage with the new `Batch.Messaging.InAppInterceptor` interface.

Use the method `Batch.Messaging.setInAppInterceptor(Batch.Messaging.InAppInterceptor interceptor)` to set your custom interceptor.&#x20;

So if you were doing:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application(), LifecycleListener2 {
    override fun onCreate() {
        super.onCreate()
        // [...]
        Batch.Messaging.setLifecycleListener(this)
    }
    
    override fun onBatchInAppMessageReady(message: BatchInAppMessage): Boolean {
         // Your implementation
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application implements LifecycleListener2 {
    @Override
    public void onCreate() {
        super.onCreate();
        Batch.Messaging.setLifecycleListener(this);
    }
    
    @Override
    public boolean onBatchInAppMessageReady(@NonNull BatchInAppMessage message) {
         // Your implementation
    }
}

```

{% endtab %}
{% endtabs %}

You should now do:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application(), InAppInterceptor {
    override fun onCreate() {
        super.onCreate()
        // [...]
        Batch.Messaging.setInAppInterceptor(this)
    }
    
    override fun onBatchInAppMessageReady(message: BatchInAppMessage): Boolean {
         // Your custom implementation
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application implements InAppInterceptor {
    @Override
    public void onCreate() {
        super.onCreate();
        Batch.Messaging.setInAppInterceptor(this);
    }
    
    @Override
    public boolean onBatchInAppMessageReady(@NonNull BatchInAppMessage message) {
         // Your implementation
    }
}

```

{% endtab %}
{% endtabs %}

For more information, please see the In-App messaging [manual mode](/developer/sdk/android/in-app-messaging.md#manual-mode) section.

### Messaging Lifecycle Listener&#x20;

The following methods in `Batch.Messaging.LifecycleListener` have been removed:

* `onBatchMessageCancelledByAutoclose`
* `onBatchMessageCancelledByUser`
* `onBatchMessageCancelledByError`
* `onBatchMessageWebViewActionTriggered`

Please update your implementation to use the new `onBatchMessageClosed(String messageIdentifier, MessagingCloseReason reason)` method. The new `MessagingCloseReason` enum will provide the context about why the message was closed.

WebView actions will now trigger the updated `onBatchMessageActionTriggered` method, with the `analyticsID` of the action being passed as the `ctaIdentifier`.

The `index` (Int) parameter in `onBatchMessageActionTriggered` has been replaced by `ctaIdentifier` (String). The method signature is now:

```java
onBatchMessageActionTriggered(String messageIdentifier, String ctaIdentifier, BatchMessagAction actions)
```

{% hint style="warning" %}
For older MEP (Mobile Engagement Platform) messages, `ctaIdentifier` will be a string in the format `"mepCtaIndex:" + index`.
{% endhint %}

The constant `GLOBAL_TAP_ACTION_INDEX` now returns a String instead of an int. Update any comparisons or usage accordingly.

So if you were doing:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application(), Batch.Messaging.LifecycleListener {
    
    override fun onCreate() {
        super.onCreate()
        Batch.Messaging.setLifecycleListener(this)
    }
    
    override fun onBatchMessageShown(messageIdentifier: String?) {
        Log.i("App", "onBatchMessageShown $messageIdentifier")
    }
  
    override fun onBatchMessageActionTriggered(
        messageIdentifier: String?,
        index: Int,
        action: BatchMessageAction
    ) {
        Log.i("App", "onBatchMessageActionTriggered $messageIdentifier")
    }
    
    override fun onBatchMessageWebViewActionTriggered(
        messageIdentifier: String?,
        analyticsID: String,
        action: BatchMessageAction
    ) {
        Log.i("App", "onBatchMessageWebViewActionTriggered $messageIdentifier")
    }
    
    override fun onBatchMessageCancelledByAutoclose(messageIdentifier: String?) {
        Log.i("App", "onBatchMessageCancelledByAutoclose $messageIdentifier")
    }
    
    override fun onBatchMessageCancelledByUser(messageIdentifier: String?) {
        Log.i("App", "onBatchMessageCancelledByUser $messageIdentifier")
    }
    
    override fun onBatchMessageCancelledByError(messageIdentifier: String?) {
        Log.i("App", "onBatchMessageCancelledByUser $messageIdentifier")
    }
    
    override fun onBatchMessageClosed(messageIdentifier: String?) {
        Log.i("App", "onBatchMessageClosed $messageIdentifier")
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application implements Batch.Messaging.LifecycleListener {

  @Override
  public void onBatchMessageShown(@Nullable String messageIdentifier) {
      Log.i("App", "onBatchMessageShown " + messageIdentifier);
  }
  
  @Override
  public void onBatchMessageActionTriggered(
      @Nullable String messageIdentifier,
      int index,
      @NonNull BatchMessageAction action
  ) {
      Log.i("App", "onBatchMessageActionTriggered " + messageIdentifier);
  }
  
   @Override
  public void onBatchMessageWebViewActionTriggered(
      @Nullable String messageIdentifier,
      @Nullable String analyticsID,
      @Nullable BatchMessageAction action
  ) {
      Log.i("App", "onBatchMessageWebViewActionTriggered " + messageIdentifier);
  }
  
  @Override
  public void onBatchMessageCancelledByAutoclose(@Nullable String messageIdentifier) {
      Log.i("App", "onBatchMessageCancelledByAutoclose " + messageIdentifier);
  }
  
  @Override
  public void onBatchMessageCancelledByUser(@Nullable String messageIdentifier) {
      Log.i("App", "onBatchMessageCancelledByUser " + messageIdentifier);
  }
  
  @Override
  public void onBatchMessageCancelledByError(@Nullable String messageIdentifier) {
      Log.i("App", "onBatchMessageCancelledByError " + messageIdentifier);
  }
  
  @Override
  public void onBatchMessageClosed(@Nullable String messageIdentifier) {
      Log.i("App", "onBatchMessageClosed " + messageIdentifier);
  }  
}
```

{% endtab %}
{% endtabs %}

You should now do:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class SampleApplication : Application(), Batch.Messaging.LifecycleListener {
    
    override fun onCreate() {
        super.onCreate()
        Batch.Messaging.setLifecycleListener(this)
    }
    
    override fun onBatchMessageShown(messageIdentifier: String?) {
        Log.i("App", "onBatchMessageShown $messageIdentifier")
    }

    
    override fun onBatchMessageActionTriggered(
        messageIdentifier: String?,
        ctaIdentifier: String?,
        action: BatchMessageAction
    ) {
        Log.i("App", "onBatchMessageActionTriggered $messageIdentifier")
        //For MEP messages, ctaIdentifier might be "mepCtaIndex:0", "mepCtaIndex:1", etc.
    }
    
    override fun onBatchMessageClosed(
        messageIdentifier: String?,
        reason: Batch.Messaging.LifecycleListener.MessagingCloseReason?
    ) {
        Log.i("BatchSample", "onBatchMessageClosed $messageIdentifier with reason $reason")
        when(reason) {
            MessagingCloseReason.Auto -> Log.i("App",
                "onBatchMessageCancelledByAutoclose $messageIdentifier"
            )
            MessagingCloseReason.User -> Log.i("App",
                "onBatchMessageCancelledByUser $messageIdentifier"
            )
            MessagingCloseReason.Action -> Log.i("App",
                "onBatchMessageCancelledByAction $messageIdentifier"
            )
            MessagingCloseReason.Error -> Log.i("App",
                "onBatchMessageCancelledByError $messageIdentifier"
            )
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class SampleApplication extends Application implements Batch.Messaging.LifecycleListener {

    @Override
    public void onCreate() {
        super.onCreate();
        Batch.Messaging.setLifecycleListener(this);
    }

    @Override
    public void onBatchMessageShown(String messageIdentifier) {
        Log.i("App", "onBatchMessageShown " + messageIdentifier);
    }

    @Override
    public void onBatchMessageActionTriggered(
        String messageIdentifier,
        String ctaIdentifier,
        BatchMessageAction action
    ) {
        Log.i("App", "onBatchMessageActionTriggered " + messageIdentifier);
        // For MEP messages, ctaIdentifier might be "mepCtaIndex:0", "mepCtaIndex:1", etc.
    }

    @Override
    public void onBatchMessageClosed(
        String messageIdentifier,
        MessagingCloseReason reason
    ) {
        Log.i("BatchSample", "onBatchMessageClosed " + messageIdentifier + " with reason " + reason);
        switch (reason) {
            case Auto:
                Log.i("App", "onBatchMessageClosedByAutoclose " + messageIdentifier);
                break;
            case User:
                Log.i("App", "onBatchMessageClosedByUser " + messageIdentifier);
                break;
            case Action:
                Log.i("App", "onBatchMessageClosedByAction " + messageIdentifier);
                break;
            case Error:
                Log.i("App", "onBatchMessageClosedByError " + messageIdentifier);
                break;
        } 
    }
}
```

{% endtab %}
{% endtabs %}

For more information, please see the [listening lifecycle event](/developer/sdk/android/mobile-landings.md#listening-to-lifecycle-events-and-button-callbacks) section.

### Manual display mode&#x20;

The messaging manual display mode has been reworked to better fit Mobile Landing on Push v2.&#x20;

What's changed:

* The enum `Format` and the method `getFormat()` in `BatchMessage` have been removed.
* The methods `loadFragment()` and `loadBanner()` in `Batch.Messaging` have been removed.
* The class `BatchBannerView` has been removed.

\
You should now use the new method `Batch.Messaging.loadMessagingView(Context context, BatchMessage message)` to load messages.

This method will returns an instance of `BatchMessagingView` which according to the `kind` property allows you to use the right method to display it.

So if you were doing something like:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
try {
    val message = pushPayload.getLandingMessage()
    when (message.format) {
        BatchMessage.Format.BANNER -> Batch.Messaging.loadBanner(this, message).show(this)
        else -> Batch.Messaging.loadFragment(this, message).show(supportFragmentManager, "batch-landing")
    }
} catch (e: BatchMessagingException) {
    e.printStackTrace()
}
```

{% endtab %}

{% tab title="Java" %}

```java
try {
      BatchMessage message = pushPayload.getLandingMessage();
      switch (message.getFormat()) {
          case FULLSCREEN:
              Batch.Messaging.loadFragment(this, message)
                .show(getSupportFragmentManager(), "batch-landing");
              break;
          case BANNER:
              Batch.Messaging.loadBanner(this, message).show(this);
              break;
      }
  }
catch (BatchMessagingException e) {
    e.printStackTrace();
}
```

{% endtab %}
{% endtabs %}

You should now do:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
try {
    val message = pushPayload.getLandingMessage()
    val messagingView = Batch.Messaging.loadMessagingView(this, message)
    when (messagingView.kind) {
        BatchMessagingView.Kind.Fragment -> messagingView.showFragment(supportFragmentManager, "batch-landing")
        BatchMessagingView.Kind.View -> messagingView.showView(this)
    }
    return
} catch (e: BatchMessagingException) {
    e.printStackTrace()
}
```

{% endtab %}

{% tab title="Java" %}

```java
try {
    BatchMessage message = pushPayload.getLandingMessage();
    BatchMessagingView messagingView = Batch.Messaging.loadMessagingView(this, message);
    switch (messagingView.getKind()) {
        case Fragment:
            messagingView.showFragment(getSupportFragmentManager(), "batch-landing");
            break;
        case View:
            messagingView.showView(this);
            break;
    }
} catch (BatchMessagingException e) {
    e.printStackTrace();
}
```

{% endtab %}
{% endtabs %}

For more information, please visit the Mobile Landing [manual mode](/developer/sdk/android/mobile-landings.md#manual-mode) section.

***

To see in details what's precisely changed since V2 please consult our [changelog](https://doc.batch.com/developer/sdk/android/advanced/pages/gh7o4aUsZ7i8Rlo8hq5K#id-3.0.0) or visit the [APIs Reference](https://batchlabs.github.io/Batch-Android-SDK/).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://doc.batch.com/developer/sdk/android/advanced/3x-migration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
