Android SDK Migration document from 2.x to 3.x

This document details the necessary changes required when migrating from Android SDK version 2.x to version 3.x.

The Webex Connect Android SDK version 3.0.0 is a major rewrite of version 2.x. This SDK is structured into modular components, each designed to offer specific functionality. Version 3.0.0 of the SDK is built in Kotlin using Android SDK Tools 35 and requires Android API level 21 or later.

📘

Note

The current version of the modular SDK does not migrate registration data, hence we recommend continuing to use the existing 2.x version. Data migration will be added in a future version, helping to ensure a smooth transition to the modular SDK.

Please refer to the table below for more details about each module and its functionality. This information will help you understand what's available in each module and decide which modules you want to integrate into your application.

ModuleDescription
webexconnect-coreThe core module is the foundation of the Webex Connect SDK. It provides essential functionality that all other modules depend on, including initialization, configuration, registration, and shared utilities.
webexconnect-pushThe push module enables your application to receive and handle push notifications. It abstracts the underlying push notification service, providing customized support for notification management.
webexconnect-fcmThe fcm module integrates Firebase Cloud Messaging to handle push notifications for devices with Google Play Services.
webexconnect-hmsThe hms module integrates Huawei Mobile Services to handle push notifications for devices with Huawei Mobile Services.
webexconnect-inappmessagingThe inappmessaging module offers both one-way and two-way messaging capabilities for your app.

Prerequisites

