Signed Call Android SDK
Learn how to integrate Signed Call Android SDK in your app to avail the Signed Call feature.
Overview
CleverTap provides In-App calls via its Signed Call Android SDK, which means you can make and receive calls in any Android application if the device has an internet connection and Signed Call Android SDK. This document shows you how to integrate the Signed Call Android SDK and manage calls. To know more about the Signed Call feature, refer to Signed Call.
Requirements
The basic requirements for the Signed Call Android SDK are:
- Minimum SDK Level - 21
- Java 8 and above
- Application permissions for the following:
- Microphone (Required)
- Notification (Required for Android 13 and above)
- Read Phone State (Optional)
Emulator Support
Emulator support is available for voice calls, but voice transmission will not work.
Install Signed Call Android SDK
Download the latest version of the Signed Call Android SDK from mavenCentral
as follows:
- Include
mavenCentral
in your project-levelbuild.gradle
file as follows:
allprojects {
repositories {
mavenCentral()
}
}
- Add the following line to the dependencies element in your application module's
build.gradle
file:
implementation "com.clevertap.android:clevertap-signedcall-sdk:0.0.4"
Add Other Dependencies
To enable voice calling with the Signed Call Android SDK, add the following dependencies to your application module's build.gradle
file:
- CleverTap Android SDK
- Firebase Cloud Messaging (FCM)
- Socket-IO Client
- Glide
- Work Manager
- ConstraintLayout
CleverTap Android SDK
The Signed Call Android SDK uses CleverTap Android SDK for analytics. The Signed Call Android SDK requires an active CleverTapAPI
instance as a parameter during the SDK initialization.
To integrate the CleverTap Android SDK, refer to the CleverTap Android SDK Integration.
Minimum Supported Version
The Signed Call Android SDK v0.0.4 integrates with CleverTap SDK v5.2.0 or higher.
FCM
The Signed Call Android SDK uses FCM dependency to get the FCM token of the device required for the successful SDK initialization. This FCM token is then used by Signed Call to enable calls via FCM Based Call Routing Channel.
Perform the following steps to add the FCM dependency to your application:
- Refer to the Firebase Integration Guide to add Firebase to your project if you have not already added it.
- Add the following code to the application module's dependency element:
implementation 'com.google.firebase:firebase-messaging:21.0.0'
FCM Version
For Signed Call Android SDK, the minimum supported version of FCM is v21.0.0.
Socket-IO Client
The Signed Call Android SDK uses a Socket-IO client library to enable the socket-based signaling channel for voice calls.
us
To add the Socket-IO client dependency to your application, add the following line to the application module's dependency element:
implementation('io.socket:socket.io-client:2.1.0') {
exclude group: 'org.json', module: 'json'
}
Glide
The Signed Call Android SDK uses a Glide library for loading the image assets on the call screen.
To add the Glide dependency to your application, add the following line to the application module's dependency element:
implementation 'com.github.bumptech.glide:glide:4.12.0'
Work Manager
The Signed Call Android SDK uses a Work Manager dependency to process the incoming call push for the receiver.
To add the Work Manager dependency to your application, add the following line to the application module's dependency element:
implementation 'androidx.work:work-runtime:2.7.1'
ConstraintLayout
The Signed Call Android SDK uses a ConstraintLayout dependency to build a responsive UI for the call screens.
To add the ConstraintLayout dependency to your application, add the following line to the application module's dependency element:
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
Upgrade Java Compatibility
The Signed Call Android SDK's source and target compatibility are set to Java 8.
To upgrade your application to target Java 8, use the following snippet:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
After updating your build.gradle
file, sync your project by clicking the Sync Project button.
Initialize and Authenticate Signed Call Android SDK
Initialize the Signed Call Android SDK using the SignedCallAPI
class instance:
SignedCallInitResponse signedCallInitListener = new SignedCallInitResponse() {
@Override
public void onSuccess() {
//App is notified on the main thread when the Signed Call SDK is initialized
}
@Override
public void onFailure(@NonNull InitException initException) {
//App is notified on the main thread when the initialization is failed
Log.d("SignedCall: ", "error code: " + initException.getErrorCode()
+ "\n error message: " + initException.getMessage()
+ "\n error explanation: " + initException.getExplanation());
if (initException.getErrorCode() == InitException.SdkNotInitializedException.getErrorCode()) {
//Handle this error here
}
}
};
//Create a Builder instance of SignedCallInitConfiguration and pass it inside the init() method
SignedCallInitConfiguration initConfiguration = new SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.build();
SignedCallAPI.getInstance().init(getApplicationContext(), initConfiguration, cleverTapAPI, signedCallInitListener);
val signedCallInitListener: SignedCallInitResponse = object : SignedCallInitResponse {
override fun onSuccess() {
//App is notified on the main thread when the Signed Call SDK is initialized
}
override fun onFailure(initException: InitException) {
//App is notified on the main thread when the initialization is failed
Log.d("SignedCall: ", "error code: " + initException.errorCode
+ "\n error message: " + initException.message
+ "\n error explanation: " + initException.explanation)
if (initException.errorCode == InitException.SdkNotInitializedException.errorCode)
{
//Handle this error here
}
}
}
//Create a Builder instance of SignedCallInitConfiguration and pass it inside the init() method
val initConfiguration = SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.build()
SignedCallAPI.getInstance().init(applicationContext, initConfiguration, cleverTapAPI, signedCallInitListener)
Following are the parameters passed inside the constructor of SignedCallInitConfiguration.Builder
:
initOptions
The initOptions
is a JSON object that is passed inside the constructor of SignedCallInitConfiguration.Builder
with the following properties:
Property | Description | Type | Notes |
---|---|---|---|
|
| String | Required |
|
| String | Required |
| Unique identity of the user. | String | Required |
|
| String | Optional |
|
| String | Optional |
ringtone | The URL of the ringtone played on the caller's end during the outgoing call. Note: The default ringtone plays without this parameter. | String | Optional |
CUID Validation Rules
The following are the validation rules for
cuid
:
- Must range between 5 and 50 characters.
- Must start with either alphabet or number.
- The name is case-sensitive, and only '_' is allowed as a special character.
- The
cuid
parameter cannot be of type number-number, that is, a number followed by a special character, which is again followed by another number. For example, org_25 is allowed, but 91_8899555 is not permitted.- Must be unique for every user.
- Must be unique for every device to allow multiple logins for the user from different devices. In such cases, the user will have multiple
cuid
's.
The syntax for initOptions
is as follows:
JSONObject initOptions = new JSONObject();
try {
initOptions.put("accountId", <string>);
initOptions.put("apiKey", <string>);
initOptions.put("cuid", <string>);
initOptions.put("appId", <string / optional>);
initOptions.put("name", <string / optional>);
initOptions.put("ringtone", <string / optional>);
} catch (JSONException e) {
e.printStackTrace();
}
val initOptions = JSONObject();
try {
initOptions.put("accountId", <string>);
initOptions.put("apiKey", <string>);
initOptions.put("cuid", <string>);
initOptions.put("appId", <string / optional>);
initOptions.put("name", <string / optional>);
initOptions.put("ringtone", <string / optional>);
} catch (e: JSONException) {
e.printStackTrace();
}
allowPersistSocketConnection
The socket connection plays a crucial role in processing the call request to initiate a call and receive calls on the socket channel. Android OS imposes several battery restrictions that lead to issues in maintaining a persistent socket connection. To overcome this issue, Signed Call Android SDK expects the allowPersistSocketConnection
flag, a boolean parameter, to be passed inside the SignedCallInitConfiguration.Builder
constructor.
The following is the Signed Call Android SDK behavior:
Value | Socket Connection | Signed Call Android SDK Behavior |
---|---|---|
true | Persistent | Uses a background service to keep the socket connection persistent in the foreground and background states of the application. |
false | Non-persistent | Does not use the background service for the socket connection; hence the socket connection may be inconsistent under battery restriction scenarios. |
Recommended Settings for Android 11 and Above
For Android 11 and above, if the socket connection is persistent, the application might show a system-generated notification to the user that the application is draining the device's battery. We recommend setting the value as
false
and keeping the socket connection non-persistent for transactional businesses.
Android 13 Changes
All applications having Android 13 and above must request Runtime Notification Permission from the user before sending the notifications.
Signed Call Android SDK utilizes both local and remote notifications during VoIP calls. Therefore, notification permission is required from the user to initialize the Signed Call SDK.
Signed Call Android SDK v0.0.2 Supports Android 13
If you want to increase the target API of your application to 33 or higher, you must upgrade the following:
- Signed Call Android SDK to version 0.0.2 or higher
- CleverTap Android SDK to version 4.7.0 or higher
Push Primer for Push Notification Permission
The Push Primer is a local In-App notification that educates users about the context of the notifications before requesting the notification permission.
To initialize the Signed Call Android SDK for Android 13 and above, you can enable the Push Primer using either of the following:
Enable Push Primer via CleverTap Android SDK
CleverTap Android SDK v4.7.0 and above supports Push Primer. For more details, refer to Android Push Primer.
Enable Push Primer via Signed Call Android SDK
The Signed Call Android SDK enables you to display Push Primer using the promptPushPrimer(jsonObjectConfig)
method through the SignedCallInitConfiguration.Builder
class. It ensures the initialization happens after the notification permission is granted using Push Primer.
To configure the Push Primer:
- Create a Push Primer configuration using the In-App campaign's Half-Interstitial or Alert template.
//Creates push primer config using Half-Interstitial template
JSONObject jsonObjectConfig = CTLocalInApp.builder()
.setInAppType(CTLocalInApp.InAppType.HALF_INTERSTITIAL)
.setTitleText("Get Notified")
.setMessageText("Please enable notifications on your device to use Push Notifications.")
.followDeviceOrientation(true)
.setPositiveBtnText("Allow")
.setNegativeBtnText("Cancel")
.setBackgroundColor(Constants.WHITE)
.setBtnBorderColor(Constants.BLUE)
.setTitleTextColor(Constants.BLUE)
.setMessageTextColor(Constants.BLACK)
.setBtnTextColor(Constants.WHITE)
.setImageUrl("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png")
.setBtnBackgroundColor(Constants.BLUE)
.build();
//Creates push primer config using Alert template
JSONObject jsonObjectConfig = CTLocalInApp.builder()
.setInAppType(CTLocalInApp.InAppType.ALERT)
.setTitleText("Get Notified")
.setMessageText("Enable Notification permission")
.followDeviceOrientation(true)
.setPositiveBtnText("Allow")
.setNegativeBtnText("Cancel")
.build();
//Creates push primer config using Half-Interstitial template
val jsonObjectConfig = CTLocalInApp.builder()
.setInAppType(InAppType.HALF_INTERSTITIAL)
.setTitleText("Get Notified")
.setMessageText("Please enable notifications on your device to use Push Notifications.")
.followDeviceOrientation(true)
.setPositiveBtnText("Allow")
.setNegativeBtnText("Cancel")
.setBackgroundColor(Constants.WHITE)
.setBtnBorderColor(Constants.BLUE)
.setTitleTextColor(Constants.BLUE)
.setMessageTextColor(Constants.BLACK)
.setBtnTextColor(Constants.WHITE)
.setImageUrl("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png")
.setBtnBackgroundColor(Constants.BLUE)
.build()
//Creates push primer config using Alert template
val jsonObjectConfig = CTLocalInApp.builder()
.setInAppType(InAppType.ALERT)
.setTitleText("Get Notified")
.setMessageText("Enable Notification permission")
.followDeviceOrientation(true)
.setPositiveBtnText("Allow")
.setNegativeBtnText("Cancel")
.build()
- Pass the Push Primer configuration inside the
promptPushPrimer(jsonObjectConfig)
method of theSignedCallInitConfiguration.Builder
class.
SignedCallInitConfiguration initConfiguration = new SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.promptPushPrimer(jsonObjectConfig)
.build();
SignedCallAPI.getInstance().init(getApplicationContext(), initConfiguration, cleverTapAPI, signedCallInitListener);
val initConfiguration = SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.promptPushPrimer(jsonObjectConfig)
.build()
SignedCallAPI.getInstance().init(applicationContext, initConfiguration, cleverTapAPI, signedCallInitListener)
Note
- The above configuration enables the Push Primer only if the device and application both target Android 13 (API level 33) or higher.
- To obtain the result of the push notification permission request, the Signed Call SDK registers a listener. After registration, this listener continues monitoring the permission result, even if the Push Primer prompt is displayed from the CleverTap Android SDK.
- If the notification permission is denied, the Signed Call Android SDK returns
InitException.NotificationPermissionRequiredException
within theonFailure(initException)
method.- The initialization of the Signed Call Android SDK with the Push Primer configuration mentioned above should be invoked within the
onResume
lifecycle method of the Activity.
Permission Management
Following are the permissions that the Signed Call Android SDK uses and their management:
Microphone
This is a required permission. The Signed Call Android SDK requires microphone permission to exchange voices during the call. At the receiver's end, the Signed Call Android SDK asks for microphone permission and handles it accordingly when the receiver answers the call. We recommend you add the required handling to request the microphone permission before initiating a call.
Note
Starting from Signed Call Android SDK v0.0.3, microphone permission prompt limit displayed during a VoIP call is aligned with the permissible threshold set by Android platform. Previously, the Signed Call Android SDK blocked all incoming calls at the receiver's end if the microphone permission was denied even once.
Read Phone State
This is optional permission. The Signed Call Android SDK uses this permission to enable busy handling for Public Switched Telephone Network (PSTN) calls. This permission determines if the receiver is available or busy on a PSTN call. We recommend you add the required handling to request the Read Phone State permission before initiating a call.
The Signed Call Android SDK exposes a promptReceiverReadPhoneStatePermission(boolean)
method via the SignedCallInitConfiguration.Builder
class. Pass the boolean flag as true
to allow the Signed Call Android SDK to prompt for the read phone state permission at the receiver's end when the receiver answers the call.
SignedCallInitConfiguration initConfiguration = new SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.promptReceiverReadPhoneStatePermission(<pass boolean here>)
.build();
SignedCallAPI.getInstance().init(getApplicationContext(), initConfiguration, cleverTapAPI, signedCallInitListener);
val initConfiguration = SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.promptReceiverReadPhoneStatePermission(<pass boolean here>)
.build()
SignedCallAPI.getInstance().init(applicationContext, initConfiguration, cleverTapAPI, signedCallInitListener)
Logout the Signed Call Android SDK
When the Signed Call Android SDK initializes, it maintains the init configuration in a local session. Use the logout(context)
method to reset the active session and disable the Signed Call functionality (call initiation and reception).
SignedCallAPI.getInstance().logout(getApplicationContext());
SignedCallAPI.getInstance().logout(applicationContext)
Make a Signed Call
Use the following code to make a Signed Call:
OutgoingCallResponse outgoingCallResponseListener = new OutgoingCallResponse() {
@Override
public void callStatus(VoIPCallStatus callStatus) {
//App is notified on the main thread to notify the changes in the call-state
if (callStatus == VoIPCallStatus.CALL_CANCELLED) {
//when the call is cancelled from the initiator's end
} else if (callStatus == VoIPCallStatus.CALL_DECLINED) {
//when the call is declined from the receiver's end
} else if (callStatus == VoIPCallStatus.CALL_MISSED) {
//when the call is missed at the receiver's end
} else if (callStatus == VoIPCallStatus.CALL_ANSWERED) {
//When the call is picked up by the receiver
} else if (callStatus == VoIPCallStatus.CALL_IN_PROGRESS) {
//when the connection to the receiver is established
} else if (callStatus == VoIPCallStatus.CALL_OVER) {
//when the call has been disconnected
} else if (callStatus == VoIPCallStatus.CALLEE_BUSY_ON_ANOTHER_CALL) {
//when the receiver is busy on another call
}
}
@Override
public void onSuccess() {
//App is notified on the main thread when the call-request is accepted and being processed by the signalling channel
}
@Override
public void onFailure(CallException callException) {
//App is notified on the main thread when the call is failed
Log.d("SignedCall: ", "error code: " + callException.getErrorCode()
+ "\n error message: " + callException.getMessage()
+ "\n error explanation: " + callException.getExplanation());
if (callException.getErrorCode() == CallException.BadNetworkException.getErrorCode()) {
//Handle this error here
}
}
};
SignedCallAPI.getInstance().call(getApplicationContext(), receiverCuid, contextOfCall, callOptions, outgoingCallResponseListener);
val outgoingCallResponseListener: OutgoingCallResponse = object : OutgoingCallResponse {
override fun callStatus(callStatus: VoIPCallStatus) {
//App is notified on the main thread to notify the changes in the call-state
if (callStatus == VoIPCallStatus.CALL_CANCELLED) {
//when the call is cancelled from the initiator's end
} else if (callStatus == VoIPCallStatus.CALL_DECLINED) {
//when the call is declined from the receiver's end
} else if (callStatus == VoIPCallStatus.CALL_MISSED) {
//when the call is missed at the receiver's end
} else if (callStatus == VoIPCallStatus.CALL_ANSWERED) {
//When the call is picked up by the receiver
} else if (callStatus == VoIPCallStatus.CALL_IN_PROGRESS) {
//when the connection to the receiver is established
} else if (callStatus == VoIPCallStatus.CALL_OVER) {
//when the call has been disconnected
} else if (callStatus == VoIPCallStatus.CALLEE_BUSY_ON_ANOTHER_CALL) {
//when the receiver is busy on another call
}
}
override fun onSuccess() {
//App is notified on the main thread when the call-request is accepted and being processed by the signalling channel
}
override fun onFailure(callException: CallException) {
//App is notified on the main thread when the call is failed
Log.d("SignedCall: ", "error code: ${callException.errorCode}"
+ "\n error message: ${callException.message}"
+ "\n error explanation: ${callException.explanation}")
}
}
SignedCallAPI.getInstance().call(applicationContext, receiverCuid, contextOfCall, callOptions, outgoingCallResponseListener)
The parameters to make a Signed Call are as follows:
Parameter | Description | Type | Notes |
---|---|---|---|
| It is the receiver's | String | Required |
| It specifies the context of the call. For example, Delivery Partner is calling, Driver is calling, Agent is calling, and so on.
| String | Required |
| It is a JSON object with the following properties:
| JSON Object | Optional |
Call Quality Control
The Signed Call Android SDK always checks the ping latency before processing the call initiation request. If the latency is more than 3 seconds, the Signed Call Android SDK does not process the call request and returns a CallException.BadNetworkException
exception.
Receive a Signed Call
Signed Call uses the following routing channels to receive Signed Calls at the receiver's end:
Socket Channel
It is a primary routing channel. Signed Call Android SDK requires a successful initialization to receive a call on the socket channel.
FCM Channel
It is a secondary or fallback routing channel that is used when the receiver is not connected to the primary routing channel (Socket).
To enable the FCM channel, follow the steps below:
-
Add your FCM Server Key to the Signed Call section of the CleverTap dashboard. Ignore it if you have already added it.
-
Add the following code to your
Application
class:
CleverTapAPI.setSignedCallNotificationHandler(new SignedCallNotificationHandler());
CleverTapAPI.setSignedCallNotificationHandler(SignedCallNotificationHandler())
- Add the following code inside your
FirebaseMessagingService
:
public class MyFcmMessageListenerService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage message){
new CTFcmMessageHandler().createNotification(getApplicationContext(), message);
}
}
class MyFcmMessageListenerService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
CTFcmMessageHandler().createNotification(applicationContext, message)
}
}
Note
If you use CleverTap's Listener Service. to handle the push notifications, then step 3 is not required. However, if you use both, the Signed Call Android SDK receives duplicate pushes for the same VoIP call. The SDK then rejects the duplicate push, which may cause the initiator to experience the receiver as busy on another call, even though the receiver would still be able to pick the call corresponding to initial VoIP push.
Important
The Missed Call Implementation is mandatory to receive calls via FCM channel for Signed Call Android v0.0.2 and below.
Close Socket Connection
The Signed Call Android SDK uses the socket connection to signal VoIP calls from the initiator to the receiver. After successful SDK initialization, the socket connection to initiate or receive VoIP calls opens.
If the socket is left open for a longer period, the application might show a system-generated notification to the user that the application is draining the device's battery. Therefore, we recommend disconnecting the socket after all expected/pending transactions are over.
To close the socket connection, use the following method as per your business use case:
SignedCallAPI.getInstance().disconnectSignallingSocket(getApplicationContext());
SignedCallAPI.getInstance().disconnectSignallingSocket(applicationContext);
The following is the Signed Call Android SDK behavior after the SDK calls the disconnectSignallingSocket(appContext)
method:
Functionality | Signed Call Android SDK Behavior |
---|---|
Initiate a call | Users cannot initiate calls. If they attempt a VoIP call request, Signed Call Android SDK returns CallException.SignallingSocketConnectionRequiredException within the onFailure(callException) method. It is essential to reinitialize the Signed Call SDK if a use case arises where a call needs to be initiated.For example, if a user happens to place an order in the application and you want to give the option to initiate a VoIP call, the Signed Call Android SDK needs to be reinitialized. |
Receive a call | Users can still receive calls as Signed Call uses FCM as a fallback channel to receive the calls. |
Busy Handling
Signed Call Android SDK smartly handles the scenarios when the user is busy on a call.
The following scenarios describe the Signed Call Android SDK behavior:
Scenario 1: The user is busy on a call (VoIP or PSTN), and another user initiates a VoIP call to the busy user. In this case, the Signed Call Android SDK displays User is busy on another call on the outgoing call screen and declines the initiated call.
Scenario 2: The user is busy on a VoIP call, and meanwhile, the user answers a PSTN call meaning that two calls (VoIP and PSTN) are connected simultaneously. In this case, the Signed Call Android SDK prioritizes the PSTN call over the VoIP call by putting the VoIP call on hold for both the receiver and initiator of the VoIP call. After the PSTN call ends, the Signed Call Android SDK resumes the VoIP call.
Prerequisites of Busy Handling Scenarios
The Signed Call Android SDK needs Read Phone State permission to handle the busy handling scenarios of PSTN calls.
- In scenario 1, Signed Call Android SDK uses this permission to determine if the user is available or busy on a PSTN call. This permission is required for Android 12 and onwards only.
- In scenario 2, the Signed Call Android SDK supports the underlying implementation only if the user has granted the Read Phone State permission.
Missed Call Solution
If the receiver misses a call, the Signed Call Android SDK shows a missed call notification to the receiver. The Signed Call Android SDK uses action buttons on the missed call notification to display a Call to Action (CTA).
To configure the CTA on the missed call notification, perform the following steps during the initialization of the Signed Call Android SDK:
- Create a list of CTAs using the
MissedCallAction
class.
List<MissedCallAction> missedCallActionsList = new ArrayList<>();
missedCallActionsList.add(new MissedCallAction("<Unique Identifier>", "<label on action-button>"));
val missedCallActionsList: MutableList<MissedCallAction> = ArrayList()
missedCallActionsList.add(MissedCallAction("<Unique Identifier>", "<label on action-button>"))
Action Buttons
You can configure a maximum of three action buttons on a missed call notification.
- Handle the click events of the missed call CTAs. To do so, create a custom
MissedCallActionsHandler
class by implementing theMissedCallNotificationOpenedHandler
.
public class MissedCallActionsHandler implements MissedCallNotificationOpenedHandler {
@Override
public void onMissedCallNotificationOpened(Context context, MissedCallNotificationOpenResult result) {
//get the the action-details from result object and handle accordingly
Log.d(TAG, "actionID: " + result.action.actionID
+ " actionLabel: " + result.action.actionLabel
+ " context of call: " + result.callDetails.callContext
+ " cuid of caller: " + result.callDetails.callerCuid
+ " cuid of callee: " + result.callDetails.calleeCuid);
}
}
class MissedCallActionsHandler : MissedCallNotificationOpenedHandler {
override fun onMissedCallNotificationOpened(context: Context, result: MissedCallNotificationOpenResult) {
//get the the action-details from result object and handle accordingly
Log.d(TAG, "actionID: " + result.action.actionID
+ " actionLabel: " + result.action.actionLabel
+ " context of call: " + result.callDetails.callContext
+ " cuid of caller: " + result.callDetails.callerCuid
+ " cuid of callee: " + result.callDetails.calleeCuid);
}
}
Note
The
MissedCallActionsHandler
must not be a singleton class.
- Pass the list of
MissedCallAction
and the canonical path of theMissedCallActionsHandler
in the
setMissedCallActions(List<MissedCallAction> list, String path)
method of theSignedCallInitConfiguration.Builder
class.
List<MissedCallAction> missedCallActionsList = new ArrayList<>();
missedCallActionsList.add(new MissedCallAction("<Unique Identifier>", "<label on action-button>"));
//gets the name of the class including its package
String missedCallHandlerPath = MissedCallActionsHandler.class.getCanonicalName();
SignedCallInitConfiguration initConfiguration = new SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.setMissedCallActions(missedCallActionsList, missedCallHandlerPath)
.build();
SignedCallAPI.getInstance().init(getApplicationContext(), initConfiguration, cleverTapAPI, signedCallInitListener);
val missedCallActionsList: MutableList<MissedCallAction> = ArrayList()
missedCallActionsList.add(MissedCallAction("<Unique Identifier>", "<label on action-button>"))
//gets the name of the class including its package
val missedCallHandlerPath = MissedCallActionsHandler::class.java.canonicalName
val initConfiguration = SignedCallInitConfiguration.Builder(options, allowPersistSocketConnection)
.setMissedCallActions(missedCallActionsList, missedCallHandlerPath)
.build()
SignedCallAPI.getInstance().init(applicationContext, initConfiguration, cleverTapAPI, signedCallInitListener)
Call Hangup Functionality
The call hangup functionality is user-driven, and ending the call depends on the user. For example, if one of the users in a call clicks the call hangup button from the ongoing call screen, the Signed Call Android SDK internally manages the call hangup functionality to end the call.
In the case of a metered call, when a business wants to end the call after a specific duration, you must maintain a timer in the application and use the following method to terminate the call when the timer ends:
SignedCallAPI.getInstance().getCallController().endCall();
SignedCallAPI.getInstance().callController?.endCall()
Override the Dashboard Branding for Call Screen
CleverTap dashboard provides a branding tool to alter the look and feel of the call screens. If you have multiple applications to integrate with the Signed Call Android SDK, all those applications will share the same branding that you have set from the CleverTap dashboard. By overriding the dashboard's call screen branding, you can have different branding for each application.
To override the dashboard branding, use the overrideDefaultBranding(SignedCallScreenBranding branding)
method exposed via the SignedCallInitConfiguration.Builder
class:
SignedCallScreenBranding callScreenBranding = new SignedCallScreenBranding(bgColor, fontColor, logoUrl, buttonTheme);
callScreenBranding.setShowPoweredBySignedCall(<true/false>); //set false to hide the label from VoIP call screens. Default value is true.
SignedCallInitConfiguration initConfiguration = new SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.overrideDefaultBranding(callScreenBranding)
.build();
SignedCallAPI.getInstance().init(getApplicationContext(), initConfiguration, cleverTapAPI, signedCallInitListener);
val callScreenBranding = SignedCallScreenBranding(bgColor, fontColor, logoUrl, buttonTheme)
val initConfiguration = SignedCallInitConfiguration.Builder(initOptions, allowPersistSocketConnection)
.overrideDefaultBranding(callScreenBranding)
.build()
SignedCallAPI.getInstance().init(applicationContext, initConfiguration, cleverTapAPI, signedCallInitListener)
The parameters to override the dashboard's call screen branding are as follows:
Parameter | Description | Type | Notes |
---|---|---|---|
bgColor | The background color of the call screens. Note: Use any Hex color code. For example, #000000 | String | Required |
fontColor | The color of the text displayed on the call screens. Note: Use any Hex color code. For example, #ffffff | String | Required |
logoUrl | The image URL that renders on the call screens. Note: Use an HTTPS URL only. | String | Required |
buttonTheme | The theme of the control buttons shown on the ongoing call screen (Mute, Speaker, and Bluetooth). Note: The Light theme represents the white color of the buttons whereas Dark is for the black color. | SignedCallScreenBranding.ButtonTheme.LIGHT OR SignedCallScreenBranding.ButtonTheme.DARK | Required |
Debugging
Signed Call Android SDK logs are, by default, set to the SignedCallAPI.LogLevel.INFO
level. We recommend you set the Signed Call Android SDK to VERBOSE mode to log warnings or other important messages to the Android logging system during development. To do so, set the debug level to SignedCallAPI.LogLevel.VERBOSE
. If you want to disable the Signed Call Android SDK logs for the production environment, you can set the debug level to SignedCallAPI.LogLevel.OFF
.
To debug your application with the Signed Call Android SDK:
- Set the debug level for the Signed Call Android SDK.
SignedCallAPI.setDebugLevel(SignedCallAPI.LogLevel.INFO); //Default Log level
SignedCallAPI.setDebugLevel(SignedCallAPI.LogLevel.DEBUG); //Set Log level to DEBUG log warnings or other important messages
SignedCallAPI.setDebugLevel(SignedCallAPI.LogLevel.VERBOSE); //Set Log level to VERBOSE
SignedCallAPI.setDebugLevel(SignedCallAPI.LogLevel.OFF); //Switch off the logs for Production environment
SignedCallAPI.setDebugLevel(SignedCallAPI.LogLevel.INFO) //Default Log level
SignedCallAPI.setDebugLevel(SignedCallAPI.LogLevel.DEBUG) //Set Log level to DEBUG log warnings or other important messages
SignedCallAPI.setDebugLevel(SignedCallAPI.LogLevel.VERBOSE) //Set Log level to VERBOSE
SignedCallAPI.setDebugLevel(SignedCallAPI.LogLevel.OFF) //Switch off the logs for Production environment
- After setting the debug level to
SignedCallAPI.LogLevel.VERBOSE
, search for
[CT]:[SignedCall]. The logcat window displays the handshakes between the Signed Call Android SDK and your application.
Error Handling
The Signed Call Android SDK provides error reporting and handling. The onFailure(InitException)
of the SignedCallInitResponse
reports all the initialization related errors, where the onFailure(CallException)
of the OutgoingCallResponse
reports all the Call related errors.
Initialization Errors
Following is the list of the error objects that you may receive when initializing the Signed Call Android SDK:
Error Object | Error Code | Error Description |
---|---|---|
NoInternetException | 1000 | No internet connection. |
AppContextRequiredException | 2000 | The application context is missing. |
CleverTapApiInstanceRequiredException | 2001 | The CleverTapApi instance is missing. |
InitConfigRequiredException | 2002 | The initOptions is missing. |
SdkNotInitializedException | 2003 | The Signed Call Android SDK is not initialized. |
MissingAccountIdOrApiKeyException | 2004 | The accountId and apiKey parameters are missing. |
MissingCuIdException | 2005 | The cuid is missing. |
InvalidCuidLengthException | 2006 | The cuid length is invalid. |
InvalidCuidException | 2007 | Invalid cuid due to violation of valid cuid rules. |
InvalidNameLengthException | 2008 | The length of the name parameter is invalid. |
InvalidAppIdException | 2009 | The appId is invalid. |
InvalidBrandingConfigException | 2010 | The branding configuration is invalid. |
BadRequestException | 2011 | The values in initOptions are invalid. |
AuthFailureException | 2012 | The user authentication is not successful. |
NotificationPermissionRequiredException | 2013 | The notification permission was not given during the SDK initialization. |
Call Errors
Following is the list of possible error objects when making a call:
Error Object | Error Code | Error Description |
---|---|---|
NoInternetException | 1000 | No internet connection. |
MicrophonePermissionNotGrantedException | 5001 | Microphone permission is not available. |
InternetLostAtReceiverEndException | 5002 | The Internet is lost at the receiver's end before the call connects. |
ContactNotReachableException | 5003 | The receiver is unreachable. |
BadNetworkException | 5004 | The Signed Call Android SDK can not initiate the call because of a poor network. |
CanNotCallSelfException | 5005 | The Receiver and Initiator's cuid is the same. |
CallContextRequiredException | 5006 | The context of the call is missing. |
CallContextExceededBy64Exception | 5007 | The length of the context message exceeds the limit of 64 characters. |
InvalidAppContextException | 5008 | Invalid context of the application. |
CalleeInfoRequiredException | 5009 | The receiver's cuid is missing. |
VoIPCallException | 5010 | The signed call can not be initiated to the unregistered/invalid cuid . |
SignallingSocketConnectionRequiredException | 5011 | The socket required to initiate a call is not connected to the signaling channel. |
IncorrectParamsInCallOptionsException | 5012 | The callOptions parameters are invalid. |
CanNotProcessCallRequest | 5013 | Cannot process new call requests as the Signed Call Android SDK is already processing another. |
CallFeatureNotAvailable | 5014 | The call feature is not enabled to initiate the call. |
FAQs
Q. Is Signed Call accountId
and apiKey
the same as CleverTap's accountId
and token
?
accountId
and apiKey
the same as CleverTap's accountId
and token
?A. No. Signed Call accountId
and apiKey
differ from CleverTap's accountId
and token.
You can find these details under your dashboard's Signed Call Settings.
Q. Does the Signed Call Android SDK support In-App calls over Bluetooth?
A. Yes. The Signed Call Android SDK has built-in Bluetooth support. It requires a runtime BLUETOOTH_CONNECT permission for Android 12 and onwards.
Q. What channels are used for call routing by Signed Call Android SDK?
A. Signed Call Android SDK uses an active socket connection as soon as the SDK is initialized. The socket connection is a primary routing channel to receive the calls, whereas FCM is a fallback channel in case the receiver is not connected to the socket channel. This socket connection processes the call requests raised to make a call. To know more, refer to the Best practices for initializing Signed Call SDKs.
Updated 2 days ago