Integre o ARTC SDK ao seu projeto Android para criar um aplicativo de áudio e vídeo em tempo real, voltado para transmissões ao vivo interativas e chamadas de vídeo.
Conceitos principais
Antes de começar, revise os seguintes conceitos fundamentais:
ARTC SDK: SDK da Alibaba Cloud para interações de áudio e vídeo em tempo real.
GRTN: Global Realtime Transport Network da Alibaba Cloud, que oferece services de comunicação de áudio e vídeo com latência ultrabaixa, alta qualidade, segurança e confiabilidade.
canal: Sala virtual destinada a interações de áudio e vídeo em tempo real.
host: Função que permite ao usuário publicar streams de áudio e vídeo em um canal e assinar streams publicados por outros hosts.
viewer: Função que habilita o usuário a assinar streams de áudio e vídeo em um canal, mas não a publicar streams.
-
Chame
setChannelProfilepara definir o cenário do canal e, em seguida, chame joinChannel para entrar em um canal:No cenário de chamada de vídeo, todos os usuários assumem a função de host e podem publicar e assinar streams.
No cenário de transmissão interativa, é necessário chamar
setClientRolepara configurar a função do usuário. Defina a função como host para quem vai publicar uma stream. Se o usuário precisar apenas assinar uma stream, defina sua função como viewer.
-
Após entrar em um canal, a função do usuário determina se ele pode publicar ou assinar streams:
Todos os participantes de um canal podem assinar suas streams de áudio e vídeo.
Um host tem permissão para publicar streams de áudio e vídeo no canal.
Caso um viewer precise publicar uma stream, ele deve invocar o método
setClientRolepara alterar sua função para host.
Projeto de exemplo
A Alibaba Cloud disponibiliza um projeto de exemplo open-source do ARTC SDK para interação de áudio e vídeo em tempo real. Baixe o projeto ou visualize o código-fonte de exemplo.
Pré-requisitos
Antes de executar o projeto de exemplo, certifique-se de que seu ambiente de desenvolvimento atenda aos seguintes requisitos:
Ferramenta de desenvolvimento: Android Studio 2020.3.1 ou superior.
-
Dispositivo de teste: Um dispositivo físico rodando Android 5.0 (API level 21) ou posterior.
NotaUtilize um dispositivo físico para testes. Emuladores podem não oferecer todas as funcionalidades necessárias.
Ambiente de rede: Uma conexão de rede estável.
Preparação do aplicativo: Obtenha o AppID e a AppKey do seu aplicativo. Para mais detalhes, consulte Create an application.
Crie um projeto
Esta seção explica como criar um projeto e adicionar as permissões necessárias para áudio e vídeo em tempo real. Caso já possua um projeto configurado, ignore esta etapa.
Abra o Android Studio e selecione New Project.
Selecione Phone and Tablet e escolha um modelo inicial. Este exemplo utiliza Empty Views Activity.
Defina o nome do projeto, o nome do pacote, o local de salvamento, a linguagem de desenvolvimento (Java neste exemplo) e a linguagem de configuração de build (Groovy DSL neste exemplo).
Clique em Finish e aguarde a sincronização do projeto.
Configure o projeto
Etapa 1: Importar o SDK
Integração automática via Maven (recomendado)
Abra o arquivo
settings.gradleno diretório raiz do seu projeto e adicione os repositórios Maven exigidos pelo ARTC SDK ao blocodependencyResolutionManagement/repositoriesconforme abaixo:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// Add the Maven repositories for the ARTC SDK
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/public' }
}
}
Nota: Se você estiver usando uma versão do Android Gradle Plugin anterior à 7.1.0, talvez não encontre esse bloco no arquivo settings.gradle. Para mais informações, consulte Android Gradle Plugin 7.1. Nesse caso, utilize a alternativa a seguir:
Abra o arquivo
app/build.gradlee adicione a dependência do ARTC SDK ao blocodependencies. As informações de versão estão disponíveis em SDK download and integration. Substitua${latest_version}pelo número específico da versão. A versão mais recente é 7.11.0.
dependencies {
// Add the dependency for the real-time audio and video SDK// Replace ${latest_version} with a specific version number
implementation 'com.aliyun.aio:AliVCSDK_ARTC:${latest_version}'// For versions 7.4.0 and earlier, you must add the keep dependency// implementation 'com.aliyun.aio.keep:keep:1.0.1'
}
Se estiver utilizando o Android Gradle Plugin 8.1 ou superior, o Android Studio recomenda que você Migre as dependências do projeto para catálogos de versões.
Integração manual
Baixe a versão desejada do arquivo AAR do ARTC SDK em SDK download and integration. A versão mais recente é 7.11.0, com um nome de arquivo semelhante a
AliVCSDK_ARTC-x.y.z.aar.Copie o arquivo AAR baixado para o diretório do seu projeto, como
app/libs. Crie essa pasta caso ela não exista.Abra o arquivo
settings.gradlena raiz do projeto e adicione o diretório que contém o arquivo AAR emdependencyResolutionManagement/repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// Add the relative path to the directory where the ARTC SDK is locatedflatDir {
dir 'app/libs'
}
}
}
Nota: Se você estiver usando uma versão do Android Gradle Plugin anterior à 7.1.0, talvez não encontre esse bloco no arquivo settings.gradle. Para mais informações, consulte Android Gradle Plugin 7.1. Nesse caso, utilize a alternativa a seguir:
Abra o arquivo build.gradle no diretório raiz do seu projeto e adicione o seguinte ao bloco allprojects/repositories:
allprojects {
repositories {
...
// Add the relative path to the directory where the ARTC SDK is locatedflatDir {
dir 'app/libs'
}
}
}
Abra o arquivo
app/build.gradlee adicione a dependência do arquivo AAR ao blocodependencies:
// Replace x.y.z with the corresponding version number
implementation(name:'AliVCSDK_ARTC', version: 'x.y.z', ext:'aar')
-
Após a conclusão do build, a dependência aparecerá na seção External Libraries.