ComponentRequirement
Android Operating SystemAndroid OS 5.0 (API 21) and higher.
Software Latest version of Android Studio
Webex Connect Android SDK
Accounts- A valid Google account (required only if you're using FCM push services)
- A valid HMS account (required only if you're using HMS push services)
- An active Webex Connect account.

Integration

The following sections outline the most common tasks required to integrate the Webex Connect SDK into your Android application. While many methods remain similar to the previous version of the SDK, many of the classes and interfaces have changed, please refer the mapping tables at the end of this guide for more details.

Dependencies

The v2.x dependencies must be removed from your gradle files and replaced with the required v3.x dependencies. You only need to include dependencies that correspond to the features you wish to use.

Remove v2.x gradle dependencies:

Your gradle file will contain one of the dependencies listed below.

//For FCM builds
dependencies {
	implementation 'com.webex.connect:core-gms-full:2.x.x'//Full fat SDK
	implementation 'com.webex.connect:core-gms-lite:2.x.x'//Lite SDK
} // Use the appropriate version
//For HMS builds
dependencies {
Implementation 'com.webex.connect:core-hms-lite:2.x.x' //Full fat SDK
Implementation 'com.webex.connect:core-hms-full:2.x.x' //Lite SDK
}// Use the appropriate version

Add v3.x gradle dependencies:

Add the dependencies that correspond to the features you plan to use.

dependencies {
  
  //FCM Module - Required to use Firebase Cloud Messaging as the push provider.
  implementation 'com.webex.connect:webexconnect-fcm:3.0.0'

  //HMS Module - Required to use Huawei Mobile Services as the push provider.
  implementation 'com.webex.connect:webexconnect-hms:3.0.0'

  //In-App Messaging - Required to use In-App messaging capabilities within your app.
  implementation 'com.webex.connect:webexconnect-inappmessaging:3.0.0'

}//It is recommended to use the latest version of each module.
dependencies {

  //FCM Module - Required to use Firebase Cloud Messaging as the push provider.
  implementation("com.webex.connect:webexconnect-fcm:3.0.0")

  //HMS Module - Required to use Huawei Mobile Services as the push provider.
  implementation("com.webex.connect:webexconnect-hms:3.0.0")

  //In-App Messaging - Required to use In-App messaging capabilities within your app.
  implementation("com.webex.connect:webexconnect-inappmessaging:3.0.0")

} //It is recommended to use the latest version of each module.

🚧

Important

You should not include both FCM and HMS modules within the same build variant.

📘

Note

For information on integrating dependencies manually, please refer to our Quick Start guide.

Android manifest configuration

This section details the changes required to the AndroidManifest.xml file. Before removing any of the listed permissions, please ensure your app does not use these for functionality unrelated to the SDK.

Remove v2.x entries.

<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<application
   android:name="YOUR_APPLICATION_CLASS_NAME"
   android:allowBackup="true"
   android:label="@string/app_name"
   android:theme="@style/AppTheme">
   <activity
       android:name="YOUR_ACTIVITY_NAME"
       android:label="@string/app_name">
       <intent-filter>
           <!-- OPTIONAL enables support for push deeplinks -->
           <data
               android:host="command"
               android:scheme="@string/app_id"/>
           <category android:name="android.intent.category.DEFAULT"/>
           <category android:name="android.intent.category.BROWSABLE"/>
           <action android:name="android.intent.action.MAIN"/>
           <category android:name="android.intent.category.LAUNCHER"/>
       </intent-filter>
   </activity>
   <receiver
       android:name="com.imimobile.connect.core.messaging.ICMessagingReceiver"
       android:enabled="true"
       android:exported="false"
             android:permission="com.imimobile.connect.core.permission.PUSH_PERMISSION">
       <intent-filter>
           <action android:name="com.imimobile.connect.core.rtmevent"/>
           <action android:name="com.imimobile.connect.core.notification.click"/>
           <action android:name="com.imimobile.connect.core.intent.notification.RECEIVE"/>
       </intent-filter>
   </receiver>
</application>

Add v3.x entries.

<!-- PERMISSIONS -->
<!-- REQUIRED for connecting to Webex Connect -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- Replace YOUR_APPLICATION_CLASS_NAME with the name of the class specific to your app.-->
<application
   android:name="YOUR_APPLICATION_CLASS_NAME"
   android:allowBackup="true"
   android:label="@string/app_name"
   android:theme="@style/AppTheme">
  <activity
  		android:name="YOUR_ACTIVITY_NAME" 
      android:label="@string/app_name">
      <intent-filter>
        <!-- OPTIONAL Enables support for push deeplinks -->
        <data
          android:host="command"
          android:scheme="@string/app_id"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
  </activity>
</application>

Configure ProGuard Rules

Several ProGuard rules have changed within v3.x, the old v2.x rules must be removed and replaced with the new v3.x rules.

Remove v2.x ProGuard entries:

-dontwarn org.eclipse.jetty.** 
-dontwarn com.google.firebase.messaging.FirebaseMessaging 
-dontwarn javax.servlet.** 
-dontwarn org.slf4j.** 
  
# for sqlcipher 
-keep class net.sqlcipher.** { *; } 
-keep class net.sqlcipher.database.* { *; } 

# WorkManager 
-keep class * extends androidx.work.Worker 
-keep class * extends androidx.work.InputMerger 
-keep public class * extends androidx.work.ListenableWorker { 
  public <init>(...); 
} 
-keep class androidx.work.WorkerParameters

# For MQTT
-keep class org.eclipse.paho.client.mqttv3.** {*;}
-keep class org.eclipse.paho.android.service.** { *; }
-keepclasseswithmembers class org.eclipse.paho.** {*;}

#Proguard rules for HMS - Please include the following rules only if you integrate the HMS SDK.
-ignorewarnings -keepattributes *Annotation* 
-keepattributes Exceptions 
-keepattributes InnerClasses 
-keepattributes Signature 
-keepattributes SourceFile,LineNumberTable 
-keep class com.hianalytics.android.**{*;} 
-keep class com.huawei.updatesdk.**{*;} 
-keep class com.huawei.hms.**{*;}

Add v3.x ProGuard entries:

-keep,includedescriptorclasses class com.webex.connect.** { *; }
-keep,includedescriptorclasses interface com.webex.connect.** { *; } 

# sqlcipher 
-keep,includedescriptorclasses class net.zetetic.database.** { *; } 
-keep,includedescriptorclasses interface net.zetetic.database.** { *; } 
 
# MQTT -  Please include the following rules only if you integrate the In-App Messaging module.
-keep class org.eclipse.paho.client.mqttv3.** {*;} 
-keep class org.eclipse.paho.android.service.** { *; } 
-keepclasseswithmembers class org.eclipse.paho.** {*;} 
 
#(Optional)- Please include the following rules only if you integrate the HMS module.
-ignorewarnings 
-keepattributes *Annotation* 
-keepattributes Exceptions 
-keepattributes InnerClasses 
-keepattributes Signature 
-keepattributes SourceFile,LineNumberTable 
-keep class com.huawei.hianalytics.**{*;} 
-keep class com.huawei.updatesdk.**{*;} 
-keep class com.huawei.hms.**{*;}

Package imports

The v3.x SDK uses new package names, remove all com.imimobile.connect.* package imports and replace with the new com.webex.connect.* equivalents. It is recommended to use your IDEs inbuilt feature to include the relevant imports as you update your code, however, you may also refer to the tables below.

SDK startup

The v3.x SDK uses Android App Startup to automatically register included modules and start the SDK. Therefore, you should remove any existing v2.x startup code. Locate your call to IMIconnect.startup and remove the code; this is usually found within the onCreate method of your Application class.

Remove the v2.x startup code:

public class MyApplication extends Application 
{
    @Override
    public void onCreate() 
    {
        super.onCreate();
      
        try 
        {
            IMIconnect.startup(this);
        } catch (ICException e) 
        {
            e.printStackTrace();
        }
    }
}

📘

Note

If you have disabled App Startup for your application, please follow the manual startup instructions provided within our Quick Start guide: Manual Startup Instructions.

Device registration

The process for device registration is the same on v3.x as it is on v2.x, but class names have changed.

Remove v2.x registration code:

var userId = "YOU_USER_ID";
var deviceProfile = new ICDeviceProfile(ICDeviceProfile.getDefaultDeviceId(), userId);

IMIconnect.register(deviceProfile, new ICRegistrationCallback()
{
   @Override
   public void onRegistrationComplete(final Bundle bundle, final ICException exception)
   {
     if (exception != null) 
     {
       Log.e("Registration", "Registration failed! Reason:" + exception.toString());
     } 
     else 
     {
       Log.d("Registration", "Registration succeeded!");
     }
   }
});

Replace with v3.x code:

val webexConnect: WebexConnect = WebexConnect.instance

// Initialize a device profile
val userId = "YOUR_USER_ID"
val deviceProfile = DeviceProfile(DeviceProfile.defaultDeviceId, userId)

// Register the device
webexConnect.register(deviceProfile) { jsonObject: JSONObject?, exception: WebexConnectException? ->
    if (exception != null) {
        Log.e("Registration", "Registration failed!", exception)
    } else {
        Log.d("Registration", "Registration succeeded!")
    }
}
WebexConnect webexConnect = WebexConnect.getInstance();

// Initialize a device profile
val userId = "YOUR_USER_ID";
val deviceProfile = new DeviceProfile(DeviceProfile.getDefaultDeviceId(), userId);

// Register the device
webexConnect.register(deviceProfile, (jsonObject, exception) -> {
    if (exception != null) {
        Log.e("Registration", "Registration failed!", exception);
    } else {
        Log.d("Registration", "Registration succeeded!");
    }
		return Unit.INSTANCE; 
});

Push Notifications

Default notification channel id:

The default channel id constant has been moved to the NotificationFactory interface and the ICConstants class has been removed.

Remove v2.x code:

ICConstants.DEFAULT_CHANNEL_ID

Replace with v3.x code:

NotificationFactory.DEFAULT_CHANNEL_ID

Push Messaging Listeners

The v2.x SDK emitted incoming push through the ICMessagingReceiver class and the ICMessageListener interface, as ICMessage objects. The v3.x SDK emits push as PushMessage objects through the PushMessagingListener interface. Listeners are registered via the PushMessaging interface.

Remove v2.x code

//Push via receiver
public class MyReceiver extends ICMessagingReceiver 
{
	@Override
	protected void onMessageReceived(final Context context, final ICMessage message) 
	{
		//Handle push
	}
}

//Push via listener
ICMessaging.getInstance().registerListener(new ICMessagingListener()
{
	@Override
  public void onMessageReceived(ICMessage icMessage)
  {
   	//Handle push
  }
}

Replace with v3 code:

PushMessaging.instance.registerMessagingListener { pushMessage: PushMessage ->
	//Handle push
}
var pushMessaging = PushMessaging.getInstance();

pushMessaging.registerMessagingListener(pushMessage -> { 
  //Handle push
	return Unit.INSTANCE; 
}); 

Notification Customization

Customization of push notifications was handled in v2.x by inheriting from ICNotificationFactory and overriding the ICNotificationReceiver.getNotificationFactory method. In v3.x there are two ways to customize the notification build process.

If you currently inherit from ICNotificationFactory, please replace the code with one of the following approaches.

To add customization on top of the SDK notification build process, implement the NotificationBuilderCallback interface and set the callback on the default NotificationFactory:

class MyNotificationBuilder: NotificationBuilderCallback
{
    override fun getActionIconId(
        context: Context,
        message: PushMessage,
        action: String,
        identifier: String
    ): Int
    {
        //Return id of the icon specific to the action
        return 0
    }

    override fun onBuildNotification(
        context: Context,
        message: PushMessage,
        notificationId: Int,
        builder: NotificationCompat.Builder
    )
    {
        //Customize notification build process here
    }
}
public class MyNotificationBuilder implements NotificationBuilderCallback {

    @Override
    public int getActionIconId(Context context, PushMessage message, String action, String identifier) {
        // Return id of the icon specific to the action
        return 0;
    }

    @Override
    public void onBuildNotification(Context context, PushMessage message, int notificationId, NotificationCompat.Builder builder) {
        // Customize notification build process here
    }
}
//PushMessaging contains a deault implementation of NotificationFactory
//Use it to set your notification builder callback
PushMessaging.instance.notificationFactory?.notificationBuilderCallback = MyNotificationBuilder()

Alternatively, to entirely replace the inbuilt notification build process, implement the NotificationFactory interface and set PushMessaging.instance.notificationFactory to your custom implementation:

//Sample assumes the same channelId is used for each notification
//You may wish to dynamically assign a channelId based on the push data
class MyNotificationFactory(private val channelId: String): NotificationFactory
{
    //Callback can be null as you will handle the build within createNotification
    override var notificationBuilderCallback: NotificationBuilderCallback? = null
    
    override fun createNotification(
        context: Context,
        message: PushMessage,
        notificationId: Int,
        smallIconResourceId: Int,
        largeIcon: Bitmap?,
        bigPicture: Bitmap?
    ): Notification
    {
        var builder = Notification.Builder(context, channelId)
        //Build Notification object
        return builder.build();
    }

}

PushMessaging.instance.notificationFactory = MyNotificationFactory()

InApp Messaging

Message Store

The ICDefaultMessageStore found in v2.x has been renamed to DefaultMessageStore in v3.x, and is set using the InAppMessaging.messageStore property.

Remove v2.x code:

var store = ICDefaultMessageStore(context, password)
ICMessaging.setMessageStore(store)

Replace with v3.x code:

var store = DefaultMessageStore.create(context, "your password")
InAppMessaging.instance.messageStore = store
DefaultMessageStore store = DefaultMessageStore.create(context, "your password");
InAppMessaging.getInstance().setMessageStore(store);

Intercepting incoming messages

The v2.x SDK emitted incoming messages and connection status changes through the ICMessagingReceiver class and the ICMessageListener. The v3.x SDK uses InAppMessagingListener and ConnectionStatusListener. Listeners are registered via the InAppMessaging interface.

Remove v2.x code:

Remove any code that uses ICMessagingReceiver and ICMessageListener for handling incoming messages and connection status changes.

//In App via receiver
public class MyReceiver extends ICMessagingReceiver 
{
	@Override
	protected void onMessageReceived(final Context context, final ICMessage message) 
	{
		//Handle incoming message
	}
  
  protected void onConnectionStatusChanged(Context context, ICConnectionStatus status, ICException exception)
  {
    //Handle connection status change
  }
}

//In App via listener
ICMessaging.getInstance().registerListener(new ICMessagingListener()
{
	@Override
  public void onMessageReceived(ICMessage icMessage)
  {
   	//Handle incoming message
  }
  
  public void onConnectionStatusChanged(ICConnectionStatus status, ICException exception)
  {
    //Handle connection status change
  }
}

Replace with v3.x code:

val inAppMessaging = InAppMessaging.instance
inAppMessaging.registerMessagingListener { inAppMessage ->
	//Handle incoming message
}

inAppMessaging.registerConnectionStatusListener { connectionStatus ->
	//Handle connection status change
}
InAppMessaging.getInstance().registerMessagingListener(inAppMessage -> { 
	//Handle incoming message
	return Unit.INSTANCE; 
}); 

InAppMessaging.getInstance().registerConnectionStatusListener(connectionStatus -> 
{ 
	//Handle connection status change
	return Unit.INSTANCE; 
}); 

Class Name Changes, Method Name Changes, and New Properties

The following tables detail the class and interface mappings between v2.x and v3.x, please refer to these tables to help transition the rest of your codebase.

Note that in v3.x, we have replaced the majority of callback interfaces with typealias for improved code readability and simplicity. Please refer to the method-specific documentation relevant to your application to understand the changes and update your implementation accordingly.

Core Module

Class Name mapping from 2.x to 3.x

Push Module

Push-FCM Module :

Push-HMS Module :

In-App Messaging Module :

2.x3.x
ICMessagingInAppMessaging
ICMessageInAppMessage
ICThreadInAppThread
ICMessageStatusInAppMessageStatus
ICMessageTypeInAppMessageType
ICThreadStatusInAppThreadStatus
ICThreadTypeInAppThreadType
ICQuickReplyDataInAppQuickReply
ICInteractiveDataInAppInteractiveData
ICInteractiveDataTypeInAppInteractiveDataType
ICButtonInAppButton
ICFormFieldInAppFormField
ICFormFieldTypeInAppFormFieldType
ICGenericTemplateElementInAppGenericTemplateElement
ICAttachmentInAppAttachment
ICMediaAttachmentInAppMediaAttachment
InAppFileAttachment
ICAudioAttachmentInAppAudioAttachment
ICImageAttachmentInAppImageAttachment
ICLocationAttachmentInAppLocationAttachment
ICVideoAttachmentInAppVideoAttachment
ICTemplateAttachmentInAppTemplateAttachment
ICTemplateTypeInAppTemplateType
ICFormTemplateAttachmentInAppFormTemplateAttachment
ICGenericTemplateAttachmentInAppGenericTemplateAttachment
ICConnectionStatusConnectionStatus
ICDefaultMessageStoreDefaultMessageStore
ICMessageStoreMessageStore
ICMessageSynchronizationModeMessageSynchronizationMode
ICMessageSynchronizationPolicyMessageSynchronizationPolicy
ICMediaFileManagerMediaFileManager
ICMessagingListenerConnectionStatusListener
InAppMessagingListener
ICFileDownloadCallbackFileDownloadCallback
ICFileUploadCallbackFileUploadCallback
ICCreateThreadCallbackCreateThreadCallback
ICDeleteMessageCallbackDeleteMessageCallback
ICFetchMessagesCallbackFetchMessagesCallback
ICFetchThreadCallbackFetchThreadCallback
ICFetchThreadsCallbackFetchThreadsCallback
ICFetchUnReadThreadCountCallbackFetchUnreadThreadCountCallback
ICFetchTopicsCallbackRemoved

By following the steps outlined in this document and updating your code to reflect the changes in class names, method names, and new properties, you should be able to successfully migrate from the monolithic v2.x SDK to the modular v3.x SDK. Please ensure that you thoroughly test your application after making these changes to confirm that all functionalities are working as expected.