Integração Mobile
Este guia explica como integrar a API do Videochamada.com.br em aplicativos mobile (iOS, Android e React Native) usando WebView.
Visão Geral
A forma mais simples de integrar videochamadas em seu app mobile é usando WebView. Esta abordagem:
- Funciona imediatamente sem implementação WebRTC nativa
- Mantém paridade de funcionalidades com a versão web
- Requer apenas 3 passos para implementar
Pré-requisitos
Antes de começar, você precisa:
- Uma conta no Videochamada.com.br
- Um projeto criado no painel de gerenciamento
- Uma API Key válida (veja Autenticação e Token)
Passo 1: Obter sua API Key
- Acesse o painel de gerenciamento do seu projeto
- Navegue até a aba API Keys
- Clique em + Nova Chave para gerar uma nova API Key
- Copie e armazene a chave de forma segura
Segurança
Nunca exponha sua API Key no código do aplicativo. Faça as chamadas à API através do seu backend.
Passo 2: Criar Chamada via API
Seu backend deve criar a chamada e retornar a URL para o app mobile.
Endpoint
Cabeçalhos
Corpo da Requisição (opcional)
Resposta
{
"id": "abc123-def456",
"status": "created",
"url": "https://call.videochamada.com.br/call/abc123-def456"
}
URL da Chamada
Use o campo url da resposta para abrir a chamada no WebView. Você pode adicionar o parâmetro ?username=NomeDoUsuario para pré-definir o nome do participante.
Passo 3: Abrir Chamada em WebView
iOS (Swift)
import UIKit
import WebKit
class VideoCallViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
var webView: WKWebView!
var callUrl: String = ""
var username: String = ""
override func viewDidLoad() {
super.viewDidLoad()
// Configurar WebView com permissões de mídia
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true
config.mediaTypesRequiringUserActionForPlayback = []
webView = WKWebView(frame: view.bounds, configuration: config)
webView.uiDelegate = self
webView.navigationDelegate = self
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(webView)
// Carregar URL da chamada
let urlString = "\(callUrl)?username=\(username.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")"
if let url = URL(string: urlString) {
webView.load(URLRequest(url: url))
}
}
// Permitir acesso à câmera e microfone
func webView(_ webView: WKWebView,
requestMediaCapturePermissionFor origin: WKSecurityOrigin,
initiatedByFrame frame: WKFrameInfo,
type: WKMediaCaptureType,
decisionHandler: @escaping (WKPermissionDecision) -> Void) {
decisionHandler(.grant)
}
}
Info.plist
Adicione as permissões necessárias no Info.plist:
<key>NSCameraUsageDescription</key>
<string>Necessário para videochamadas</string>
<key>NSMicrophoneUsageDescription</key>
<string>Necessário para videochamadas</string>
Android (Kotlin)
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.webkit.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class VideoCallActivity : AppCompatActivity() {
private lateinit var webView: WebView
private val PERMISSION_REQUEST_CODE = 1001
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Verificar permissões
checkPermissions()
// Configurar WebView
webView = WebView(this).apply {
settings.javaScriptEnabled = true
settings.mediaPlaybackRequiresUserGesture = false
settings.domStorageEnabled = true
webChromeClient = object : WebChromeClient() {
override fun onPermissionRequest(request: PermissionRequest) {
runOnUiThread {
request.grant(request.resources)
}
}
}
}
setContentView(webView)
// Carregar URL da chamada
val callUrl = intent.getStringExtra("CALL_URL") ?: return
val username = intent.getStringExtra("USERNAME") ?: "Participante"
val encodedUsername = java.net.URLEncoder.encode(username, "UTF-8")
webView.loadUrl("$callUrl?username=$encodedUsername")
}
private fun checkPermissions() {
val permissions = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
)
val permissionsToRequest = permissions.filter {
ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
}
if (permissionsToRequest.isNotEmpty()) {
ActivityCompat.requestPermissions(
this,
permissionsToRequest.toTypedArray(),
PERMISSION_REQUEST_CODE
)
}
}
override fun onBackPressed() {
if (webView.canGoBack()) {
webView.goBack()
} else {
super.onBackPressed()
}
}
}
AndroidManifest.xml
Adicione as permissões necessárias:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
React Native
Instale a dependência:
import React, { useRef } from 'react';
import { StyleSheet, View, Platform, PermissionsAndroid } from 'react-native';
import { WebView } from 'react-native-webview';
const VideoCallScreen = ({ route }) => {
const { callUrl, username } = route.params;
const webViewRef = useRef(null);
// Solicitar permissões no Android
React.useEffect(() => {
const requestPermissions = async () => {
if (Platform.OS === 'android') {
try {
const grants = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.CAMERA,
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
]);
console.log('Permissões:', grants);
} catch (err) {
console.warn(err);
}
}
};
requestPermissions();
}, []);
const encodedUsername = encodeURIComponent(username || 'Participante');
const fullUrl = `${callUrl}?username=${encodedUsername}`;
return (
<View style={styles.container}>
<WebView
ref={webViewRef}
source={{ uri: fullUrl }}
style={styles.webview}
javaScriptEnabled={true}
domStorageEnabled={true}
mediaPlaybackRequiresUserAction={false}
allowsInlineMediaPlayback={true}
// Permissões de mídia
mediaCapturePermissionGrantType="grant"
// Configurações adicionais
startInLoadingState={true}
allowsFullscreenVideo={true}
onError={(syntheticEvent) => {
const { nativeEvent } = syntheticEvent;
console.warn('WebView error:', nativeEvent);
}}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
webview: {
flex: 1,
},
});
export default VideoCallScreen;
Permissões iOS (Info.plist)
Para React Native no iOS, adicione ao ios/[SeuApp]/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Necessário para videochamadas</string>
<key>NSMicrophoneUsageDescription</key>
<string>Necessário para videochamadas</string>
Fluxo Completo
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ App Mobile │ │ Seu Backend │ │ Videochamada │
│ │ │ │ │ API │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
│ 1. Solicitar chamada │ │
│───────────────────────>│ │
│ │ │
│ │ 2. POST /api/calls │
│ │───────────────────────>│
│ │ │
│ │ 3. Retorna URL │
│ │<───────────────────────│
│ │ │
│ 4. Retorna URL │ │
│<───────────────────────│ │
│ │ │
│ 5. Abre WebView │ │
│─────────────────────────────────────────────────>
│ │ │
Troubleshooting
Câmera/Microfone não funcionam
- iOS: Verifique se as permissões estão no
Info.plist - Android: Verifique se as permissões estão no
AndroidManifest.xmle se foram solicitadas em runtime - React Native: Certifique-se de que
mediaPlaybackRequiresUserAction={false}está configurado
WebView não carrega
- Verifique se o dispositivo tem conexão com a internet
- Confirme que a URL da chamada está correta
- No Android, certifique-se de que
javaScriptEnabled={true}
Chamada não conecta
- Verifique se a chamada não expirou (
expiresAt) - Confirme que o status da chamada é
createdouactive - Teste a URL diretamente no navegador do dispositivo
Erro 401 (Unauthorized)
- Verifique se a API Key está correta
- Confirme que a API Key está ativa no painel
- Certifique-se de usar
Bearer {API_KEY}no header
Próximos Passos
- Obter Status de Chamada - Monitore o status da chamada
- Listar Participantes - Veja quem está na chamada
- Webhooks - Receba eventos em tempo real
- Encerrar Chamada - Finalize a chamada programaticamente