Recuperar convites de chamada pendentes
Quando um usuário recebe um convite para uma chamada recebida e, em seguida, atualiza a página (ou reinicia o aplicativo) antes de atender, o Client SDK pode reenviar o convite automaticamente — sem a necessidade de nenhuma chamada à API adicional.
Isso funciona porque o Serviço de Conversação armazena eventos pendentes por aproximadamente 30 segundos. Ao passar o ID da sessão anterior para createSession, o servidor reproduz esses eventos na nova sessão e o callInvite evento (ou onCallInvite (delegado) é acionado automaticamente.
Como funciona
- Manter o ID da sessão retornado por
createSession(por exemplo, emsessionStoragena internet, ouUserDefaults/SharedPreferences(no celular). - Na próxima carga, recuperar o ID da sessão salva e repassá-lo para
createSession. - Registre o ouvinte de convite antes de chamar
createSessionpara que já esteja em vigor quando os eventos pendentes forem acionados.
Aviso: O Serviço de Conversação mantém os eventos pendentes por aproximadamente 30 segundos. Se já tiver passado mais tempo desde que o convite original foi enviado, ele não será reenviado.
Casos extremos
- O prazo expirou: Se o prazo de retenção de 30 segundos já tiver expirado,
createSessionainda assim é bem-sucedida — você obtém uma sessão válida, mas o convite pendente não é reenviado. A essa altura, a chamada já terá expirado ou sido cancelada. - ID de sessão inválido: Se o ID da sessão armazenado for inválido ou pertencer a um usuário diferente, o SDK o ignora e cria uma nova sessão. Nenhum evento pendente é reproduzido.
- Encerramento do aplicativo vs. atualização da página: Na internet,
sessionStorageé apagado quando a aba é fechada; portanto, esse padrão funciona para atualizações dentro da própria aba. Para reinicializações do aplicativo móvel, armazene o ID da sessão em um armazenamento durável (UserDefaults/SharedPreferences).
Exemplo
Copiar
client.on('callInvite', (callId, from) => {
console.log(`Received call invite ${callId} from ${from}`);
});
const previousSessionId = store.getSessionId();
try {
const sessionId = previousSessionId
? await client.createSession(jwt, previousSessionId)
: await client.createSession(jwt);
store.saveSessionId(sessionId);
console.log(`Session ready: ${sessionId}`);
} catch (error) {
console.error('Failed to create/reconnect session', error);
}
Copiar
client.setCallInviteListener { callId, from, channelType ->
println("Received call invite $callId from $from on $channelType")
}
val previousSessionId = store.getSessionId()
if (previousSessionId != null) {
client.createSession(jwt, previousSessionId) { error, sessionId ->
if (error != null) {
println("Failed to reconnect session: $error")
return@createSession
}
sessionId?.let(store::saveSessionId)
println("Reconnected session: $sessionId")
}
} else {
client.createSession(jwt) { error, sessionId ->
if (error != null) {
println("Failed to create session: $error")
return@createSession
}
sessionId?.let(store::saveSessionId)
println("Session created: $sessionId")
}
}
Copiar
client.setCallInviteListener((callId, from, channelType) -> {
System.out.println(
"Received call invite " + callId + " from " + from + " on " + channelType
);
return null;
});
String previousSessionId = store.getSessionId();
if (previousSessionId != null) {
client.createSession(jwt, previousSessionId, (error, sessionId) -> {
if (error != null) {
System.out.println("Failed to reconnect session: " + error);
return null;
}
if (sessionId != null) {
store.saveSessionId(sessionId);
}
System.out.println("Reconnected session: " + sessionId);
return null;
});
} else {
client.createSession(jwt, null, (error, sessionId) -> {
if (error != null) {
System.out.println("Failed to create session: " + error);
return null;
}
if (sessionId != null) {
store.saveSessionId(sessionId);
}
System.out.println("Session created: " + sessionId);
return null;
});
}
Copiar
class InviteDelegate: NSObject, VGVoiceClientDelegate {
func voiceClient(_ client: VGVoiceClient, didReceiveInviteForCall callId: VGCallId, from caller: String, with type: VGVoiceChannelType) {
print("Received call invite \(callId) from \(caller)")
}
func voiceClient(_ client: VGVoiceClient, didReceiveHangupForCall callId: VGCallId, withQuality callQuality: VGRTCQuality, reason: VGHangupReason) {}
func voiceClient(_ client: VGVoiceClient, didReceiveInviteCancelForCall callId: VGCallId, with reason: VGVoiceInviteCancelReason) {}
func client(_ client: VGBaseClient, didReceiveSessionErrorWith reason: VGSessionErrorReason) {}
}
let delegate = InviteDelegate()
client.delegate = delegate
if let previousSessionId = store.getSessionId() {
client.createSession(jwt, sessionId: previousSessionId) { error, sessionId in
guard error == nil, let sessionId = sessionId else {
print("Failed to reconnect session: \(error?.localizedDescription ?? "unknown")")
return
}
store.saveSessionId(sessionId)
print("Reconnected session: \(sessionId)")
}
} else {
client.createSession(jwt) { error, sessionId in
guard error == nil, let sessionId = sessionId else {
print("Failed to create session: \(error?.localizedDescription ?? "unknown")")
return
}
store.saveSessionId(sessionId)
print("Session created: \(sessionId)")
}
}
Copiar
self.store = store;
client.delegate = self;
NSString *previousSessionId = [store getSessionId];
if (previousSessionId != nil) {
[client createSession:jwt sessionId:previousSessionId callback:^(NSError * _Nullable error, NSString * _Nullable sessionId) {
if (error != nil || sessionId == nil) {
NSLog(@"Failed to reconnect session: %@", error);
return;
}
[store saveSessionId:sessionId];
NSLog(@"Reconnected session: %@", sessionId);
}];
} else {
[client createSession:jwt callback:^(NSError * _Nullable error, NSString * _Nullable sessionId) {
if (error != nil || sessionId == nil) {
NSLog(@"Failed to create session: %@", error);
return;
}
[store saveSessionId:sessionId];
NSLog(@"Session created: %@", sessionId);
}];
}