Zum Inhalt springen

Erste Schritte mit RealtimeKit

Dieser Leitfaden führt Sie durch die Integration des Capacitor RealtimeKit-Plugins, um Ihrer Anwendung Videokonferenzen mit Cloudflare Calls hinzuzufügen.

Installieren Sie das Plugin mit npm:

Terminal-Fenster
npm install @capgo/capacitor-realtimekit
npx cap sync

Dieses Plugin verwendet das Cloudflare RealtimeKit SDK:

  • iOS: RealtimeKitCoreiOS (automatisch über Swift Package Manager installiert)
  • Android: com.cloudflare.realtimekit:ui-android Version 0.2.2

Im build.gradle Ihrer App:

buildscript {
ext {
realtimekitUiVersion = '0.2.2' // or your desired version
}
}

Fügen Sie Folgendes zum Info.plist Ihrer App hinzu:

<key>NSCameraUsageDescription</key>
<string>We need camera access for video calls</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need microphone access for audio calls</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need photo library access to share images</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>We need Bluetooth access for audio routing</string>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>voip</string>
<string>fetch</string>
<string>remote-notification</string>
</array>

Fügen Sie Ihrem AndroidManifest.xml die folgenden Berechtigungen hinzu:

<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.MODIFY_AUDIO_SETTINGS" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
import { CapacitorRealtimekit } from '@capgo/capacitor-realtimekit';
async function initializeRealtimeKit() {
try {
await CapacitorRealtimekit.initialize();
console.log('RealtimeKit initialized');
} catch (error) {
console.error('Failed to initialize RealtimeKit:', error);
}
}
async function startMeeting(meetingUrl: string) {
try {
await CapacitorRealtimekit.startMeeting({
url: meetingUrl
});
console.log('Meeting started');
} catch (error) {
console.error('Failed to start meeting:', error);
}
}

Hier finden Sie einen umfassenden Videokonferenzservice:

import { CapacitorRealtimekit } from '@capgo/capacitor-realtimekit';
export interface MeetingConfig {
url: string;
displayName?: string;
audioEnabled?: boolean;
videoEnabled?: boolean;
}
export class VideoConferenceService {
private isInitialized = false;
private currentMeetingUrl: string | null = null;
async initialize(): Promise<boolean> {
if (this.isInitialized) {
console.log('RealtimeKit already initialized');
return true;
}
try {
await CapacitorRealtimekit.initialize();
this.isInitialized = true;
console.log('RealtimeKit initialized successfully');
return true;
} catch (error) {
console.error('Failed to initialize RealtimeKit:', error);
return false;
}
}
async startMeeting(config: MeetingConfig): Promise<void> {
if (!this.isInitialized) {
const initialized = await this.initialize();
if (!initialized) {
throw new Error('Failed to initialize RealtimeKit');
}
}
try {
await CapacitorRealtimekit.startMeeting({
url: config.url
});
this.currentMeetingUrl = config.url;
console.log('Meeting started:', config.url);
} catch (error) {
console.error('Failed to start meeting:', error);
throw error;
}
}
async joinMeeting(meetingUrl: string, displayName?: string): Promise<void> {
const config: MeetingConfig = {
url: meetingUrl,
displayName: displayName
};
await this.startMeeting(config);
}
getCurrentMeetingUrl(): string | null {
return this.currentMeetingUrl;
}
isInMeeting(): boolean {
return this.currentMeetingUrl !== null;
}
async getPluginVersion(): Promise<string> {
try {
const result = await CapacitorRealtimekit.getPluginVersion();
return result.version;
} catch (error) {
console.error('Failed to get plugin version:', error);
return 'unknown';
}
}
}
// Usage
const videoService = new VideoConferenceService();
// Initialize on app start
await videoService.initialize();
// Start a meeting
await videoService.startMeeting({
url: 'https://your-cloudflare-calls-url.com/meeting/123'
});
// Join an existing meeting
await videoService.joinMeeting(
'https://your-cloudflare-calls-url.com/meeting/456',
'John Doe'
);

Um dieses Plugin verwenden zu können, müssen Sie Cloudflare Calls einrichten:

Melden Sie sich bei Cloudflare an, wenn Sie noch kein Konto haben.

  1. Navigieren Sie zu Ihrem Cloudflare-Dashboard
  2. Gehen Sie zum Abschnitt Anrufe
  3. Aktivieren Sie die Anrufe API
  4. Holen Sie sich Ihre API-Anmeldeinformationen

Sie benötigen einen Backend-Dienst, um Besprechungs-URLs zu erstellen. Beispiel mit Cloudflare Workers:

// Cloudflare Worker example
export default {
async fetch(request: Request): Promise<Response> {
const { pathname } = new URL(request.url);
if (pathname === '/create-meeting') {
const meetingId = generateMeetingId();
const meetingUrl = `https://your-app.calls.cloudflare.com/${meetingId}`;
return new Response(JSON.stringify({
meetingId,
meetingUrl
}), {
headers: { 'Content-Type': 'application/json' }
});
}
return new Response('Not found', { status: 404 });
}
};
function generateMeetingId(): string {
return Math.random().toString(36).substring(2, 15);
}

Treffen mit benutzerdefinierter Konfiguration

Section titled “Treffen mit benutzerdefinierter Konfiguration”
class MeetingManager {
private videoService: VideoConferenceService;
constructor() {
this.videoService = new VideoConferenceService();
}
async createAndJoinMeeting(userName: string): Promise<string> {
// Initialize if needed
await this.videoService.initialize();
// Call your backend to create a meeting
const meetingUrl = await this.createMeetingOnBackend();
// Join the meeting
await this.videoService.joinMeeting(meetingUrl, userName);
return meetingUrl;
}
async createMeetingOnBackend(): Promise<string> {
const response = await fetch('https://your-api.com/create-meeting', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const data = await response.json();
return data.meetingUrl;
}
async shareMeetingLink(meetingUrl: string) {
// Use Capacitor Share API
if ('share' in navigator) {
await (navigator as any).share({
title: 'Join my meeting',
text: 'Join me for a video call',
url: meetingUrl
});
}
}
}
import { Capacitor } from '@capacitor/core';
async function checkAndRequestPermissions(): Promise<boolean> {
if (Capacitor.getPlatform() === 'web') {
// Request browser permissions
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true
});
// Stop the stream, we just needed permission
stream.getTracks().forEach(track => track.stop());
return true;
} catch (error) {
console.error('Permission denied:', error);
return false;
}
}
// On native platforms, permissions are requested automatically
return true;
}
// Use before starting a meeting
const hasPermissions = await checkAndRequestPermissions();
if (hasPermissions) {
await videoService.startMeeting({ url: meetingUrl });
}
import { useEffect, useState } from 'react';
import { VideoConferenceService } from './VideoConferenceService';
function VideoCallComponent() {
const [videoService] = useState(() => new VideoConferenceService());
const [isReady, setIsReady] = useState(false);
useEffect(() => {
videoService.initialize().then(setIsReady);
}, []);
const joinMeeting = async (meetingUrl: string) => {
if (!isReady) {
console.error('Video service not ready');
return;
}
try {
await videoService.joinMeeting(meetingUrl, 'User Name');
} catch (error) {
console.error('Failed to join meeting:', error);
}
};
return (
<div>
<button
onClick={() => joinMeeting('https://your-meeting-url')}
disabled={!isReady}
>
Join Meeting
</button>
</div>
);
}
import { ref, onMounted } from 'vue';
import { VideoConferenceService } from './VideoConferenceService';
export default {
setup() {
const videoService = new VideoConferenceService();
const isReady = ref(false);
onMounted(async () => {
isReady.value = await videoService.initialize();
});
const joinMeeting = async (meetingUrl: string) => {
if (!isReady.value) {
console.error('Video service not ready');
return;
}
try {
await videoService.joinMeeting(meetingUrl, 'User Name');
} catch (error) {
console.error('Failed to join meeting:', error);
}
};
return {
isReady,
joinMeeting
};
}
};
  1. Frühzeitig initialisieren: Initialisieren Sie RealtimeKit, wenn Ihre App startet
  2. Behandeln von Fehlern: Wickeln Sie Aufrufe immer in Try-Catch-Blöcke ein
  3. Berechtigungen anfordern: Stellen Sie vor dem Start sicher, dass Sie über Kamera-/Mikrofonberechtigungen verfügen
  4. Netzwerk testen: Überprüfen Sie die Internetverbindung, bevor Sie beitreten
  5. Hintergrundaudio: Hintergrundmodi für iOS konfigurieren
  6. Benutzererfahrung: Ladezustände während der Initialisierung anzeigen
  7. URLs bereinigen: Überprüfen Sie Besprechungs-URLs vor der Verwendung
async function troubleshootMeeting(meetingUrl: string) {
// Check initialization
const version = await videoService.getPluginVersion();
console.log('Plugin version:', version);
// Verify URL format
if (!meetingUrl.startsWith('https://')) {
console.error('Invalid meeting URL, must use HTTPS');
return;
}
// Try starting meeting
try {
await videoService.startMeeting({ url: meetingUrl });
} catch (error) {
console.error('Meeting failed:', error);
}
}

Stellen Sie unter iOS sicher, dass Info.plist alle erforderlichen Nutzungsbeschreibungen enthält. Überprüfen Sie auf Android, ob AndroidManifest.xml-Berechtigungen vorhanden sind.

Stellen Sie sicher, dass der Hintergrund-Audiomodus in Info.plist konfiguriert ist:

<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>voip</string>
</array>