Fishjam React Native Client
@fishjam-cloud/react-native-client — Fishjam's SDK for React Native / Expo apps on iOS and Android. Re-exports the web @fishjam-cloud/react-client hook surface, overrides some hooks with mobile-aware versions, and adds mobile-only APIs.
Read
../platform/SKILL.mdfirst for the domain model.Read
../react-client/SKILL.mdfor the shared hook catalog. This skill is the mobile delta — permissions, foreground service, screen-share broadcast extension, CallKit, audio routing, the Expo plugin. The hooks that work identically to the web SDK aren't re-documented here.
Minimal app
bashnpm install @fishjam-cloud/react-native-client @fishjam-cloud/react-native-webrtc # @fishjam-cloud/react-native-webrtc is a peerDependency — install it explicitly. # Do NOT install upstream `react-native-webrtc` (the unforked package) — it will collide.
app.json (Expo):
json{ "expo": { "plugins": [ [ "@fishjam-cloud/react-native-client", { "android": { "enableForegroundService": true, "enableScreensharing": true }, "ios": { "enableScreensharing": true, "broadcastExtensionTargetName": "MyAppScreenSharing", "broadcastExtensionDisplayName": "MyApp Screen Sharing", "appGroupContainerId": "group.com.myapp.screensharing", "mainTargetName": "MyApp" } } ] ] } }
Then npx expo prebuild to generate native code.
tsximport { FishjamProvider } from '@fishjam-cloud/react-native-client'; export default function App() { return ( <FishjamProvider fishjamId={process.env.EXPO_PUBLIC_FISHJAM_ID!}> <Room /> </FishjamProvider> ); }
Hook delta vs web (../react-client/)
Re-exported unchanged
These hooks behave identically to the web SDK — see ../react-client/ references.
useConnection, useDataChannel, useSandbox, useUpdatePeerMetadata, useVAD, Variant, InitializeDevicesSettings.
useSandboxRoomTypedivergence. The web SDK accepts'audio_only'(underscore); the React Native SDK accepts'audio-only'(hyphen). Passing the wrong form on either platform makes the Sandbox API reject the request. (Web wire format isaudio_only; the RN hook silently sends'audio-only'and the server validation 400s.)
Overridden (mobile-specific implementations of same API)
Same call signatures as web; internals adapted to React Native. Read ../react-client/ references for the API, then this skill's mobile-hook-overrides.md for behavioral deltas.
useCamera, useMicrophone, useScreenShare, useCustomSource, useInitializeDevices, useLivestreamStreamer, useLivestreamViewer, usePeers.
Mobile-only (no web equivalent)
| Hook / API | Purpose | Reference |
|---|---|---|
useCameraPermissions, useMicrophonePermissions | Query / request iOS-Android device permissions | permissions.md |
useForegroundService | Keep audio/video/screen-share alive when the app is backgrounded on Android | foreground-service.md |
useCallKit, useCallKitEvent, useCallKitService | iOS CallKit integration (treats Fishjam sessions as native phone calls) | callkit.md |
useAudioOutput + AudioDeviceType | Switch audio routing (speaker / earpiece / Bluetooth) | audio-output.md |
RTCView, RTCPIPView | Native components for rendering video tracks (in place of <video>) | rtcview.md |
ScreenCapturePickerView + startPIP / stopPIP | Native components / functions for iOS screen picker and Picture-in-Picture | screen-sharing.md, picture-in-picture.md |
FishjamProvider differences
The mobile provider is a thin wrapper around the React one but drops two props:
persistLastDevice— not supported on mobile (nolocalStorage; OS manages device selection).fishjamClient— internal-only on mobile (the SDK constructs its own withclientType: 'mobile').
All other props (fishjamId, reconnect, constraints, bandwidthLimits, videoConfig, audioConfig, debug) work the same as web.
Key rules
- Install
@fishjam-cloud/react-native-webrtc(the fork) — but NOT the upstreamreact-native-webrtc. The fork is apeerDependencyof@fishjam-cloud/react-native-client, so you must add it explicitly. Installing the upstream (unforked)react-native-webrtcwill collide with the fork and break the native build. - The Expo plugin is required even in bare workflow. For Expo CNG (managed): register in
app.json/app.config.ts. For bare: still register and runnpx expo prebuild, or do the manual native steps (native-setup.md). - Request permissions before
useInitializeDevices. iOS in particular will silently fail device init ifNSCameraUsageDescription/NSMicrophoneUsageDescriptionisn't declared and granted. - Foreground service is mandatory for backgrounded streaming on Android. When the user puts the app in background, Android suspends the WebRTC peer connection unless a foreground service is running.
useForegroundServicesolves this. - iOS screen sharing requires a Broadcast Extension. A separate iOS target generated by the Expo plugin. Configure
broadcastExtensionTargetName+appGroupContainerIdand the plugin scaffolds it duringprebuild. - iOS PIP needs the plugin flag.
ios.supportsPictureInPicture: trueandenableVoIPBackgroundMode: truefor CallKit-paired calls.
References
| File | When to read |
|---|---|
native-setup.md | Install + Expo plugin options (Android + iOS), bare workflow manual steps, prebuild flow. |
permissions.md | useCameraPermissions, useMicrophonePermissions, request-before-init pattern. |
rtcview.md | Rendering video — RTCView props (streamURL, trackId, mediaStream), RTCPIPView, mirror / styling. |
screen-sharing.md | Android MediaProjection vs iOS Broadcast Extension; ScreenCapturePickerView; app-group pitfalls. |
foreground-service.md | ForegroundServiceConfig, Android permissions, iOS background modes. |
picture-in-picture.md | RTCPIPView, startPIP, stopPIP, plugin flags. |
callkit.md | useCallKit, useCallKitEvent, useCallKitService, CallKitConfig, CallKitAction. |
audio-output.md | useAudioOutput, AudioDeviceType, switching speaker / earpiece / Bluetooth. |
mobile-hook-overrides.md | Per-hook behavioral deltas vs the web SDK. |
example-projects.md | Runnable apps in the fishjam-cloud/examples repo under mobile-react-native/. |


