HappyOyster Referência da API do Android SDK
O ponto de entrada para o HappyOyster Android SDK é o objeto singleton HappyOyster . Exceto para initialize , updateToken , attachmentVideo e sendCommand , todos os métodos de negócios são funções de suspensão que lançam SDKError em caso de falha. Abrange os três modos aventura/direção/atuação, a configuração do modelo necessária e AspectRatio.
Se a corrotina do chamador for cancelada, o SDK cancelará a solicitação HTTP em andamento da chamada, se houver, e propagará CancellationException inalterado em vez de convertê-lo para SDKError. O cancelamento não reverte uma solicitação que o servidor já aceitou.
Para obter o fluxo de integração, instalação e práticas recomendadas, consulte Guia de integração do Happy Oyster Android SDK.
Terminologia Básica
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> Prazo </th><th> Significado </th></tr></thead><tbody><tr><td> ficha </td><td> QwenCloud chave de API do gateway: injetado como um token de portador pelo seu aplicativo via <code>atualizarToken(token)</code>. O SDK mantém apenas o mais recente; ele não persiste nem o atualiza. Quando a chave muda, você a injeta novamente. O gateway requer todas as solicitações do SDK, incluindo <code>inícioViagem</code>, para usar este portador. Quando a Bearer Key expira ou é inválida, o SDK lança <code>Erro SDK(101002)</code>; nesse caso você deve obter novamente e injetar a Chave do Portador (<code>atualizarToken</code>), em vez de trocar por um novo ingresso. Recomendação de segurança: o Bearer do lado do cliente deve usar um token de curta duração cunhado pelo seu servidor, em vez de agrupar uma chave de API de longa duração no aplicativo ou enviá-la para um repositório de código. </td></tr><tr><td> bilhete </td><td> Credencial de experiência única: trocado pelo seu servidor através da plataforma aberta e entregue ao cliente, utilizado apenas para um único <code>inícioViagem</code>. Torna-se inválido quando a experiência termina (normal ou anormalmente) e não pode ser reutilizado. Erros de credenciais no nível do ticket são identificados por códigos de servidor de seis dígitos (por exemplo, <code>401010</code> = bilhete inválido/expirado, <code>401011</code> = ticket já usado), que o SDK passa literalmente. </td></tr></tbody></table>
Requisitos ambientais
<table><colgroup><col style={{ width: "33.333333%" }} /><col style={{ width: "66.666667%" }} /></colgroup><thead><tr><th> Artigo </th><th> Requisito </th></tr></thead><tbody><tr><td> minSdk </td><td> 24 (Android 7.0) e superior </td></tr><tr><td> compileSdk </td><td> 36 </td></tr><tr><td> Idioma </td><td> Kotlin (co-rotina <code>suspender</code> APIs) </td></tr><tr><td> ABI </td><td> <code>arm64-v8a</code> / <code>armeabi-v7a</code> (o mecanismo de comunicação em tempo real inclui bibliotecas nativas) </td></tr><tr><td> Rede </td><td> É necessário acesso público à Internet </td></tr></tbody></table>
Conceitos Básicos
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> Conceito </th><th> Descrição </th></tr></thead><tbody><tr><td> Mundo </td><td> Um mundo de IA, contendo personagens e cenas. Criado e gerenciado pelo seu servidor. </td></tr><tr><td> Viajar </td><td> Uma única experiência em tempo real. Ciclo de vida básico: <code>init → pendente → em execução → concluído</code> (o fracasso é <code>falhou</code>). Nos modos de direção e atuação, se a experiência permitir pausas, <code>correndo</code> pode entrar <code>pausado</code> através de <code>pausaViagem</code>, depois retorne para <code>correndo</code> através de <code>currículoViagem</code> (a direção também pode usar <code>retrocederViagem</code>, após o qual o servidor retoma a experiência automaticamente); <code>em execução ⇄ pausado</code> pode repetir várias vezes. </td></tr><tr><td> Modo </td><td> <code>aventura</code> (interação dispositivo/comando), <code>dirigir</code> (narrativa baseada em texto), ou <code>atuando</code> (Atuação: narrativa baseada em texto cuja proporção de reprodução é fixada pelo servidor na criação do mundo). O SDK expõe uniformemente esses três valores. </td></tr><tr><td> Vídeo em tempo real </td><td> Estabelecido e mantido automaticamente pelo SDK depois <code>inícioViagem</code> consegue; você não precisa conectar/desconectar manualmente. Ele é liberado automaticamente em <code>fimViagem</code>. </td></tr></tbody></table>
Visão geral
HappyOyster métodos
<table><colgroup><col style={{ width: "38.580247%" }} /><col style={{ width: "61.419753%" }} /></colgroup><thead><tr><th> Método </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>inicializar(contexto, configuração)</code> </td><td> Inicializa o SDK. A reinicialização ociosa é suportada; a reinicialização enquanto uma viagem está começando, ativa ou terminando é rejeitada com <code>103004</code>. </td></tr><tr><td> <code>atualizarToken(token)</code> </td><td> Injeta/atualiza o QwenCloud Chave de API do gateway (token do portador). </td></tr><tr><td> <code>inícioViagem(bilhete)</code> </td><td> Inicia uma experiência com uma credencial única e estabelece automaticamente a conexão de vídeo em tempo real. </td></tr><tr><td> <code>pausaViagem()</code> </td><td> Pausa a experiência de forma assíncrona (dirigindo e atuando, e somente se a experiência suportar pausa); após a aceitação, a pausa real é determinada por <code>onStatusChanged(Pausado)</code>. </td></tr><tr><td> <code>retomarViagem()</code> </td><td> Retoma uma experiência pausada (direção e atuação); inclui 3× repetição de espera internamente. </td></tr><tr><td> <code>rebobinarViagem(rebobinarToSec)</code> </td><td> Retrocede até o número especificado de segundos (dirigindo apenas, estado <code>pausado</code>). O valor dos segundos deve ser um múltiplo de 4. Agir não não suporte para retrocesso. </td></tr><tr><td> <code>enviarInstruir(conteúdo)</code> </td><td> Envia uma instrução de texto para conduzir a narrativa (direção e atuação, <code>correndo</code> ou <code>pausado</code>). </td></tr><tr><td> <code>enviarComando(comando)</code> </td><td> Envia comandos de controle de direção/visão/ação (modo aventura, <code>correndo</code> apenas; tópico principal). Não disponível para atuação. </td></tr><tr><td> <code>anexarVídeo()</code> </td><td> Retorna um <code>SurfaceView</code> para reprodução; adicione-o ao seu layout para renderizar (thread principal). </td></tr><tr><td> <code>fimViagem()</code> </td><td> Finaliza a experiência, desconectando automaticamente a conexão em tempo real e liberando todos os recursos da sessão. </td></tr><tr><td> <code>VERSÃO</code> </td><td> String de versão do SDK (SemVer), uma constante de tempo de compilação. </td></tr></tbody></table>
Eventos
<table><colgroup><col style={{ width: "38.580247%" }} /><col style={{ width: "61.419753%" }} /></colgroup><thead><tr><th> Evento </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>onStatusChanged(status)</code> </td><td> Experimente a mudança de status (incluindo o ciclo de vida do vídeo em tempo real); os valores são definidos em <code>Valor de status de viagem</code>. </td></tr><tr><td> <code>onError(erro)</code> </td><td> Retorno de chamada quando um fluxo automático interno falha; um erro fatal também encerra a experiência atual. </td></tr></tbody></table>
Principais tipos de dados
<table><colgroup><col style={{ width: "38.580247%" }} /><col style={{ width: "61.419753%" }} /></colgroup><thead><tr><th> Tipo </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>SDKConfig</code> </td><td> Configuração de inicialização do SDK (<code>apiHost</code> e <code>modelo</code> são necessários, mais <code>nível de registro</code>, <code>logcatEnabled</code>, <code>manipulador de log</code>e <code>callbackTimeoutMs</code>). </td></tr><tr><td> <code>Valor de status de viagem</code> </td><td> Situação da experiência: <code>Iniciar</code> / <code>Pendente</code> / <code>Correndo</code> / <code>Pausado</code> / <code>Falha</code> / <code>Concluído</code>. </td></tr><tr><td> <code>ModoValor</code> </td><td> Modo de experiência: <code>aventura</code> / <code>dirigir</code> / <code>atuando</code>. </td></tr><tr><td> <code>CriaçãoModelValue</code> </td><td> Modelo de criação mundial: <code>Simples</code> (padrão, orientado por instrução) / <code>Lista de scripts</code> (roteiro estruturado, <code>enviarInstruir</code> não suportado). </td></tr><tr><td> <code>IniciarTravelData</code> </td><td> Retornado por <code>inícioViagem</code>; contém metadados como <code>modo</code>, <code>versão</code>, <code>criaçãoModelo</code>, <code>proporção de aspecto</code>e <code>maxExperienceTimeSec</code>. </td></tr><tr><td> <code>Comando de Aventura</code> </td><td> Parâmetro para <code>enviarComando</code>; contém os três campos <code>tradução</code> / <code>rotação</code> / <code>interação</code>. </td></tr><tr><td> <code>Erro SDK</code> </td><td> Erro do SDK; contém <code>código: Int</code> e opcional <code>cru: Algum?</code>. </td></tr></tbody></table>
HappyOyster.initialize
Inicializa o SDK; chame-o antes de qualquer outra API (de preferência em Application.onCreate). config é obrigatório e deve carregar o da sua conta QwenCloud apiHost e um model de happyoyster-1.0-directing / happyoyster-1.0-acting / happyoyster-1.0-adventure (correspondendo à entrada Open API). O SDK constrói URLs de solicitação da seguinte forma:
https://{apiHost}/api/v2/apps/{model}/openapi/v1/{endpoint}
model não tem valor padrão: omitindo-o ao construir SDKConfig é um erro em tempo de compilação. Passar um valor em branco faz initialize lançar sincronizadamente SDKError(100002); nenhum tempo de execução é criado ou substituído e nenhuma solicitação de rede é feita. O SDK contém apenas o contexto do aplicativo, não uma atividade. A reinicialização é suportada somente enquanto o tempo de execução anterior está ocioso. Para trocar de modelo, reinicialize com o novo model enquanto ocioso; se uma viagem estiver começando, ativa ou terminando, aguarde endTravel() primeiro.
Assinatura
fun initialize(context: Context, config: SDKConfig)
Parâmetros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "18.518519%" }} /><col style={{ width: "13.888889%" }} /><col style={{ width: "49.074074%" }} /></colgroup><thead><tr><th> Campo </th><th> Tipo </th><th> Obrigatório </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>contexto</code> </td><td> <code>Contexto</code> </td><td> Sim </td><td> Passando <code>aplicaçãoContext</code> é recomendado. </td></tr><tr><td> <code>configuração</code> </td><td> <code>SDKConfig</code> </td><td> Sim </td><td> Configuração do SDK; deve carregar os requisitos exigidos e livres de inadimplência <code>apiHost</code> e <code>modelo</code>. </td></tr></tbody></table>
Devoluções
Nenhum valor de retorno.
Erros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>100002</code> </td><td> <code>modelo</code> está em branco. A inicialização falha de forma síncrona com <code>SDKError.raw</code> definido como <code>SDKConfig.model não deve ficar em branco</code>; nenhum tempo de execução é criado ou substituído e nenhuma solicitação de rede é feita. </td></tr><tr><td> <code>103004</code> </td><td> A reinicialização foi rejeitada porque uma viagem está começando, ativa ou terminando. Aguarde <code>fimViagem()</code> e tente novamente. </td></tr></tbody></table>
HappyOyster.updateToken
Injeta/atualiza o QwenCloud Chave de API do gateway. Thread-safe e chamável depois initialize; o SDK usa o token mais recente para startTravel e solicitações subsequentes de controle de experiência. O ticket é uma credencial de experiência única e não deve ser confundida com o token do portador.
Assinatura
fun updateToken(token: String)
Parâmetros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "18.518519%" }} /><col style={{ width: "13.888889%" }} /><col style={{ width: "49.074074%" }} /></colgroup><thead><tr><th> Campo </th><th> Tipo </th><th> Obrigatório </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>ficha</code> </td><td> <code>Corda</code> </td><td> Sim </td><td> O QwenCloud Chave de API do gateway, usada como token do portador. </td></tr></tbody></table>
Devoluções
Nenhum valor de retorno.
Erros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>100001</code> </td><td> O SDK não foi inicializado. </td></tr></tbody></table>
HappyOyster.startTravel
Inicia uma experiência única ticket. Se for bem-sucedido, o SDK estabelece automaticamente a conexão de vídeo em tempo real e inicia a pesquisa de status interna, com status exibido via onStatusChanged.
ticketé uma credencial única e é considerada consumida assim que a chamada é feita.- Apenas uma viagem simultânea é permitida por aplicativo a qualquer momento; ligar novamente enquanto uma experiência está em andamento lança
SDKError(103004), comSDKError.rawcontendo apenas um resumo editado do ticket atualmente ativo para diagnóstico, nunca o ticket completo. - Opcionalmente passe
maxExperienceTimeSecpara limitar a duração máxima desta experiência (apenas modo de exploração do mundo/aventura); consulte Parâmetros.
StartTravelData.creationModel (CreationModelValue, padrão CreationModelValue.Simple): indica o modelo de criação do mundo, ou seja, como o conteúdo do script é gerenciado. simple (padrão) é um mundo comum orientado por instruções; mundos de exploração mundial também são normalizados para este valor. scriptlist é um mundo ScriptList estruturado – seu conteúdo de script não é acessado por meio deste SDK. No modo ScriptList (creationModel == CreationModelValue.ScriptList), chamando sendInstruct é rejeitado e joga SDKError(103002). Este campo tem como padrão simple.
StartTravelData.aspectRatio (String?): a proporção de aspecto de reprodução que o servidor atribuiu a esta sessão, como um width:height corda. Não nulo apenas para Atuação—"9:16" (retrato, o padrão do lado do servidor na criação) ou "16:9" (paisagem); null para exploração do mundo e modos de direção, e null quando o servidor não informa o valor. O SDK preserva valores desconhecidos literalmente (não os recolhe para null), então os hosts devem tratar qualquer valor não reconhecido como null e voltar à sua própria orientação padrão; o próprio SDK não consome esse campo.
O valor é entregue com o startTravel() valor de retorno: dimensiona o contêiner de reprodução após startTravel() retorna e antes de ligar attachVideo() e adicionar a visualização retornada ao seu layout - o SDK só começa a vincular o fluxo remoto para renderização quando o host anexa a visualização, portanto, decidir a orientação nesse ponto ainda precede o primeiro quadro renderizado (no entanto, não é garantido que isso aconteça antes que o SDK entre na sala em tempo real). A visualização remota está vinculada a um modo de renderização cortar para preencher, portanto, um contêiner cuja orientação discorda desse valor corta a imagem em vez de colocá-la em caixa de correio.
Assinatura
suspend fun startTravel(ticket: String): StartTravelData
suspend fun startTravel(ticket: String, maxExperienceTimeSec: Int?): StartTravelData
Parâmetros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "18.518519%" }} /><col style={{ width: "13.888889%" }} /><col style={{ width: "49.074074%" }} /></colgroup><thead><tr><th> Campo </th><th> Tipo </th><th> Obrigatório </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>bilhete</code> </td><td> <code>Corda</code> </td><td> Sim </td><td> A credencial de experiência única, entregue pelo seu servidor. </td></tr><tr><td> <code>maxExperienceTimeSec</code> </td><td> <code>Internacional?</code> </td><td> Não </td><td> Duração máxima desta experiência em segundos; o mundo encerra a sessão automaticamente assim que for alcançado. Aplica-se apenas ao modo de exploração mundial (aventura); ignorado nos modos de direção (direção em tempo real) e atuação. Os valores permitidos são configurados pelo servidor, atualmente <code>60</code> / <code>90</code> / <code>120</code>; passando <code>nulo</code> (ou usando a sobrecarga sem este parâmetro) aplica o padrão do servidor (atualmente <code>60</code>). Passar um valor não suportado faz com que o rejeição do servidor <code>inícioViagem</code> com <code>400000</code>, jogando <code>Erro SDK(400000)</code> sem nenhuma viagem ativa criada. O SDK não valida o valor localmente — o conjunto permitido é autoritativo no servidor. </td></tr></tbody></table>
Devoluções
Devoluções StartTravelData, contendo metadados de experiência (mode, version, creationModel, aspectRatio, etc.). Inspecione os metadados retornados antes de decidir como interagir (por exemplo, travel.mode, travel.creationModel, travel.version); para Atuação, dimensione também o contêiner de reprodução de travel.aspectRatio.
Erros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>401010</code> </td><td> <code>bilhete</code> inválido ou expirado </td></tr><tr><td> <code>401011</code> </td><td> <code>bilhete</code> já usado </td></tr><tr><td> <code>400000</code> </td><td> Parâmetro inválido (por exemplo <code>maxExperienceTimeSec</code> não está dentro do conjunto permitido pelo servidor); isso <code>inícioViagem</code> não consegue iniciar </td></tr><tr><td> <code>403002</code> </td><td> O mundo não está em um estado pronto </td></tr><tr><td> <code>500001</code> </td><td> Alocação de recursos/falha no serviço interno </td></tr><tr><td> <code>103004</code> </td><td> Uma viagem já está começando, ativa ou terminando, ou <code>inícioViagem</code> é chamado simultaneamente (apenas uma viagem é permitida por vez; <code>SDKError.raw</code> contém apenas um resumo editado do ticket ativo) </td></tr></tbody></table>
HappyOyster.pauseTravel / HappyOyster.resumeTravel
Pausar/retomar a experiência. O SDK gerencia apenas uma viagem por vez; encryptedTravelId é obtido internamente pelo SDK e não precisa ser passado pelo chamador.
Pré-condições:
pauseTravel: chamável apenas em dirigir ou atuar e quando o estado érunning.resumeTravel: chamável apenas em dirigir ou atuar e quando o estado épaused.
Nem todas as experiências suportam pausa/retomada: a experiência deve relatar o identificador de versão que seu modo exige (StartTravelData.version—storyV2 para dirigir, actingV2 para Atuação; comparado ignorando os espaços em branco e letras maiúsculas ao redor), caso contrário, ambos pauseTravel e resumeTravel retornar 103002. A atuação suporta pausa/retomada, mas não suporta rewindTravel.
A pausa é assíncrona (importante): pauseTravel é uma operação "pesada" - uma chamada bem-sucedida (retorno de método) significa apenas a pausa foi aceita; naquele momento a experiência é na verdade ainda não foi pausado. <strong>A pausa só é real quando o onStatusChanged relatórios de retorno de chamada paused.</strong> Portanto, acione a máquina de estado do host e chame o gate a partir desse retorno de chamada: entre "chamar pauseTravel" e "recebendo o paused callback" você pode marcar o estado local como pausing; só depois de receber paused você deve permitir o início resumeTravel ou rewindTravel. Não trate o retorno de pauseTravel como já pausado.
Manipulação da conexão em tempo real: após uma pausa real, o SDK desconecta a conexão em tempo real; ao retomar, o SDK se reúne automaticamente e restaura a imagem usando a credencial entregue durante o mesmo startTravel, sem necessidade de intervenção do hospedeiro.
Barreira de pausa-desmontagem ordenada: depois Paused é emitido, a desmontagem da sala em tempo real do lado do servidor ainda pode demorar um pouco. O SDK estabelece uma janela de liquidação de 3 segundos a partir da confirmação da pausa. Se resumeTravel ou rewindTravel é chamada dentro dessa janela, a chamada suspensa primeiro aguarda sem bloqueio pelo tempo restante e, em seguida, envia a solicitação de API de reabertura da sala. Nenhum atraso é adicionado se 3 segundos já tiverem decorrido naturalmente. Isso evita que uma desmontagem com pausa tardia feche a sala recém-aberta e volte à superfície 105001.
retomar nova tentativa de API: resumeTravel tenta internamente até 3 vezes em caso de falha (recuo 1 s/2 s/3 s) para lidar com uma breve indisponibilidade de serviço após uma pausa; somente se todas as 3 tentativas falharem o erro será propagado para cima.
Recomenda-se que o host espere até 3 s após resumeTravel retorna com sucesso antes de iniciar pauseTravel novamente, para evitar alternar com muita frequência. Esta é uma recomendação de resfriamento de chamada do lado do host e não é aplicada pelo próprio SDK. Consulte Guia de integração do Happy Oyster Android SDK para obter detalhes.
Assinatura
suspend fun pauseTravel(): TravelStateData
suspend fun resumeTravel(): TravelStateData
Parâmetros
Sem parâmetros.
Devoluções
Devoluções TravelStateData (contém encryptedTravelId, status).
Erros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>103001</code> </td><td> Nenhuma experiência ativa </td></tr><tr><td> <code>103002</code> </td><td> Estado não permitido ou esta experiência não suporta pausa/retomada </td></tr><tr><td> <code>103003</code> </td><td> Chamado no modo aventura; apenas direção e apoio de atuação, pausa/retomada </td></tr></tbody></table>
HappyOyster.rewindTravel
Retrocede até o número especificado de segundos. encryptedTravelId é obtido internamente pelo SDK.
Pré-condições: chamável apenas em modo de direção e quando o estado é paused (rebobinar não é permitido no running estado). Nem todas as experiências de direção apoiam o retrocesso, e as sem suporte retornam 103002. Após um retrocesso bem-sucedido, a experiência é retomada automaticamente e o SDK reconecta automaticamente o RTC, sem necessidade de intervenção do host.
Atuar não tem capacidade de retrocesso: chamá-lo em Atuação é rejeitado localmente pelo SDK com 103003, e nenhuma solicitação é emitida. Na atuação, os anfitriões devem esconder o ponto de entrada de retrocesso em vez de apenas desativar o botão.
Assinatura
suspend fun rewindTravel(rewindToSec: Double): RewindTravelData
Parâmetros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "18.518519%" }} /><col style={{ width: "13.888889%" }} /><col style={{ width: "49.074074%" }} /></colgroup><thead><tr><th> Campo </th><th> Tipo </th><th> Obrigatório </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>retrocederToSec</code> </td><td> <code>Duplo</code> </td><td> Sim </td><td> O número alvo de segundos para retroceder, que deve ser um múltiplo de 4 (por exemplo, 4, 8, 12). Um não múltiplo de 4 é reduzido pelo servidor até o múltiplo menor de 4 mais próximo (por exemplo, passar 7 resulta em 4). </td></tr></tbody></table>
Devoluções
Devoluções RewindTravelData (contém encryptedTravelId, status, resumedAtSec), onde resumedAtSec é o número de segundos para o qual o servidor realmente retrocedeu (já reduzido a um múltiplo de 4).
Erros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>103001</code> </td><td> Nenhuma experiência ativa </td></tr><tr><td> <code>103002</code> </td><td> Estado não é <code>pausado</code>ou esta experiência não suporta retrocesso </td></tr><tr><td> <code>103003</code> </td><td> Chamado no modo aventura ou atuação; apenas o modo de direção suporta retrocesso </td></tr></tbody></table>
HappyOyster.sendInstruct
Envia uma instrução de texto para conduzir a narrativa. Válido em dirigir ou atuar e quando o estado de experiência é running ou paused. encryptedTravelId é obtido internamente pelo SDK.
Comportamento no estado pausado: o SDK faz não retomar automaticamente enquanto pausado; a instrução é enviada diretamente. Cabe ao anfitrião decidir se deseja ligar resumeTravel primeiro antes de enviar a instrução.
Assinatura
suspend fun sendInstruct(content: String): SendInstructData
Parâmetros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "18.518519%" }} /><col style={{ width: "13.888889%" }} /><col style={{ width: "49.074074%" }} /></colgroup><thead><tr><th> Campo </th><th> Tipo </th><th> Obrigatório </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>conteúdo</code> </td><td> <code>Corda</code> </td><td> Sim </td><td> O conteúdo da instrução de texto a ser enviado. </td></tr></tbody></table>
Devoluções
Devoluções SendInstructData (contém encryptedTravelId, content, accepted).
Erros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>103001</code> </td><td> Nenhuma experiência ativa (nunca liguei <code>inícioViagem</code>, ou terminou) </td></tr><tr><td> <code>103003</code> </td><td> O modo atual não é dirigir nem atuar (chamado no modo aventura) </td></tr><tr><td> <code>103002</code> </td><td> O estado de experiência não é nem <code>correndo</code> nem <code>pausado</code> (por exemplo, ainda no <code>iniciar</code>/<code>pendente</code> fase); ou o mundo atual está no modo ScriptList (<code>StartTravelData.creationModel == CreationModelValue.ScriptList</code>) — o envio de instruções não é permitido no modo ScriptList, onde os scripts são gerenciados pelo QwenCloud API da plataforma </td></tr><tr><td> <code>403004</code> </td><td> Bloco de moderação de conteúdo </td></tr><tr><td> <code>404000</code> </td><td> Viajar não existe </td></tr></tbody></table>
HappyOyster.sendCommand
Envia comandos de controle de direção/visão/ação. Válido apenas em modo aventura e quando running.
- Chame no tópico principal; uma chamada fora da principal é lançada de forma síncrona
IllegalStateException. - Nenhum relatório de experiência ativa
103001. - Ligando para fora modo aventura (direção / atuação) relatórios
103003. - Relatórios de estado não permitidos
103002. - O uplink é estabelecido através de um fluxo de áudio silencioso (o SDK não grava nem carrega áudio real);
RECORD_AUDIOnão é um pré-requisito rígido para o DataChannel, mas declará-lo e concedê-lo é recomendado para compatibilidade entre dispositivos (consulte Guia de integração do Happy Oyster Android SDK § Instalação · Permissões).105004significa que o canal em tempo real não está pronto/um envio falhou (por exemplo, uma interrupção de conexão do DataChannel ou uma anomalia no canal em tempo real); ele não é acionado diretamente por uma permissão ausente.
Aceleração integrada de 42 ms (24 fps, últimas vitórias): sendCommand limita internamente as gravações do DataChannel em intervalos de 42 ms (cerca de 24 fps). Execuções de validação de estado de forma síncrona e imediata, lançando imediatamente uma chamada ilegal; a gravação real do DataChannel é acelerada de forma assíncrona. Se pelo menos 42 ms se passaram desde o envio anterior, o comando é despachado imediatamente (incluindo a primeira chamada). Caso contrário, o comando pendente será substituído pelo valor mais recente e despachado uma vez no final da janela atual de 42 ms. Várias chamadas em uma janela produzem, portanto, uma gravação on-wire contendo o último valor. O anfitrião pode ligar sendCommand na taxa de quadros do jogo sem implementar seu próprio limitador de taxa.
Enviar falhas durante a limitação: a liberação acelerada é assíncrona e uma falha de envio não pode ser lançada para o chamador – o erro é apresentado por meio do onError retorno de chamada (não fatal, 105004). Os comandos pendentes são descartados quando a sessão termina (eles não serão enviados após o término da sessão).
<strong>AdventureCommand campos e valores</strong>:
<table><colgroup><col style={{ width: "20%" }} /><col style={{ width: "40%" }} /><col style={{ width: "40%" }} /></colgroup><thead><tr><th> Campo </th><th> Semântica </th><th> Valores </th></tr></thead><tbody><tr><td> <code>tradução</code> </td><td> Movimento: frente/esquerda/trás/direita/diagonal/ocioso </td><td> <code>W</code> / <code>A</code> / <code>S</code> / <code>D</code> / <code>W_A</code> / <code>W_D</code> / <code>S_A</code> / <code>S_D</code> / <code>Nenhum</code> </td></tr><tr><td> <code>rotação</code> </td><td> Visualização: cima/baixo/esquerda/direita/diagonal/nenhum </td><td> <code>Mouse_Up</code> / <code>Mouse_Para baixo</code> / <code>Mouse_Esquerda</code> / <code>Rato_Direita</code> / <code>Mouse_Cima_Esquerda</code> / <code>Mouse_Cima_Direita</code> / <code>Mouse_Baixo_Esquerda</code> / <code>Mouse_Baixo_Direita</code> / <code>Nenhum</code> </td></tr><tr><td> <code>interação</code> </td><td> Interação: salto/ataque/agachamento/corrida/nenhuma </td><td> <code>Salte</code> / <code>Ataque</code> / <code>Agachamento</code> / <code>Corrida</code> / <code>Nenhum</code> </td></tr></tbody></table>
Os três campos são grupos de comando independentes e mutuamente exclusivos. O movimento/visualização diagonal usa um solteiro valor combinado (por exemplo, frente+esquerda é W_A, não simultâneo W e A no mesmo campo). Cada chamada deve conter o estado atual completo.
Melhores práticas: ações únicas versus ações retidas
Use o intervalo de 42 ms como modelo mental:
Ação de um tiro (por exemplo, toque em pular/atacar ou dar um passo): ligue uma vez. O SDK envia no intervalo mais próximo; sem chamadas repetidas ou acompanhamento None comando é necessário.
// Jump once
HappyOyster.sendCommand(AdventureCommand("None", "None", "Jump"))
Ação realizada (por exemplo, continue se movendo ou girando): chamar cada quadro enquanto estiver em espera. O SDK emite aproximadamente um comando a cada 42 ms. No lançamento, envie explicitamente um comando contendo None para redefinir o estado. O SDK nunca gera um comando de redefinição automaticamente.
// While held: call from the host's frame loop
HappyOyster.sendCommand(AdventureCommand("W", "None", "None"))
// On release: explicitly reset once
HappyOyster.sendCommand(AdventureCommand("None", "None", "None"))
Assinatura
fun sendCommand(command: AdventureCommand)
Parâmetros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "18.518519%" }} /><col style={{ width: "13.888889%" }} /><col style={{ width: "49.074074%" }} /></colgroup><thead><tr><th> Campo </th><th> Tipo </th><th> Obrigatório </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>comando</code> </td><td> <code>Comando de Aventura</code> </td><td> Sim </td><td> Um objeto de comando contendo os três campos <code>tradução</code>, <code>rotação</code>, <code>interação</code>. </td></tr></tbody></table>
Devoluções
Nenhum valor de retorno (síncrono). A validação de estado é executada de forma síncrona e imediata; a gravação do DataChannel é acelerada de forma assíncrona.
Erros
<table><colgroup><col style={{ width: "30.864198%" }} /><col style={{ width: "69.135802%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>103001</code> </td><td> Nenhuma experiência ativa </td></tr><tr><td> <code>103002</code> </td><td> Estado não permitido </td></tr><tr><td> <code>103003</code> </td><td> Chamado fora do modo aventura (direção/atuação) </td></tr><tr><td> <code>105004</code> (através <code>onError</code>) </td><td> Falha no envio de liberação acelerada (retorno de chamada assíncrono e não fatal) </td></tr></tbody></table>
HappyOyster.attachVideo
Retorna um SurfaceView para reprodução, que você adiciona ao seu layout; o SDK conclui internamente a vinculação de renderização com o fluxo remoto.
- Chame no tópico principal; uma chamada fora da principal é lançada de forma síncrona
IllegalStateException. - O SDK mantém apenas uma referência fraca à View retornada e libera a vinculação de renderização quando a experiência termina; você mesmo deve remover a Visualização do layout.
- Para experiências de atuação, dimensione o contêiner de reprodução de
StartTravelData.aspectRatioantes de adicionar a visualização retornada ao seu layout: a renderização está vinculada a um clipe para preencher modo, portanto, uma orientação incompatível corta a imagem (consultestartTravel).
Assinatura
fun attachVideo(): SurfaceView
Parâmetros
Sem parâmetros.
Devoluções
Retorna um SurfaceView; adicione-o ao seu layout para reproduzir o vídeo em tempo real.
Erros
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "81.481481%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>100001</code> </td><td> SDK não inicializado </td></tr></tbody></table>
HappyOyster.endTravel
Termina a experiência. encryptedTravelId é obtido internamente pelo SDK. Após uma chamada bem-sucedida (ou uma saída anormal), o SDK desconecta automaticamente a conexão em tempo real, interrompe a pesquisa interna e libera todos os recursos da sessão, e a corrente ticket é invalidado ao mesmo tempo.
Assinatura
suspend fun endTravel(): EndTravelData
Parâmetros
Sem parâmetros.
Devoluções
Devoluções EndTravelData (contém encryptedTravelId, status, endedAt, durationSec).
Erros
<table><colgroup><col style={{ width: "50%" }} /><col style={{ width: "50%" }} /></colgroup><thead><tr><th> código </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>100001</code> </td><td> SDK não inicializado </td></tr><tr><td> <code>103001</code> </td><td> Nenhuma experiência ativa </td></tr></tbody></table>
HappyOyster.VERSION
Retorna a string da versão do SDK (SemVer), como "x.y.z". Este valor é uma constante de tempo de compilação injetada pelo VERSION_NAME Propriedade Gradle; pode ser lido com segurança sem ligar initialize primeiro.
Assinatura
val VERSION: String
Devoluções
A string da versão do SDK, como "x.y.z".
Log.d("MyApp", "SDK version: ${HappyOyster.VERSION}")
Audição de eventos
interface HappyOysterListener {
fun onStatusChanged(status: TravelStatusValue) {}
fun onError(error: SDKError) {}
}
fun addListener(listener: HappyOysterListener)
fun removeListener(listener: HappyOysterListener)
Os eventos do SDK são um canal push proativo para você, usado para relatar situações não acionadas por suas próprias chamadas explícitas (por exemplo, problemas na conexão em tempo real ou pesquisa de status que o SDK mantém automaticamente).
<table><colgroup><col style={{ width: "50%" }} /><col style={{ width: "50%" }} /></colgroup><thead><tr><th> Evento </th><th> Descrição </th></tr></thead><tbody><tr><td> <code>onStatusChanged</code> </td><td> Experimente a mudança de status (incluindo o ciclo de vida do vídeo em tempo real); os valores são definidos em <code>Valor de status de viagem</code>. </td></tr><tr><td> <code>onError</code> </td><td> Retorno de chamada quando um fluxo automático interno falha; um erro fatal também encerra a experiência atual (consulte a seção de código de erro). </td></tr></tbody></table>
addListener / removeListener deve ser chamado depois initialize; chamando-os antes da inicialização ser lançada SDKError(100001). Recomenda-se cadastrar os ouvintes imediatamente após HappyOyster.initialize(...) retorna com sucesso.
Modelos de dados
// Configuration
data class SDKConfig(
// Required: your account's QwenCloud API Host (e.g., maas.qwencloudapi.com), copied from the API Key page in the QwenCloud console;
// must belong to the same account as the injected API Key, otherwise the gateway returns AccessDenied.
val apiHost: String,
// Required with no default: the complete HappyOyster model name and version (e.g., happyoyster-1.0);
// refer to the official QwenCloud HappyOyster model documentation for available values.
val model: String,
// Minimum level for the built-in Logcat sink (does not affect logHandler); defaults to INFO, which
// includes the lifecycle anchors (initialize, Travel start/status/end, RTC connect/first-frame) needed
// to reconstruct a session timeline. Drop to WARN for errors-only, or raise to DEBUG/VERBOSE to diagnose.
val logLevel: LogLevel = LogLevel.INFO,
// Timeout for RTC join (timeout triggers 105002), first-frame wait (timeout triggers 105003), and SDK gateway HTTP signaling calls (timeout triggers 105005);
// the two RTC phases are serial, so the worst-case wait is 2×callbackTimeoutMs (60s).
val callbackTimeoutMs: Long = SDKConfig.DEFAULT_CALLBACK_TIMEOUT_MS, // 30_000ms
// Whether the SDK writes its own logs to Android Logcat (tag HappyOysterSDK); defaults to false (silent).
val logcatEnabled: Boolean = false,
// Host log callback; receives the full stream of SDK LogRecords, unaffected by logLevel; defaults to null.
val logHandler: HappyOysterLogHandler? = null,
) {
companion object {
/** Default callback timeout (milliseconds). Public constant, usable for comparison or display. */
const val DEFAULT_CALLBACK_TIMEOUT_MS: Long = 30_000
}
}
enum class LogLevel { VERBOSE, DEBUG, INFO, WARN, ERROR, NONE }
// Host log sink; injected via SDKConfig.logHandler; full firehose, unaffected by logLevel.
fun interface HappyOysterLogHandler {
fun onLog(record: LogRecord)
}
// SDK structured log record; delivered to HappyOysterLogHandler; contains no sensitive values (Bearer /
// ticket / RTC token, RTC identity fields, and media URLs are all redacted). travelId (encryptedTravelId)
// is kept in full so it can be correlated with server-side session logs.
data class LogRecord(
val level: LogLevel,
val tag: String, // fixed as "HappyOysterSDK"
val message: String, // readable log line (includes event name and details)
val throwable: Throwable?,
val timestampMs: Long, // epoch milliseconds at emission time
)
// Status and mode (unknown values are preserved to allow service extension)
@JvmInline value class TravelStatusValue(val rawValue: String) {
companion object {
val Init = TravelStatusValue("init")
val Pending = TravelStatusValue("pending")
val Running = TravelStatusValue("running")
val Paused = TravelStatusValue("paused")
val Failed = TravelStatusValue("failed")
val Completed = TravelStatusValue("completed")
}
}
@JvmInline value class ModeValue(val rawValue: String) {
companion object {
val Adventure = ModeValue("adventure")
val Directing = ModeValue("directing")
val Acting = ModeValue("acting")
}
}
@JvmInline value class CreationModelValue(val rawValue: String) {
companion object {
val Simple = CreationModelValue("simple") // default; prompt/instruct-driven, world-exploration worlds normalize to this
val ScriptList = CreationModelValue("scriptlist") // structured ScriptList world; sendInstruct not supported (throws 103002)
}
}
// startTravel return
data class StartTravelData(
val encryptedTravelId: String, // identifier for subsequent control interfaces
val encryptedWorldId: String,
val mode: ModeValue, // adventure / directing / acting
val creationModel: CreationModelValue = CreationModelValue.Simple, // world creation model; Simple (default) is instruct-driven, ScriptList does not support sendInstruct
val playUrl: String?,
val firstFrame: String?, // first-frame image address, may be produced asynchronously
val bgmUrl: String?,
val version: String, // world version identifier; Acting is actingV2
val aspectRatio: String? = null, // Acting only: 9:16 / 16:9; other modes null. Use to set player orientation
val maxExperienceTimeSec: Int? = null, // server-reported max experience time (seconds); non-null only for adventure; null for directing / acting
)
// Control interface parameters and returns
data class AdventureCommand(
val translation: String, // movement: forward/left/back/right/diagonal (W_A, …)/idle
val rotation: String, // view: up/down/left/right/diagonal (Mouse_Up_Left, …)/none
val interaction: String, // interaction: jump/attack/squat/sprint/none
)
data class TravelStateData(val encryptedTravelId: String, val status: TravelStatusValue)
data class RewindTravelData(val encryptedTravelId: String, val status: TravelStatusValue, val resumedAtSec: Double)
data class EndTravelData(val encryptedTravelId: String, val status: TravelStatusValue, val endedAt: String, val durationSec: Int)
data class SendInstructData(val encryptedTravelId: String, val content: String, val accepted: Boolean)
// Error (identified by code; the original information is in raw)
// Note: SDKError is not a data class (no copy()/destructuring), it is a plain class.
class SDKError(val code: Int, val raw: Any? = null) : Exception("Happy Oyster SDK error: $code")
Códigos de erro
Os erros são identificados por um número code. O SDK passa por códigos de erro de negócios que o chamador pode manipular (geralmente 4xxxxx / 5xxxxx); códigos de erro do SDK local são 1xxxxx.
Códigos de erro comercial (comuns)
<table><colgroup><col style={{ width: "18.518519%" }} /><col style={{ width: "40.740741%" }} /><col style={{ width: "40.740741%" }} /></colgroup><thead><tr><th> código </th><th> Significado </th><th> Manuseio sugerido </th></tr></thead><tbody><tr><td> <code>400000</code> </td><td> Parâmetro inválido (enum inválido, etc.) </td><td> Verifique os parâmetros da solicitação ou a versão do SDK </td></tr><tr><td> <code>401010</code> </td><td> <code>bilhete</code> inválido ou expirado </td><td> Faça com que seu servidor emita novamente uma credencial </td></tr><tr><td> <code>401011</code> </td><td> <code>bilhete</code> já usado </td><td> A credencial é única; reemitir </td></tr><tr><td> <code>403001</code> </td><td> O mundo não existe, foi excluído ou não pertence ao desenvolvedor atual (incluindo um mundo já excluído no <code>inícioViagem</code> credencial) </td><td> Selecione novamente um mundo válido </td></tr><tr><td> <code>403002</code> </td><td> O mundo não está em um estado pronto </td><td> Espere até que o mundo esteja pronto antes de começar </td></tr><tr><td> <code>403004</code> </td><td> Violação de conteúdo de entrada (moderação de conteúdo); aplica-se a <code>enviarInstruir</code> instruções de texto </td><td> Modifique o conteúdo de entrada e tente novamente </td></tr><tr><td> <code>403007</code> </td><td> Especificação de serviço não ativada para esta conta </td><td> Não tente novamente quando a capacidade estiver cheia; mudar para uma especificação habilitada ou solicitar ativação </td></tr><tr><td> <code>403008</code> </td><td> Configuração de capacidade temporariamente indisponível </td><td> Tente novamente mais tarde </td></tr><tr><td> <code>404000</code> </td><td> O recurso de viagem não existe ou o ID não pertence à conta corrente </td><td> Reinicie a viagem </td></tr><tr><td> <code>409000</code> </td><td> Solicitar conflitos com o estado atual do recurso </td><td> Verifique o estado da viagem </td></tr><tr><td> <code>429001</code> </td><td> Limite de simultaneidade de SKU atingido </td><td> Tente novamente após o término de uma sessão existente (não confunda com <code>500001</code>) </td></tr><tr><td> <code>429002</code> </td><td> Nenhuma capacidade disponível atualmente </td><td> Tente novamente mais tarde </td></tr><tr><td> <code>500001</code> </td><td> Alocação de recursos de inferência/falha de serviço interno </td><td> Tente novamente mais tarde </td></tr><tr><td> <code>500000</code> </td><td> Erro interno do sistema </td><td> Tentar novamente mais tarde/relatar </td></tr></tbody></table>
Códigos de erro locais do lado do cliente
<table><colgroup><col style={{ width: "10%" }} /><col style={{ width: "40%" }} /><col style={{ width: "15%" }} /><col style={{ width: "35%" }} /></colgroup><thead><tr><th> código </th><th> Significado </th><th> Fatal? </th><th> Manuseio sugerido </th></tr></thead><tbody><tr><td> <code>100001</code> </td><td> Chamado antes da inicialização do SDK </td><td> Chamada rejeitada </td><td> <code>inicializar</code> primeiro </td></tr><tr><td> <code>100002</code> </td><td> <code>modelo</code> estava em branco durante a inicialização do SDK; lançado sincronizadamente com <code>SDKError.raw</code> definido como <code>SDKConfig.model não deve ficar em branco</code>; nenhum tempo de execução é criado ou substituído e nenhuma solicitação de rede é feita </td><td> Falha na inicialização </td><td> Passe um nome e versão completos do modelo e, em seguida, chame <code>inicializar</code> novamente; consulte o oficial QwenCloud HappyOyster documentação do modelo para valores disponíveis </td></tr><tr><td> <code>101001</code> </td><td> QwenCloud Chave de API do gateway não injetada </td><td> Não </td><td> Tente novamente depois <code>atualizarToken</code> </td></tr><tr><td> <code>101002</code> </td><td> QwenCloud A chave de API do portador do gateway expirou ou foi rejeitada. Nota: esta é a chave do portador do gateway, não o ticket único; erros de credenciais em nível de ticket são identificados por códigos de servidor de seis dígitos (por exemplo, <code>401010</code>/<code>401011</code>) </td><td> Não </td><td> Obtenha novamente a Chave do Portador e <code>atualizarToken</code>; não há necessidade de trocar por um novo ingresso </td></tr><tr><td> <code>103001</code> </td><td> Nenhuma experiência ativa atualmente </td><td> Chamada rejeitada </td><td> <code>inícioViagem</code> primeiro </td></tr><tr><td> <code>103002</code> </td><td> O estado atual não permite esta operação (incluindo: incompatibilidade de estado; a experiência não suporta pausa/retomada/retrocesso para <code>pausaViagem</code>/<code>currículoViagem</code>/<code>retrocederViagem</code> (é <code>versão</code> não é o identificador v2 que seu modo exige); indique não <code>pausado</code> para <code>retrocederViagem</code>; <code>criaçãoModel == ScriptList</code> para <code>enviarInstruir</code>) </td><td> Chamada rejeitada </td><td> Verifique o estado e modo da experiência; <code>enviarInstruir</code> não está disponível no modo ScriptList (<code>CreationModel == CreationModelValue.ScriptList</code>), onde o conteúdo do script não é gerenciado por meio deste SDK </td></tr><tr><td> <code>103003</code> </td><td> Incompatibilidade de modo: <code>enviarComando</code> chamado para dirigir ou atuar, ou <code>pausaViagem</code> / <code>currículoViagem</code> / <code>retrocederViagem</code> / <code>enviarInstruir</code> chamado em aventura, ou <code>retrocederViagem</code> chamado em atuação </td><td> Chamada rejeitada </td><td> Verifique se o modo atual corresponde aos requisitos da interface </td></tr><tr><td> <code>103004</code> </td><td> Um simultâneo <code>inícioViagem</code> chamada ou reinicialização enquanto uma viagem está começando, ativa ou terminando (somente uma viagem é permitida por vez; <code>SDKError.raw</code> para início simultâneo contém apenas um resumo editado do ticket) </td><td> Chamada rejeitada </td><td> Aguarde <code>fimViagem()</code> antes de tentar novamente </td></tr><tr><td> <code>105001</code> </td><td> Falha na conexão em tempo real </td><td> Sim </td><td> Terminar e reiniciar </td></tr><tr><td> <code>105002</code> </td><td> A adesão em tempo real expirou </td><td> Sim </td><td> Terminar e reiniciar </td></tr><tr><td> <code>105003</code> </td><td> Tempo limite esgotado aguardando o primeiro quadro do vídeo </td><td> Sim </td><td> Terminar e reiniciar </td></tr><tr><td> <code>105004</code> </td><td> Canal em tempo real não pronto/falha no envio </td><td> Não </td><td> Confirme se o canal em tempo real está pronto e tente novamente <code>enviarComando</code> depois <code>correndo</code>; se um dispositivo específico se comportar mal, tente declarar e conceder <code>GRAVAR_ÁUDIO</code> (consulte Guia de integração do Happy Oyster Android SDK § Instalação · Permissões) </td></tr><tr><td> <code>105005</code> </td><td> Uma chamada de sinalização HTTP do gateway SDK não retornou dentro <code>callbackTimeoutMs</code> (padrão 30); Junção RTC e uso de tempos limite do primeiro quadro <code>105002</code> e <code>105003</code>, respectivamente </td><td> Não </td><td> É recomendável tentar novamente ou aumentar <code>callbackTimeoutMs</code> </td></tr><tr><td> <code>105006</code> </td><td> Encerramento automático sem fluxo: o primeiro quadro nunca chegou ou o fluxo foi interrompido durante a execução e não foi recuperado antes do tempo limite. O SDK encerra proativamente a experiência atual </td><td> Sim </td><td> Terminar e reiniciar </td></tr><tr><td> <code>106001</code> </td><td> Erro de rede local </td><td> Não </td><td> Nova tentativa </td></tr><tr><td> <code>106002</code> </td><td> Falha na análise da resposta </td><td> Não </td><td> Lançado para o chamador quando acionado por uma chamada explícita; na pesquisa de status interna, apenas <code>onError</code> é emitido e a experiência não é encerrada </td></tr><tr><td> <code>106003</code> </td><td> O serviço upstream retornou uma resposta de erro irreconhecível; o SDK manteve as informações originais em <code>SDKError.raw</code> (incluindo rejeições de borda de gateway, como <code>Acesso negado</code>) </td><td> Não </td><td> Nova tentativa; se persistir, investigue a disponibilidade do serviço junto com <code>cru</code>. Se <code>cru</code> contém <code>Acesso negado</code> (na maioria das vezes na primeira solicitação após a inicialização), este é um problema de configuração do gateway; verifique em ordem: ① se o <code>modelo</code> o nome e a versão estão corretos, ainda disponíveis, publicados e autorizados; ② <code>apiHost</code> ortografia; ③ se <code>apiHost</code>, <code>modelo</code>, e a chave injetada via <code>atualizarToken</code> corresponder à conta necessária; ④ se sua conta foi adicionada à lista de permissões de aplicativos </td></tr><tr><td> <code>108001</code> </td><td> SDK desativado remotamente (totalmente desligado ou versão muito baixa); a razão está em <code>SDKError.raw</code> (Sequência) </td><td> Sim (quando o SDK detecta um resultado de desativação, ele encerra automaticamente a experiência em andamento; você pode reiniciar após a recuperação) </td><td> Avise o usuário com base no motivo em <code>cru</code>; orientar uma atualização quando a versão for muito baixa </td></tr></tbody></table>
"Fatal?" refere-se especificamente a se ele aciona o SDK para encerrar automaticamente a experiência atual. Erros de validação síncrona, como 100001/100002/103xxx apenas rejeitar/jogar para essa chamada (100002 falha diretamente na inicialização) e não encerra uma experiência.
Fatal vs não fatal:
- Erros fatais: o SDK encerra automaticamente a experiência atual (desconecta a conexão em tempo real, libera recursos, chama
endTravel) e a superfície atravésonError; o host deve limpar o estado atual da experiência e permitir a reinicialização. Existem quatro categorias: <strong>① a pesquisa de status interna lê um status de experiência defailed</strong> (e.g.,500001falha de inferência); ② conexão em tempo real fatal (105001/105002/105003); ③ encerramento automático sem transmissão (105006: o primeiro quadro nunca chegou ou o fluxo foi interrompido durante a execução e não se recuperou antes do tempo limite e o SDK o encerra proativamente); ④ SDK desativado remotamente (108001). - Erros não fatais: não encerram a experiência e só aparecem via
onError; você podeupdateTokennovamente ou aguarde a recuperação do serviço/canal em tempo real antes de continuar. Uma única solicitação com falha de pesquisa de status interno (rede106001, analisando106002, anomalia a montante106003, erro de negócios5xxxxx) se enquadra nesta categoria – a votação continua no próximo ciclo, e somente quando lê um status defailedisso encerra a experiência; falha de autenticação101001e um assíncronosendCommandfalha no envio de liberação acelerada105004também não são fatais. Observação: o SDK nunca envia nenhuma carga útil de manutenção de atividade própria pelo canal em tempo real, portanto105004não pode aparecer enquanto a sessão estiver ociosa – só pode ser acionada por você mesmosendCommandligue.