Skip to content

Upgrade to Kaleyra Video SDK v4.x

Federico Marin edited this page May 2, 2024 · 10 revisions

Upgrade to v4.+

This new version comes with general improvements, comes with APIs that have been simplified to let the SDK integration be easier for third part apps.

The new version of the SDK brings a lot of new features and simplifies the integration flow by a huge margin.


Updated Requirements

UI fully re-written in compose

  • For more details you can view the open-sourced code of this repo

APIs changes

The APIs will no longer be made with Java-flavored. They will be fully developed in Kotlin and for it only.

| N.B. The SDK will continue to work with Java projects, it just will not be beautiful when used in java.

Configure the KaleyraVideo (previously BandyerSDK)

  • The SDK configuration has been changed and must be now implemented using the new API on the BandyerSDK singleton that follows:
v4 v3
val configuration = Configuration(
	"mAppId_xxx",  
	Environment.Sandbox,
	Region.Europe, // or Region.India or Region.US
        // httpStack,  
        // logger
)
KaleyraVideo.configure(configuration)
val configuration = BandyerSDKConfiguration.Builder(
	"mAppId",
	Environment.Sandbox,
	Region.Eu) 
// .httpStack(okHttpClient)
// .logger(logger)
  .build()
BandyerSDK.getInstance().configure(configuration)

Connect

v4 v3
KaleyraVideo.connect("userA",  { expiresAt ->
    Result.success("fetchedTokenFromYourServer") // or Result.fail()
}) // returns a Deferred<User>
val session = Session("userA",object :AccessTokenProvider{
   override fun provideAccessToken(userId: String, completion: Completion<String>) {
   	completion.success("fetchedTokenFromYourServer") // completion.fail()
   }
})
BandyerSDK.getInstance().connect(session)

Connect Access Link

v4 v3
KaleyraVideo.connect("https://") // returns a Deferred<User>
var callIntent = BandyerIntent.Builder().startFromJoinCallUrl(currentActivity,"https://....").build()
startActivity(callIntent)

Disconnect

v4 v3
KaleyraVideo.disconnect(clearSavedData = false)
BandyerSDK.getInstance().disconnect(clearSavedData = true) // or BandyerSDK.getInstance().disconnect()

Reset

v4 v3
KaleyraVideo.reset()
BandyerSDK.getInstance().reset()

Handle push notifications

You no longer need to give any payload to the KaleyraVideo. You are only required to configure & connect the KaleyraVideo.

Please follow the client side requirements as specified here.

N.B. After the connect the KaleyraVideo will auto sync with the incoming calls and chat messages

Start a call

v4 v3
KaleyraVideo.conference.call(listOf("userB")) { // vararg
  preferredType = Call.PreferredType.audioOnly() // audioUpgradable(), audioVideo()
    // recordingType = Call.Recording.Type.manual() // Call.Recording.Type.automatic()
    // maxDuration = 60L // in seconds >= 60
}: Result<Call>
var callIntent = BandyerIntent.Builder().startWithAudioCall(activity) //  startWithAudioUpgradableCall, startWithAudioVideoCall
     .with(arrayListOf("userB"))
     .build()

startActivity(callIntent)

Call properties

// call.id
// call.creationDate
// call.state
// call.preferredType
// call.participants
// call.time.maxDuration, call.time.elapsed, call.time.remaining
// call.inputs
// call.effects
// call.recording.state, call.recording.type
// call.whiteboard
// call.sharedFolder

Join a call

v4 v3
KaleyraVideo.conference.joinUrl("https://....") : Result<Call>
var callIntent = BandyerIntent.Builder().startFromJoinCallUrl(currentActivity,"https://....").build()
startActivity(callIntent)

Start a chat

v4 v3
KaleyraVideo.conversation.chat(currentActivity, listOf("userB")) : Result<Chat>
var chatIntent =  BandyerIntent.Builder().startWithChat(currentActivity).with("userB").build()
startActivity(chatIntent)

Advanced

Call UI tools/actions

SDK actions definition has been strongly simplified

v4 v3
KaleyraVideo.conference.callActions 
    = CallUI.Action.default + FileShare
val callOptions: CallOptions = CallOptions()
           .withRecordingEnabled(AUTOMATIC)
           .withBackCameraAsDefault()
           .withProximitySensorDisabled()
           .withFeedbackEnabled()

val callCapabilitySet = CustomCapabilitySet(
   CustomChatConfiguration(),
   CustomFileShareConfiguration(),
   CustomScreenShareConfiguration(),
   CustomWhiteboardConfiguration()
)

val customCallConfiguration = CustomCallConfiguration(callCapabilitySet, callOptions)

BandyerSDK.getInstance().configure(
   BandyerSDKConfiguration.Builder("mAppId", Environment.Sandbox, Region.Eu).tools {
       withCall {
           callConfiguration = customCallConfiguration
       }
   }.build()
)

Chat UI tools/actions

v4 v3
KaleyraVideo.conversation.chatActions 
    = ChatUI.Action.default
val callOptions = CallOptions()
   .withRecordingEnabled(CallRecordingType.AUTOMATIC) 
   .withBackCameraAsDefault()
   .withProximitySensorDisabled()
   .withFeedbackEnabled();

