Outgoing iOS screen-share via ReplayKit broadcast extension
Lets a native-call user share their iPhone screen (whole device, works backgrounded). LiveKit 2.15.3 ships the broadcast stack (BroadcastManager + LKSampleHandler + IPC), so: - New Broadcast Upload Extension target "BroadcastExtension" (com.bizgaze.connect.broadcast): SampleHandler.swift subclasses LKSampleHandler; injected by mobile/scripts/add-broadcast-extension.rb which also LINKS the LiveKit SPM product into the extension + sets the App Group. Sources in mobile/ios-broadcast/. - Plugin: Room created with ScreenShareCaptureOptions(useBroadcastExtension: true); startScreenShare -> BroadcastManager.requestActivation() (system picker); stopScreenShare -> requestStop(); BroadcastManagerDelegate -> fires screenShareState to the web. LiveKit auto-publishes the track. - ios-patch.sh: RTCScreenSharingExtension + RTCAppGroupIdentifier keys. - codemagic.yaml: run the injector + sign the 3rd bundle id (.broadcast). - home.html: toggleScreen native -> start/stop; screenShareState listener reflects state + broadcasts meeting-screen so peers' stage shows it. REQUIRES a one-time manual Apple portal step: enable the App Group on the com.bizgaze.connect.broadcast App ID (see mobile/IOS_SETUP.md) or the archive fails code-signing. SPM-linked extension is new on our CI — expect build iteration. Web deployed (no-ops on builds without startScreenShare). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3879,6 +3879,8 @@ async function setupNativeCall(){
|
||||
NC.addListener('callError', (e)=>{ console.warn('[callkit] call error:', (e&&e.error)||''); });
|
||||
// Muted from the CallKit system UI → reflect it in the meeting window's mic button.
|
||||
NC.addListener('setMuted', (e)=>{ if(!e||meetState!=='call'||!meetNative) return; meetMic=!e.muted; try{ updateMicBtn(); setTileMute('__local', !meetMic); meetSend({type:'meeting-state', muted:!meetMic, camOff:!meetCam}); }catch(_){} });
|
||||
// Screen share (ReplayKit) started/stopped from the system — reflect it and tell peers so their stage shows it.
|
||||
NC.addListener('screenShareState', (e)=>{ if(meetState!=='call'||!meetNative) return; const on=!!(e&&e.sharing); meetScreen=on; try{ updateScreenBtn(); setLocalSharing(on); meetSend({type:'meeting-screen', on}); }catch(_){} });
|
||||
// Ended on the CallKit system screen / plugin ended on remote hang-up. Leave the meeting window too (guarded
|
||||
// so our own in-app hang-up, which already called the plugin, doesn't loop). Then tell the server.
|
||||
NC.addListener('endCall', (d)=>{ try{
|
||||
@@ -5226,7 +5228,12 @@ function meetMakePeer(peerId, name){
|
||||
// (no extra tiles, the peer's video just shows the screen). Falls back to addTrack+renegotiate if
|
||||
// no video sender exists yet (camera never turned on). Stopping restores the camera (or avatar).
|
||||
async function toggleScreen(){
|
||||
if(meetNative){ toast('Sharing your screen from iPhone isn’t supported yet — but you’ll see others’ shared screens.'); return; } // iOS has no getDisplayMedia / ReplayKit ext wired
|
||||
if(meetNative){ // native call: the plugin shares the whole phone screen via the ReplayKit broadcast extension
|
||||
const NC=nativeCallPlugin();
|
||||
if(!NC||!NC.startScreenShare){ toast('Update the app to share your screen'); return; }
|
||||
try{ if(meetScreen) await NC.stopScreenShare(); else await NC.startScreenShare(); }catch(_){}
|
||||
return; // meetScreen + the button flip happen on the authoritative screenShareState event
|
||||
}
|
||||
if(meetScreen){ stopScreen(); return; }
|
||||
if(!meetMultiShare && meetSharers.size>0){ toast('Someone is already sharing their screen'); return; }
|
||||
if(SFU.on){
|
||||
|
||||
Reference in New Issue
Block a user