Native Android RTC integration
The native Android SDK uses device WebRTC capture and rendering. Your Activity owns layout, controls, and OS permission prompts. The SDK owns the room, media, and state. Start with a viewer ticket for receive-only, then issue publishing capabilities to approved members.
flowchart LR
A["Activity creates SDK"] --> B["joinWithAccessTicket"]
B --> C["onJoined / onError"]
C --> D["Bind remote track to Renderer"]
D --> E["leave → close"]
Keep matching dependencies
Use the delivered AAR or source :sdk module and retain its matching WebRTC, OkHttp, and native dependencies. Copying only the AAR or adding a different WebRTC release may break builds or runtime media. The current SDK requires Android API 26 or later. Declare camera and microphone permissions in the Manifest and request them at runtime only when needed.
If integrating a delivered AAR, add matching external dependencies to Gradle. The current source uses:
dependencies {
implementation(files("libs/AKStreamRtcSDK.aar"))
implementation("io.github.webrtc-sdk:android:144.7559.09")
implementation("com.squareup.okhttp3:okhttp:5.3.0")
}
The source :sdk module declares these itself. If a later delivery upgrades them, use that AAR's dependency list rather than treating these values as permanent.
Create a client from an Activity:
TransformSurfaceViewRenderer localView = new TransformSurfaceViewRenderer(this);
AkNativeRtcClient client = new AkNativeRtcClient(this, localView, listener);
client.setInitialMediaEnabled(false, false);
client.joinWithAccessTicket(serverUrl, roomId, accessTicket, passcode);
Here listener implements AkNativeRtcClient.Listener; join data comes from your backend. Returning from this method means joining started, not that it succeeded. Use onJoined, onError, and actual media callbacks to decide. The SDK initializes its local renderer, so the host must not call init() again.
At minimum handle onJoined, onRemoteVideo, onRemoteVideoRemoved, onError, and onLeft; use onLocalMediaState and onMediaPermissionChanged for controls. These callbacks may be off the UI thread, so update Android views on the main thread. Prove that remote frames and audio really arrive before enabling local publishing.
| Callback/result | What the Activity does | What it does not prove |
|---|---|---|
onJoined(participantId) |
Save member identity and show the room | Remote media has already arrived |
onRemoteVideo(publicationId, track) |
Create a Renderer and bind this track | All publications from a same-name member share one view |
onLocalMediaState(mic,camera) |
Update actual microphone/camera controls | A button click itself succeeded |
onMediaPermissionChanged(kind,allowed) |
Explain host restrictions and block invalid actions | Unmuting a restriction turns the device on automatically |
onContinuousRecordingChanged(recording) |
Show current run or no active run | Stopping means files are ready to download |
onHttpError(error) |
Preserve status; refresh tickets on real 401, show permission on 403 | Old tickets should be retried forever |
Views, audio, and lifecycle
When onRemoteVideo(publicationId, VideoTrack) arrives, create and bind one renderer for that publication. onRemoteVideoRemoved removes only that publication. Select microphones, cameras, and audio routes by the real IDs returned by the SDK, then use state callbacks to confirm the result.
Screen sharing requires MediaProjection and a foreground service. Forward Activity lifecycle and permission results according to the SDK controller. Retain the meeting while another Activity opens for attachment selection. Call leave() for a normal departure and close() when disposing the client; removing only video views is not enough.
After background recovery, check member presence, local sent frames, and remote decoded frames independently. Some Android devices restrict background camera or microphone capture. A foreground service or floating preview does not prove media is still sending. Ask a second device to verify video and sound and capture send/receive stats if needed.
onContinuousRecordingChanged reports recording state. The host can call startContinuousRecording(RoomCallback) or stopContinuousRecording(recordingId, RoomCallback) when authorized; ordinary members may call getContinuousRecording(RoomCallback). The SDK supplies data, while the host draws recording and replay controls. These interfaces are in the the matching version delivery source/package; an old APK is not updated automatically. See Android methods for inputs, callbacks, and edge cases.
Match exact dependency versions and permissions to the delivered Android SDK README and AAR. Install on a real device and follow the acceptance checklist.
If the app reconnects forever, first check that its server URL is reachable HTTPS from the phone, rather than the development computer's 127.0.0.1. Then check certificate, room ticket, WebSocket, and media ports separately. An OS-canceled install means the phone still has the old build; do not attribute its behavior to the updated SDK.