Using the SDK with your own UI
Using the SDK with your own UI
Though the Talk SDK includes a built-in UI, you can build and use your own UI if you prefer. The SDK also includes an API that encapsulates all its functionality.
This section describes how to use the SDK API with your own UI. To customize the look and feel of the SDK's built-in UI, see Customizing the look.
You need to create a SDK instance to access the API. See Creating a SDK instance in Getting started.
Topics covered:
- Starting calls with your own permissions and call screens
- Managing calls with your own call screen
- Using your own call screen only
- Using your own permissions screen only
Starting calls with your own permissions and call screens
You can build your own permissions and call screens and then use the SDK's API to add functionality to the UI.
Each Talk call has the following setup flow:
Use the SDK's API to perform each step in the setup flow.
In addition, your permissions screen should check for permission to access the device's microphone and get the user's permission if not yet granted. To learn more, see Permissions overview in the Android docs.
Check for agent availability
Determine if any agents are available for a Talk digital line. Hiding the call button when no agents are available is recommended to improve the user experience.
Use the API's lineStatus
method to determine if any agents are available for a Talk digital line. For details, see Checking for agent availibility in Getting started.
Check for permission to record audio
After determining that agents are available but before starting the call, you must ensure that the user has granted permission to record audio.
Talk SDK requires the following dangerous permission:
android.permission.RECORD_AUDIO
To verify whether the permission is granted, use the API's arePermissionsGranted
method.
Java
boolean permissionsGranted = talk.arePermissionsGranted();
if(permissionsGranted) {
// fine to start a call
} else {
// request permission
}
Kotlin
val permissionsGranted = talk.arePermissionsGranted()
if (permissionsGranted) {
// fine to start the call
} else {
// request permission
}
If the permission is granted, you can start the call. See Start the call. Otherwise, your application has to obtain the permission from the user. To learn more, see Request App Permissions in the Android docs.
Start the call
Once you're sure that an agent is available and your application has the required permissions, you can start a call to an agent.
-
Create
CallData
.Java
CallData callData = CallDataBuilder.create("your digital line name")
.recordingConsentAnswer(null)
.build();
Kotlin
val callData = CallData(digitalLine = "your digital line name", recordingConsentAnswer = null)
The
CallDataBuilder.create
method requires a digital line nickname.RecordingConsentAnswer
is an optional property. -
Create the call.
Java
TalkListenableFuture<TalkCallResult> job = TalkJavaCompat.createCall(talk, callData);
job.addListener(new TalkJavaCompatListener<TalkCallResult>() {
@Override
public void onSuccess(@NotNull TalkCallResult result) {
handleTalkCallResult(result);
}
@Override
public void onError(@NotNull Throwable throwable) {
}
});
Kotlin
yourCoroutineScope.launch {
val callResult = talk.createCall(callData)
handleTalkCallResult(callResult)
}
-
Handle the result.
The
talk.createCall()
method returnsTalkCallResult
, which is a Kotlin sealed class that contains one of the following states:TalkCallResult.Failure.DigitalLineNotFound
- The digital line nickname does not exist in the accountTalkCallResult.Failure.Unknown
- Creating the call failed due to an unknown errorTalkCallResult.Success
- Creating the call was successful and a call to an agent was established. See Managing calls with your own call screen
If the
TalkCallResult
isTalkCallResult.Failure.DigitalLineNotFound
orTalkCallResult.Failure.Unknown
, the call was not established and you should inform the user about the error.
Managing calls with your own call screen
After starting a call successfully (when TalkCallResult
is TalkCallResult.Success
), you can perform the following actions to manage the call:
- Listen to call status changes
- Mute or unmute the call
- Change the audio output of the call
- Disconnect the call
Listening to call status changes
You can listen to changes in the call status by using the statusChanges
property of TalkCallResult.Success
. It's called every time the status changes and can be one of the following values:
CALL_CONNECTED
- the call is connectedCALL_DISCONNECTED
- the call is disconnected, either by an user or agentCALL_DISCONNECTED_CONNECTION_ERROR
- the call is disconnected due to connection issuesCALL_FAILED
- the call failed to connectCALL_RECONNECTING
- the call is not connected and trying to reconnect againCALL_RECONNECTED
- the call reconnected after being disconnected
Example:
Java
if (result instanceof TalkCallResult.Success) {
TalkCallResult.Success success = (TalkCallResult.Success) result;
success.getStatusChanges().observe(this, new Observer<CallStatus>() {
@Override
public void onChanged(CallStatus callStatus) {
// do something with callStatus
}
});
}
Kotlin
if (result is TalkCallResult.Success) {
yourCoroutineScope.launch {
result.statusChanges.collect { callStatus ->
// do something with callStatus
}
}
}
Muting or unmuting the call
You can mute or unmute the call.
You can check the current state of muting with the talkCall.isMuted()
method. You can change the mute state with talkCall.mute(boolean)
.
Java
boolean muted = success.getTalkCall().isMuted();
success.getTalkCall().mute(!muted);
Kotlin
val muted = result.talkCall.isMuted()
result.talkCall.mute(!muted)
Changing the audio output of the call
You can change the audio output of the call from a headset to the device's built-in speakers. By default, the audio is played through a wireless Bluetooth headset when detected or a phone headset when a Bluetooth headset is not found.
To change the audio output, use talkCall.changeAudioOutput(AudioOutput)
.
AudioOutput
is an enum that can be one of the following:
AudioOutput.SPEAKERS
- the audio is routed through the built-in device speakersAudioOutput.HEADSET
- the audio is routed through the device headsetAudioOutput.BLUETOOTH
- the audio is routed through the external Bluetooth headset
Before setting desired audio output on your call you need to subscribe to updates for supported audio devices. Not all AudioOutput
types are supported on all devices (device must support Bluetooth) or in every scenarios (Bluetooth needs to be turned on and the device must be activated).
To minimize the effort required by you, the Talk SDK exposes a stream of supported audio devices. Your application needs to listen to this stream and update your UI options properly based on the values received.
TalkCallResult.Success
contains the property availableAudioDevices
, which is either of type Flow<List<AudioDevice>>
for Kotlin or LiveData<List<AudioDevice>>
for Java.
AudioDevice
describes the available audio device. In addition to AudioOutput
, it may contain additional properties specific for the given type. All descendants of AudioOutput
contain a boolean flag indicating whether it's the currently active audio device.
AudioDevice
can be one of following items:
AudioDevice.Speakers
, which has the following properties:isActive
: Whether the speakers actively used to play audio or notaudioOutput
: Enum representing this state. Used to change the active audio output
AudioDevice.Headset
, which has the following properties:isActive
: Whether the speakers actively used to play audio or notaudioOutput
: Enum representing this state. Used to change the active audio output
AudioDevice.BluetoothHeadset
, which has the following properties:deviceName
: Name of the Bluetooth device or null if the name could not be retrievedisActive
: Whether the speakers actively used to play audio or notaudioOutput
: Enum representing this state. Used to change the active audio output
To retrieve the current state of the audio output, you can use one of following approaches:
- Use the
talkCall.getAudioOutput()
method, which returns the currently used audio output at the moment the method is called. - Use the
talkCallResult.availableAudioDevices
stream, which is updated any time the activeAudioDevice
changes or the Bluetooth device changes to another one.
Zendesk recommends using the second approach because it always provides up-to-date data. Use the first approach only when you need data synchronously.
Example - Listening for available audio devices
Java
success.getAvailableAudioDevices().observe(this, new Observer<List<AudioDevice>>() {
@Override
public void onChanged(List<AudioDevice> audioDevices) {
AudioDevice activeAudioDevice = null;
for (AudioDevice audioDevice : audioDevices) {
if (audioDevice.isActive()) {
activeAudioDevice = audioDevice;
break;
}
}
// display available audio devices
}
});
Kotlin
yourCoroutineScope.launch {
success.availableAudioDevices.collect { availableAudioDevices ->
val activeDevice = devices.find { it.isActive }
// display available audio devices
}
}
Example - Changing audio output
Java
success.getTalkCall().changeAudioOutput(AudioOutput.SPEAKERS);
Kotlin
result.talkCall.changeAudioOutput(AudioOutput.SPEAKERS)
Disconnecting the call
To disconnect the call, use talkCall.disconnect()
.
Java
success.getTalkCall().disconnect();
Kotlin
result.talkCall.disconnect()
Shortly after calling disconnect()
, the statusChanges
property discussed above will specify CallStatus.DISCONNECTED
.
Using your own call screen only
The user must have granted permission to record audio before a call can start. You can use the SDK's built-in permissions screen to handle permissions and use your own call screen to start and manage the call.
To use your own call screen only, pass an Intent
to use it into talk.startCallSetupFlow
instead of a null value. Your Intent
must lead to an Activity
.
After permissions are checked and the consent screen is finished, the SDK will run the Intent
instead of the built-in call screen.
-
Create the
Activity
in your application and register it in AndroidManifest.xml.Java
public class CustomCallScreenJavaActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Kotlin
class CustomCallScreenActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
-
In
onCreate
, extract theRecordingConsentAnswer
from the permissions screen.Java
RecordingConsentAnswer recordingAnswer = CallSetupIntentContract.getRecordingAnswer(getIntent());
Kotlin
val recordingAnswer = CallSetupIntentContract.getRecordingAnswer(intent)
-
With the received
RecordingConsentAnswer
object, create the call using the SDK API. See Start the call. -
Start the SDK's built-in permissions screen with an intent to your
Activity
:Java
talk.startCallSetupFlow(this, "your digital line name", new Intent(this, CustomCallScreenJavaActivity.class));
Kotlin
talk.startCallSetupFlow(
context = this,
digitalLine = "your digital line name",
successIntent = Intent(this, CustomCallScreenActivity::class.java)
)
After the call starts successfully, you can manage the call with your call screen. See Managing calls with your own call screen.
Using your own permissions screen only
You can use your own permissions and consent screens and then use the SDK's built-in call screen.
In this case, your application is responsible for checking and requesting permission to access the microphone as well as to record audio. See Check for permission to record audio. If the call is started without the required permissions, the SDK will throw a runtime exception.
Use the talk.startCallScreen
method to start the SDK call screen.
Java
talk.startCallScreen(this, "your digital line name", null);
Kotlin
talk.startCallScreen(
context = this,
digitalLine = "your digital line name",
recordingConsentAnswer = null
)
The startCallScreen
method has three required arguments:
context
- the AndroidContext
, used for starting a new screendigitalLine
- nickname of the digital line configured in your accountrecordingConsentAnswer
- the consent for recording the call. One of "OPTED_IN", "OPTED_OUT", or null. When null, the default account setting for the recording is used
Note: For this release, the recording consent is not supported by the system, but the SDK API supports it. For an initial integration of Talk SDK, we recommend setting recordingConsentAnswer
to null.