Etapa 2: Especifique arquiteturas de CPU suportadas
Abra o arquivo app/build.gradle e especifique as arquiteturas de CPU suportadas no bloco defaultConfig. As arquiteturas disponíveis incluem armeabi-v7a, arm64-v8a, x86, and x86_64. Selecione aquelas adequadas ao seu caso de uso.
android {
defaultConfig {
// ...other default configurations// Support for armeabi-v7a and arm64-v8a architectures
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
}
Etapa 3: Defina permissões
Configure as permissões necessárias para o seu aplicativo.
Acesse o diretório app/src/main, abra o arquivo AndroidManifest.xml e adicione as permissões requeridas.
<uses-feature android:name="android.hardware.camera" android:required="false" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!-- Request legacy Bluetooth permissions on older devices. --><uses-permissionandroid:name="android.permission.BLUETOOTH"android:maxSdkVersion="30" /><uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"android:maxSdkVersion="30" /><!-- Needed only if your app communicates with already-paired Bluetooth devices. --><uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /><uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.WRITE_SETTINGS"tools:ignore="ProtectedPermissions" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Permissões de Bluetooth em tempo de execução
O arquivo AndroidManifest.xml interno do ARTC SDK declara diversas permissões. Note que cabe a você solicitar quaisquer permissões dinâmicas necessárias durante a execução. A permissão BLUETOOTH_CONNECT, introduzida no Android 12, é um exemplo disso. Ao importar o ARTC SDK, as permissões declaradas nele são mescladas ao manifesto do seu aplicativo. Recomendamos declarar explicitamente todas as permissões necessárias no seu próprio manifesto para garantir clareza e aderência ao princípio do menor privilégio.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Dependendo do seu cenário de negócios, caso não precise de alguma das permissões listadas, declare sua remoção no arquivo AndroidManifest.xml do projeto principal:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" tools:node="remove"/>
Cenários de permissão de Bluetooth:
Cenário 1: Bluetooth necessário
O targetSdk do seu aplicativo é inferior a 31
Quando o targetSdk do projeto for menor que 31, a funcionalidade Bluetooth é controlada pela permissão legada BLUETOOTH. Declare o seguinte no manifesto do seu aplicativo:
<!-- Declare the Bluetooth permission --><uses-permission android:name="android.permission.BLUETOOTH" /><!-- Override and remove the permission for API 31+ --><uses-permission android:name="android.permission.BLUETOOTH_CONNECT" tools:node="remove" />
Nota
O SDK inclui uma declaração para a permissão
BLUETOOTH_CONNECT. Essa permissão foi introduzida no Android 12 (API level 31) e deve ser solicitada em tempo de execução através derequestPermissions.-
Em alguns dispositivos, se um aplicativo incluir a declaração
BLUETOOTH_CONNECT, o sistema exige uma solicitação em tempo de execução para evitar umaSecurityException. Caso enfrente esse problema, adote uma das abordagens abaixo:Opção 1: Remova a declaração da permissão usando
tools:node="remove".Opção 2: Solicite a permissão em tempo de execução.
O targetSdk do seu aplicativo é 31 ou superior
Quando o targetSdk do projeto for 31 ou maior, você precisará gerenciar as permissões de Bluetooth para suportar tanto versões antigas quanto recentes do Android. Declare as permissões no arquivo AndroidManifest.xml do aplicativo principal:
<!-- Declare the Bluetooth permission and set android:maxSdkVersion to 30 for compatibility with earlier devices --><uses-permission android:name="android.permission.BLUETOOTH"/><!-- Declare the Bluetooth permission for API 31+ --><uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/><!-- Other Bluetooth permissions -->
Além disso, como BLUETOOTH_CONNECT é uma permissão dinâmica, é obrigatório solicitá-la em tempo de execução:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
String[] permissions = {
android.Manifest.permission.BLUETOOTH_CONNECT
};
ActivityCompat.requestPermissions(activity, permissions, REQUEST_BLUETOOTH);
}
Cenário 2: Bluetooth não necessário
Para evitar falhas ou prompts de permissão relacionados ao Bluetooth, recomendamos remover as permissões desnecessárias.
No arquivo AndroidManifest.xml do projeto principal, use tools:node="remove" para substituir e remover a permissão:
<!-- Override and remove the Bluetooth permission declarations from the ARTC SDK --><uses-permission android:name="android.permission.BLUETOOTH" tools:node="remove" /><uses-permission android:name="android.permission.BLUETOOTH_CONNECT" tools:node="remove" />
Outras permissões de tempo de execução
No Android 6.0 (API level 23) e versões posteriores, é obrigatório solicitar permissões perigosas em tempo de execução. Além de declará-las no arquivo AndroidManifest.xml, você deve solicitá-las programaticamente durante a execução.
As seguintes permissões exigem solicitação em tempo de execução:
Manifest.permission.CAMERA
Manifest.permission.WRITE_EXTERNAL_STORAGE
Manifest.permission.RECORD_AUDIO
Manifest.permission.READ_EXTERNAL_STORAGE
Manifest.permission.READ_PHONE_STATE
No Android 12 (API level 31) ou superior, também é necessário solicitar a seguinte permissão em tempo de execução:
Manifest.permission.BLUETOOTH_CONNECT
A tabela a seguir descreve as principais permissões e suas finalidades:
|
Permissão |
Descrição |
Finalidade |
Obrigatória |
Permissão de runtime |
|
|
Concede acesso à câmera. |
Capturar vídeo para comunicação em tempo real. |
Sim |
Android >= 6.0 |
|
|
Concede acesso ao microfone. |
Capturar áudio para comunicação em tempo real. |
Sim |
Android >= 6.0 |
|
|
Concede acesso à internet. |
Transmitir dados de áudio e vídeo pela rede. |
Sim |
Não |
|
|
Permite obter o status da rede. |
Monitorar conectividade e otimizar a qualidade da stream, gerenciando reconexões. |
Opcional |
Não |
|
|
Permite obter o status do Wi-Fi. |
Obter informações sobre a conexão Wi-Fi atual para otimizar o desempenho da rede. |
Opcional |
Não |
|
|
Permite modificar configurações de áudio. |
Ajustar volume do sistema ou alternar entre dispositivos de saída (ex: alto-falante, fone de ouvido). |
Opcional |
Não |
|
|
Permissão de Bluetooth (funcionalidade básica) |
Conectar a dispositivos Bluetooth, como headsets. |
Opcional |
Não |
|
|
Permissão de conexão Bluetooth |
Comunicar-se com dispositivos Bluetooth pareados, por exemplo, para transmitir streams de áudio. |
Opcional |
Android >= 12 |
|
|
Permite acessar informações relacionadas ao estado telefônico do dispositivo. |
Gerenciar streams de áudio durante chamadas telefônicas, pausando a sessão quando uma chamada iniciar. |
Opcional |
Android >= 6.0 |
|
|
Permite ler arquivos do armazenamento externo. |
Habilitar recursos como reproduzir um arquivo de áudio local como efeito sonoro ou música de fundo. |
Opcional |
Android >= 6.0 |
|
|
Permite gravar no armazenamento externo. |
Salvar arquivos como logs do aplicativo ou mídias gravadas. |
Opcional |
Android >= 6.0 |
Etapa 4: Evitar ofuscação de código (opcional)
No arquivo app/proguard-rules.pro, adicione as regras do ProGuard abaixo para impedir que as interfaces públicas do SDK sejam ofuscadas.
-keep class com.aliyun.allinone.** {*;}-keep class com.aliyun.rts.network.AliHttpTool {*;}-keep class com.aliyun.common.AlivcBase {*;}-keep class com.huawei.multimedia.alivc.** {*;}-keep class com.alivc.rtc.** {*;}-keep class com.alivc.component.** {*;}-keep class org.webrtc.** {*;}
FAQ
ARTC SDK e permissões adicionais
Ao importar o ARTC SDK, as permissões do manifesto dele são automaticamente mescladas ao manifesto do seu aplicativo. A lista exata pode variar conforme a versão do SDK. Para obter a lista mais precisa, inspecione o arquivo AndroidManifest.xml dentro do arquivo .aar do SDK.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Essas permissões servem principalmente para suportar recursos como detecção de estado de rede, acesso a informações de Wi-Fi, conexões Bluetooth e roteamento de áudio.
Resolver conflitos de permissão
O ARTC SDK foi projetado para se adaptar a diferentes versões do Android. Por exemplo, ele considera a nova permissão de runtime BLUETOOTH_CONNECT no Android 12 (API level 31) e posteriores. Embora esse design geralmente evite erros de compilação, você ainda pode encontrar problemas como:
Comportamento inesperado em tempo de execução, como falhas na mesclagem do Manifest.
Risco de reprovação na Google Play: Se seu aplicativo declarar uma permissão para um recurso que não utiliza, ele poderá ser rejeitado por violar o princípio do menor privilégio.
Para mitigar esses possíveis problemas, considere as estratégias a seguir:
Avalie os requisitos de permissão. Primeiro, determine se seu aplicativo realmente precisa de todas as permissões declaradas pelo SDK. Caso não utilize um recurso como Bluetooth, remova a declaração da permissão associada para seguir o princípio do menor privilégio. Por exemplo, se o targetSdk do seu app for menor que 31, a permissão
BLUETOOTH_CONNECTnão é necessária.-
Use diretivas de mesclagem do Manifest para resolver conflitos. Se uma permissão declarada pelo SDK entrar em conflito com uma declaração em outro módulo (por exemplo, um atributo
maxSdkVersiondiferente), utilize uma diretiva de namespacetoolsnoAndroidManifest.xmlprincipal do seu app para resolver o conflito:<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><!-- Example: Remove a permission declared by the SDK that your app does not need --><uses-permissionandroid:name="android.permission.BLUETOOTH_CONNECT"tools:node="remove" /><!-- Example: Override a permission attribute --><uses-permissionandroid:name="android.permission.BLUETOOTH"android:maxSdkVersion="30"tools:replace="android:maxSdkVersion" /></manifest>
Etapa 5: Crie a UI
Crie a interface do usuário para o seu cenário interativo em tempo real. O código de exemplo abaixo cria duas views para uma chamada de vídeo, exibindo o vídeo local e o remoto.
Procedimento
Esta seção explica como usar o ARTC SDK para construir uma aplicação básica de áudio e vídeo em tempo real. Copie o exemplo de código para testar rapidamente e siga as etapas para compreender as chamadas principais da api.
O diagrama a seguir ilustra o fluxo de trabalho básico de uma chamada de áudio e vídeo em tempo real:
Abaixo está um exemplo completo de código que demonstra o processo básico para implementar uma chamada de vídeo:
Para detalhes sobre o código de exemplo completo e como executá-lo, consulte Run the ARTC demo for Android.
1. Solicitar permissões
Antes de iniciar uma chamada de vídeo, verifique se o aplicativo possui as permissões necessárias:
private static final int REQUEST_PERMISSION_CODE = 101;
private static final String[] PERMISSION_MANIFEST = {
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
};
private static final String[] PERMISSION_MANIFEST33 = {
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CAMERA
};
private static String[] getPermissions() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
return PERMISSION_MANIFEST;
}
return PERMISSION_MANIFEST33;
}
public boolean checkOrRequestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {
requestPermissions(getPermissions(), REQUEST_PERMISSION_CODE);
return false;
}
}
return true;
}
2. Obter um token de autenticação
Entrar em um canal ARTC requer um token de autenticação. Para detalhes sobre como gerar um token, consulte Token-based authentication. O método de geração do token (parâmetro único ou múltiplos parâmetros) determina qual api joinChannel deve ser chamada.
Ambiente de produção:
A geração de um token exige sua AppKey. Codificar a AppKey diretamente no cliente representa um risco de segurança, portanto, recomendamos fortemente gerar tokens no seu Servidor de Aplicativos e enviá-los ao cliente.
Desenvolvimento e depuração:
Durante o desenvolvimento, caso seu Servidor de Aplicativos ainda não possa gerar tokens, utilize o exemplo abaixo para criar tokens temporários:
public final class ARTCTokenHelper {
/**
* RTC AppId
*/
public static String AppId = "";
/**
* RTC AppKey
*/
public static String AppKey = "";
/**
* Generate a single-parameter meeting token based on channelId, userId, and nonce
*/
public static String generateSingleParameterToken(String appId, String appKey, String channelId, String userId, long timestamp, String nonce) {
StringBuilder stringBuilder = new StringBuilder()
.append(appId)
.append(appKey)
.append(channelId)
.append(userId)
.append(timestamp);
String token = getSHA256(stringBuilder.toString());
try{
JSONObject tokenJson = new JSONObject();
tokenJson.put("appid", AppId);
tokenJson.put("channelid", channelId);
tokenJson.put("userid", userId);
tokenJson.put("nonce", nonce);
tokenJson.put("timestamp", timestamp);
tokenJson.put("token", token);
String base64Token = Base64.encodeToString(tokenJson.toString().getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP);
return base64Token;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Generate a single-parameter meeting token based on channelId, userId, and timestamp
*/
public static String generateSingleParameterToken(String appId, String appKey, String channelId, String userId, long timestamp) {
return generateSingleParameterToken(appId, appKey, channelId, userId, timestamp, "");
}
public static String getSHA256(String str) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] hash = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));
return byte2Hex(hash);
} catch (NoSuchAlgorithmException e) {
// Consider logging the exception and/or re-throwing as a RuntimeException
e.printStackTrace();
}
return "";
}
private static String byte2Hex(byte[] bytes) {
StringBuilder stringBuilder = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
// Use single quote for char
stringBuilder.append('0');
}
stringBuilder.append(hex);
}
return stringBuilder.toString();
}
public static long getTimesTamp() {
return System.currentTimeMillis() / 1000 + 60 * 60 * 24;
}
}
3. Importar classes do ARTC SDK
Importe as classes e interfaces do ARTC SDK:
// Import ARTC classes
import com.alivc.rtc.AliRtcEngine;
import com.alivc.rtc.AliRtcEngineEventListener;
import com.alivc.rtc.AliRtcEngineNotify;
4. Crie e inicializar o engine
-
Crie o engine RTC
Chame o método
getInstance[1/2]para criar uma instância deAliRTCEngine.private AliRtcEngine mAliRtcEngine = null; if(mAliRtcEngine == null) { mAliRtcEngine = AliRtcEngine.getInstance(this); } -
Inicializar o engine
-
Chame
setChannelProfilepara definir o perfil do canal comoAliRTCSdkInteractiveLive(modo interativo).Escolha entre o modo interativo para entretenimento e o modo de comunicação para chamadas. Selecionar o modo correto garante uma experiência de usuário fluida e uso eficiente da rede.
Modo
Publicação
Assinatura
Descrição
Modo interativo
Restrições baseadas em funções se aplicam. Apenas usuários com a função host podem publicar streams.
Os participantes podem trocar de função a qualquer momento durante a sessão.
Sem restrições de função. Todos os participantes têm permissão para assinar streams.
No modo interativo, eventos como entrada ou saída de um host são enviados aos viewers. A atividade de um viewer não é enviada ao host, garantindo uma experiência ininterrupta para ele.
Se você prevê que os viewers possam precisar interagir no futuro, recomendamos o uso do modo interativo. Sua flexibilidade permite ajustar as funções dos usuários para atender a diferentes necessidades de interação.
Modo de comunicação
Sem restrições de função. Todos os participantes têm permissão para publicar streams.
Sem restrições de função. Todos os participantes têm permissão para assinar streams.
No modo de comunicação, os participantes têm ciência da presença uns dos outros na sessão.
Embora este modo não diferencie funções de usuário, ele é funcionalmente equivalente à função host no modo interativo. Isso simplifica as operações, permitindo que os usuários obtenham a funcionalidade desejada com menos chamadas de api.
-
Chame
setClientRolepara definir a função do usuário comoAliRTCSdkInteractive(host) ouAliRTCSdkLive(viewer). Nota: A função host publica e assina por padrão. A função viewer apenas assina por padrão, com visualização prévia e publicação desativadas.NotaQuando um usuário troca de função em um canal, o sistema ajusta o status de publicação das streams de áudio e vídeo adequadamente:
Trocar de host para viewer: O sistema interrompe a publicação das streams locais de áudio e vídeo. As streams remotas assinadas não são afetadas, e o usuário pode continuar assistindo aos outros participantes.
Trocar de viewer para host: O sistema inicia a publicação das streams locais de áudio e vídeo. As streams remotas assinadas permanecem inalteradas, e o usuário pode continuar assistindo aos outros participantes.
// Set the channel profile to interactive mode. In RTC, always use AliRTCSdkInteractiveLive. mAliRtcEngine.setChannelProfile(AliRtcEngine.AliRTCSdkChannelProfile.AliRTCSdkInteractiveLive); // Set the user role. Use AliRTCSdkInteractive to both publish and subscribe to streams, or AliRTCSdkLive to only subscribe. mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
-
-
Configure callbacks comuns
Quando o SDK encontra um problema, ele tenta primeiro uma recuperação automática. Para erros que não consegue resolver, o SDK notifica seu aplicativo por meio de callbacks.
Abaixo estão os principais callbacks para problemas irrecuperáveis que sua aplicação deve tratar:
Causa da exceção
Callback e parâmetros
Solução
Descrição
Falha na autenticação
O parâmetro
resultdo callbackonJoinChannelResultéAliRtcErrJoinBadToken.Seu aplicativo deve verificar se o token está correto.
Se a autenticação falhar quando um usuário chamar uma api, o callback retornará um erro de falha de autenticação.
Token prestes a expirar
onAuthInfoWillExpireObtenha um novo token e chame
refreshAuthInfopara atualizar as informações de autenticação.Um erro de expiração de token pode ocorrer tanto ao chamar uma api quanto durante a execução. O erro é reportado através de um callback de api ou de um callback de erro separado.
Token expirado
onAuthInfoExpiredSeu aplicativo deve entrar novamente no canal.
Um erro de expiração de token pode ocorrer tanto ao chamar uma api quanto durante a execução. O erro é reportado através de um callback de api ou de um callback de erro separado.
Problema de conexão de rede
O callback
onConnectionStatusChangeretorna AliRtcConnectionStatusFailed.Seu aplicativo deve entrar novamente no canal.
O SDK recupera-se automaticamente de breves desconexões de rede. Se a desconexão exceder um limite predefinido, ocorre um timeout e a conexão é encerrada. Seu aplicativo deve verificar o status da rede e solicitar que o usuário entre novamente no canal.
Removido do canal
onByeAliRtcOnByeUserReplaced: Verifique se outro usuário entrou com o mesmouserId.AliRtcOnByeBeKickedOut: O usuário foi removido do canal pelo Servidor de Aplicativos e deve entrar novamente.AliRtcOnByeChannelTerminated: O canal foi encerrado e o usuário deve entrar novamente.
O service RTC permite que um administrador remova participantes.
Exceção de dispositivo local
onLocalDeviceExceptionSeu aplicativo deve verificar as permissões e se o hardware está funcionando corretamente.
O service RTC suporta detecção e diagnóstico de dispositivos. Quando ocorre uma exceção de dispositivo local que o SDK não consegue resolver, ele notifica seu aplicativo através de um callback. Seu aplicativo deve então verificar o status do dispositivo.
private AliRtcEngineEventListener mRtcEngineEventListener = new AliRtcEngineEventListener() { @Override public void onJoinChannelResult(int result, String channel, String userId, int elapsed) { super.onJoinChannelResult(result, channel, userId, elapsed); handleJoinResult(result, channel, userId); } @Override public void onLeaveChannelResult(int result, AliRtcEngine.AliRtcStats stats){ super.onLeaveChannelResult(result, stats); } @Override public void onConnectionStatusChange(AliRtcEngine.AliRtcConnectionStatus status, AliRtcEngine.AliRtcConnectionStatusChangeReason reason){ super.onConnectionStatusChange(status, reason); handler.post(new Runnable() { @Override public void run() { if(status == AliRtcEngine.AliRtcConnectionStatus.AliRtcConnectionStatusFailed) { /* TODO: This callback must be handled. It is triggered only after the SDK's internal recovery strategies fail. We recommend notifying the user. */ ToastHelper.showToast(VideoChatActivity.this, R.string.video_chat_connection_failed, Toast.LENGTH_SHORT); } else { /* TODO: Optional. Add business logic here, such as for data analytics or UI updates. */ } } }); } @Override public void onLocalDeviceException(AliRtcEngine.AliRtcEngineLocalDeviceType deviceType, AliRtcEngine.AliRtcEngineLocalDeviceExceptionType exceptionType, String msg){ super.onLocalDeviceException(deviceType, exceptionType, msg); /* TODO: This callback must be handled. It is triggered only after the SDK's internal recovery strategies fail. We recommend notifying the user of the device error. */ handler.post(new Runnable() { @Override public void run() { String str = "OnLocalDeviceException deviceType: " + deviceType + " exceptionType: " + exceptionType + " msg: " + msg; ToastHelper.showToast(VideoChatActivity.this, str, Toast.LENGTH_SHORT); } }); } }; private AliRtcEngineNotify mRtcEngineNotify = new AliRtcEngineNotify() { @Override public void onAuthInfoWillExpire() { super.onAuthInfoWillExpire(); /* TODO: This must be handled. The token is about to expire. Your app must get a new authentication token for the current channel and user, and then call refreshAuthInfo. */ } @Override public void onRemoteUserOnLineNotify(String uid, int elapsed){ super.onRemoteUserOnLineNotify(uid, elapsed); } // In the onRemoteUserOffLineNotify callback, unbind the renderer for the remote video stream. @Override public void onRemoteUserOffLineNotify(String uid, AliRtcEngine.AliRtcUserOfflineReason reason){ super.onRemoteUserOffLineNotify(uid, reason); } // In the onRemoteTrackAvailableNotify callback, set up the renderer for the remote video stream. @Override public void onRemoteTrackAvailableNotify(String uid, AliRtcEngine.AliRtcAudioTrack audioTrack, AliRtcEngine.AliRtcVideoTrack videoTrack){ handler.post(new Runnable() { @Override public void run() { if(videoTrack == AliRtcVideoTrackCamera) { SurfaceView surfaceView = mAliRtcEngine.createRenderSurfaceView(VideoChatActivity.this); surfaceView.setZOrderMediaOverlay(true); FrameLayout view = getAvailableView(); if (view == null) { return; } remoteViews.put(uid, view); view.addView(surfaceView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); AliRtcEngine.AliRtcVideoCanvas remoteVideoCanvas = new AliRtcEngine.AliRtcVideoCanvas(); remoteVideoCanvas.view = surfaceView; mAliRtcEngine.setRemoteViewConfig(remoteVideoCanvas, uid, AliRtcVideoTrackCamera); } else if(videoTrack == AliRtcVideoTrackNo) { if(remoteViews.containsKey(uid)) { ViewGroup view = remoteViews.get(uid); if(view != null) { view.removeAllViews(); remoteViews.remove(uid); mAliRtcEngine.setRemoteViewConfig(null, uid, AliRtcVideoTrackCamera); } } } } }); } /* Your app must handle cases where multiple devices attempt to join with the same userId. */ @Override public void onBye(int code){ handler.post(new Runnable() { @Override public void run() { String msg = "onBye code:" + code; ToastHelper.showToast(VideoChatActivity.this, msg, Toast.LENGTH_SHORT); } }); } }; mAliRtcEngine.setRtcEngineEventListener(mRtcEngineEventListener); mAliRtcEngine.setRtcEngineNotify(mRtcEngineNotify);
5. Defina propriedades de áudio e vídeo
-
Defina propriedades de áudio
Chame
setAudioProfilepara configurar o modo de codificação de áudio e o cenário de áudio.mAliRtcEngine.setAudioProfile(AliRtcEngine.AliRtcAudioProfile.AliRtcEngineHighQualityMode, AliRtcEngine.AliRtcAudioScenario.AliRtcSceneMusicMode); -
Defina propriedades de vídeo
Configure as propriedades da stream de vídeo publicada, como resolução, bitrate e taxa de quadros.
// Set video encoding parameters. AliRtcEngine.AliRtcVideoEncoderConfiguration aliRtcVideoEncoderConfiguration = new AliRtcEngine.AliRtcVideoEncoderConfiguration(); aliRtcVideoEncoderConfiguration.dimensions = new AliRtcEngine.AliRtcVideoDimensions( 720, 1280); aliRtcVideoEncoderConfiguration.frameRate = 20; aliRtcVideoEncoderConfiguration.bitrate = 1200; aliRtcVideoEncoderConfiguration.keyFrameInterval = 2000; aliRtcVideoEncoderConfiguration.orientationMode = AliRtcVideoEncoderOrientationModeAdaptive; mAliRtcEngine.setVideoEncoderConfiguration(aliRtcVideoEncoderConfiguration);
6. Configure propriedades de publicação e assinatura
Configure a publicação de streams e o comportamento padrão de assinatura:
Chame
publishLocalAudioStreampara publicar a stream de áudio.Chame
publishLocalVideoStreampara publicar a stream de vídeo. Para uma chamada apenas de áudio, defina isso comofalse.
// The SDK publishes audio by default, so you do not need to call publishLocalAudioStream.
mAliRtcEngine.publishLocalAudioStream(true);
// For a video call, you do not need to call publishLocalVideoStream(true) because the SDK publishes video by default.
// For an audio-only call, you must call publishLocalVideoStream(false) to disable video publishing.
mAliRtcEngine.publishLocalVideoStream(true);
// Set the default to subscribe to remote audio and video streams.
mAliRtcEngine.setDefaultSubscribeAllRemoteAudioStreams(true);
mAliRtcEngine.subscribeAllRemoteAudioStreams(true);
mAliRtcEngine.setDefaultSubscribeAllRemoteVideoStreams(true);
mAliRtcEngine.subscribeAllRemoteVideoStreams(true);
Por padrão, o SDK publica automaticamente streams locais e assina streams remotas. Chame os métodos acima para desativar esse comportamento automático.
7. Iniciar a pré-visualização local
Chame
setLocalViewConfigpara configurar a view de pré-visualização local. Isso requer um objetoAliRtcVideoCanvas.Chame o método startPreview para iniciar a pré-visualização do vídeo local.
mLocalVideoCanvas = new AliRtcEngine.AliRtcVideoCanvas();
SurfaceView localSurfaceView = mAliRtcEngine.createRenderSurfaceView(VideoChatActivity.this);
localSurfaceView.setZOrderOnTop(true);
localSurfaceView.setZOrderMediaOverlay(true);
FrameLayout fl_local = findViewById(R.id.fl_local);
fl_local.addView(localSurfaceView, layoutParams);
mLocalVideoCanvas.view = localSurfaceView;
mAliRtcEngine.setLocalViewConfig(mLocalVideoCanvas, AliRtcVideoTrackCamera);
mAliRtcEngine.startPreview();
8. Entrar no canal
Chame joinChannel para entrar em um canal. Se o token for gerado com base na regra de parâmetro único, chame a interface de parâmetro único [joinChannel[1/3]](t2309760.xdita#758b964acc7jd) do SDK. Se o token for gerado com base na regra de múltiplos parâmetros, chame a interface de múltiplos parâmetros [joinChannel[2/3]](t2309760.xdita#766e40a1cfk4p) do SDK. Após entrar no canal, o callback onJoinChannelResult fornece o resultado. Se o result for 0, você entrou no canal com sucesso. Caso contrário, verifique se o token fornecido é inválido.
mAliRtcEngine.joinChannel(token, null, null, null);
Após entrar no canal, o SDK publica e assina streams com base nos parâmetros definidos antes da entrada.
O SDK publica e assina streams automaticamente por padrão para reduzir o número de chamadas de api necessárias.
9. Configure a view remota
Durante a inicialização do engine, configure o callback mAliRtcEngine.setRtcEngineNotify. No callback onRemoteTrackAvailableNotify, configure a view remota para cada usuário remoto:
@Override
public void onRemoteTrackAvailableNotify(String uid, AliRtcEngine.AliRtcAudioTrack audioTrack, AliRtcEngine.AliRtcVideoTrack videoTrack){
handler.post(new Runnable() {
@Override
public void run() {
if(videoTrack == AliRtcVideoTrackCamera) {
SurfaceView surfaceView = mAliRtcEngine.createRenderSurfaceView(VideoChatActivity.this);
surfaceView.setZOrderMediaOverlay(true);
FrameLayout fl_remote = findViewById(R.id.fl_remote);
if (fl_remote == null) {
return;
}
fl_remote.addView(surfaceView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
AliRtcEngine.AliRtcVideoCanvas remoteVideoCanvas = new AliRtcEngine.AliRtcVideoCanvas();
remoteVideoCanvas.view = surfaceView;
mAliRtcEngine.setRemoteViewConfig(remoteVideoCanvas, uid, AliRtcVideoTrackCamera);
} else if(videoTrack == AliRtcVideoTrackNo) {
FrameLayout fl_remote = findViewById(R.id.fl_remote);
fl_remote.removeAllViews();
mAliRtcEngine.setRemoteViewConfig(null, uid, AliRtcVideoTrackCamera);
}
}
});
}
10. Sair do canal e destruir o engine
Quando a sessão de áudio e vídeo terminar, saia do canal e destrua o engine:
Chame
stopPreviewpara parar a pré-visualização de vídeo.Chame
leaveChannelpara sair do canal.Chame
destroypara destruir o engine e liberar seus recursos.
private void destroyRtcEngine() {
mAliRtcEngine.stopPreview();
mAliRtcEngine.setLocalViewConfig(null, AliRtcVideoTrackCamera);
mAliRtcEngine.leaveChannel();
mAliRtcEngine.destroy();
mAliRtcEngine = null;
}
11. Demonstração