val callConfiguration = CustomChatConfiguration.CustomCapabilitySet.CustomCallConfiguration(
   CustomChatConfiguration.CustomCapabilitySet.CustomCallConfiguration.CustomCapabilitySet(
       CustomFileShareConfiguration(),
       CustomScreenShareConfiguration(),
       CustomWhiteboardConfiguration()
   ),
   callOptions
);

val customChatConfiguration = CustomChatConfiguration(
   CustomChatConfiguration.CustomCapabilitySet(
       audioUpgradableCallConfiguration =   callConfiguration, 
       audioVideoCallConfiguration  = callConfiguration
   )
)


BandyerSDK.getInstance().configure(
   BandyerSDKConfiguration.Builder("mAppId", Environment.Sandbox, Region.Eu).tools {
       withChat {
           chatConfiguration = customChatConfiguration
       }
   }.build()
)

Call events

  • CallObserver, CallUIObserver & CallEventBroadcastReceiver have been removed and replaced by state flow property
v4 v3
call.state.onEach { println("callState=$it") }.launchIn(MainScope())
val callObserver = object : CallObserver {
   override fun onCallCreated(call: Call) = println("onCallCreated")
   override fun onCallStarted(call: Call) = println("onCallStarted")
   override fun onCallEnded(call: Call) = println("onCallEnded")
   override fun onCallEndedWithError(call: Call, exception: CallException) = println("onCallEndedWithError")
}
BandyerSDK.getInstance().callModule?.addCallObserver(callObserver)
  • CallRecordingObserver has been removed and replaced by extras.recording.state flow property
v4 v3
call.recording
    .flatMapLatest { it.state }
    .onEach {  println("recordingState=$it") }
    .launchIn(MainScope())
val callRecordingObserver = object : CallRecordingObserver {
   override fun onCallRecordingStateChanged(call: Call, callRecordingState: CallRecordingState) = println("onCallRecordingStateChanged")
   override fun onCallRecordingFailed(call: Call, reason: String) = println("onCallRecordingFailed")
}
call.addCallRecordingObserver(callRecordingObserver)

Chat events

  • ChatObserver & ChatEventBroadcastReceiver have been removed. You can now know the state of the chat by using the state flow property
v4 v3
chat.state.onEach { println("chatState=$it") }.launchIn(MainScope())
val chatObserver = object : ChatObserver {}
BandyerSDK.getInstance().chatModule?.addChatObserver(chatObserver)

Module Observer

v4 v3
// for the call
BandyerSDK.conference.state.onEach { println("conferenceState=$it") }.launchIn(MainScope())
// for the chat
BandyerSDK.conversation.state.onEach { println("conversationState=$it") }.launchIn(MainScope())
val moduleObserver = object : BandyerModuleObserver {
   override fun onModuleReady(module: BandyerModule) = println("onModuleReady")
   override fun onModulePaused(module: BandyerModule)  = println("onModulePaused")
   override fun onModuleFailed(module: BandyerModule, throwable: Throwable) = println("onModuleFailed")
   override fun onModuleStatusChanged(module: BandyerModule, moduleStatus: BandyerModuleStatus) = println("onModuleStatusChanged")
}
BandyerSDK.getInstance().addModuleObserver(moduleObserver)

NotificationListeners

Have been removed as they are not needed.

Extras

FeedbackUI

call.withFeedback = true // or false

DisableProximity

call.disableProximity = true // or false

BackCamera/RearCamera as Default

MainScope().launch {
    val camera = call.inputs.available.first { it is Input.Camera.Internal }
    camera.lenses.firstOrNull{ it.isRear }?.let{ camera.setLens(it) }
}

User Identity Verification Has been removed

KaleyraVideoService

Please add this abstract service in order to handle edge cases when the Token expires and the application has been murdered from the user or the system. Add the following service to the AndroidManifest.xml inside the application tag

<service  
  android:name=".DemoAppKaleyraVideoService"  
  android:exported="false">  
    <intent-filter>  
        <!-- Do not modify this -->  
  <action android:name="kaleyra_collaboration_configure" />  
    </intent-filter>  
</service>
class DemoAppKaleyraVideoService : KaleyraVideoService() {  
    override suspend fun onRequestKaleyraVideoConfigure(): Unit {
        // here you should configure the SDK
    } 
}

Client UserDetailsProvider

KaleyraVideo.userDetailsProvider = { userIds: List<String> ->
    Result.success(userIds.map { UserDetails(it,"Alice", Uri.EMPTY) })
}

Theme customization

Server Theme customization

Since every client had to provide a Theme implementation in order to customize the client call and chat UIs, has now been integrated a new convenient and centralized way to achieve the same result.

Client Theme customization

KaleyraVideo.theme = CompanyUI.Theme(
	fontFamily = androidx.compose.ui.text.font.FontFamily.SansSerif,
	defaultStyle = CompanyUI.Theme.DefaultStyle.System,
	day = CompanyUI.Theme.Style(
		logo = Uri.parse("https.//example.com/your-logo.png"), 
		colors = CompanyUI.Theme.Colors(secondary = Color(0xFF0087E2))),
	night = CompanyUI.Theme.Style(
		logo = Uri.parse("https.//example.com/your-logo.png"), 
		colors = CompanyUI.Theme.Colors(secondary = Color.Yellow))
)
Clone this wiki locally