-
Notifications
You must be signed in to change notification settings - Fork 0
Upgrade to Kaleyra Video SDK v4.x
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.
- kotlin 1.9.0 or newer
- target api 33 (lower apis are deprecated from play store since January 2023)
- kotlinCompilerExtensionVersion 1.5.3 or newer
- JDK 17
- jvmTarget = "1.8"
- For more details you can view the open-sourced code of this repo
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.
- 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) |
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) |
v4 | v3 |
KaleyraVideo.connect("https://") // returns a Deferred<User> |
var callIntent = BandyerIntent.Builder().startFromJoinCallUrl(currentActivity,"https://....").build()
startActivity(callIntent) |
v4 | v3 |
KaleyraVideo.disconnect(clearSavedData = false) |
BandyerSDK.getInstance().disconnect(clearSavedData = true) // or BandyerSDK.getInstance().disconnect() |
v4 | v3 |
KaleyraVideo.reset() |
BandyerSDK.getInstance().reset() |
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
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.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
v4 | v3 |
KaleyraVideo.conference.joinUrl("https://....") : Result<Call> |
var callIntent = BandyerIntent.Builder().startFromJoinCallUrl(currentActivity,"https://....").build()
startActivity(callIntent) |
v4 | v3 |
// this will create the unique chat between logged user and "userB"
KaleyraVideo.conversation.chat(currentActivity, userId = "userB") : Result<Chat>
// this will create the unique chat between logged user, "userB" and "userC"
KaleyraVideo.conversation.chat(currentActivity, userIds = listOf("userB", "userC")): Result<ChatUI>
// this will always create a new group chat between logged user, "userB" and "userC" with the
// group chat friendly name set as "soccer team!"
KaleyraVideo.conversation.chat(currentActivity, userIds = listOf("userB", "userC"), friendlyName = "soccer team!"): Result<ChatUI> |
var chatIntent = BandyerIntent.Builder().startWithChat(currentActivity).with("userB").build()
startActivity(chatIntent) |
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()
) |
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()
) |
- 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) |
- 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) |
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) |
Have been removed as they are not needed.
call.withFeedback = true // or false
call.disableProximity = true // or false
KaleyraVideo.conference.call.onEach {
it.inputs.useBackCamera()
}.launchIn(MainScope())
Please add and implement abstract class KaleyraVideoInitializer in order to handle edge cases when the connection token expires and the application has been killed from the user or from the system. Add the following metadata to the AndroidManifest.xml inside the application tag. The metadata is needed in order to instantiate your KaleyraVideoInitializer class from within the SDK.
<!-- app manifest -->
<application>
[...]
<meta-data
android:name="kaleyra_video_initializer"
android:value="com.example.app.AppKaleyraVideoInitializer" /> <!-- path to your KaleyraVideInitializer implementation -->
</application>
Implement the App Initializer as follows:
package com.example.app
// KaleyraVideoInitializer implementation
class AppAppKaleyraVideoInitializer : KaleyraVideoInitializer() {
override fun onRequestKaleyraVideoConfigure() {
if (KaleyraVideo.isConfigured) return
val configuration = Configuration(
"appId",
Environment.Production,
Region.Europe
)
KaleyraVideo.configure(configuration)
}
override fun onRequestKaleyraVideoConnect() {
KaleyraVideo.connect("userId") { requestToken("userId") }
}
}
KaleyraVideo.userDetailsProvider = { userIds: List<String> ->
Result.success(userIds.map { UserDetails(it,"Alice", Uri.EMPTY) })
}
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.
val brandColorSeed = ColorResource(Color(0xFF2A638A).toArgb())
val brandLogoUri = getYourBrandLogoUri()
KaleyraVideo.theme = Theme(
logo = Theme.Logo(URIResource(brandLogoUri, brandLogoUri)),
palette = Theme.Palette(seed = brandColorSeed),
typography = Theme.Typography(fontFamily = KaleyraFontFamily.default),
config = Theme.Config(style = Theme.Config.Style.System) // or force light mode with Theme.Config.Style.Light and dark with Theme.Config.Style.Dark
)