Documentation

    Full Device Screen Sharing

    By default, the Co-Browsing API Flutter SDK shares only your app's screen. With full device screen sharing, agents can see the entire device screen, including other apps, the home screen, and system UI.

    On iOS this uses Apple's Broadcast Upload Extension (ReplayKit); on Android it uses the MediaProjection API. Both need a little native setup, described below.

    Physical devices only
    Full device screen sharing only works on physical devices. It is not supported on the iOS Simulator or Android emulators.

    Full device screen sharing must also be enabled in the Co-Browsing API dashboard (admin interface) in addition to the steps below.

    iOS setup

    Full device capture on iOS runs in a Broadcast Upload Extension — a separate native target in your app's Xcode project (under ios/). It sends frames to your app through an App Group, and the SDK relays them to the agent.

    1. Add the extension dependency

    In your app's ios/Podfile, add the broadcast subspec to the extension target. Do not pin a version — it follows the UpscopeSDK version that upscopeio_flutter_sdk already requires:

    target 'YourAppBroadcast' do
      pod 'UpscopeSDK/BroadcastExtension'
    end
    

    Then run pod install from the ios/ directory.

    2. Create the Broadcast Upload Extension target

    1. Open ios/Runner.xcworkspace in Xcode
    2. Go to File > New > Target
    3. Select Broadcast Upload Extension
    4. Uncheck "Include UI Extension"
    5. Name it (e.g., YourAppBroadcast — match the target name used in the Podfile above)
    6. The bundle identifier must be prefixed with your main app's bundle identifier (e.g., com.yourcompany.yourapp.broadcast)

    3. Configure App Groups

    Both your main app (the Runner target) and the extension need to share data through an App Group:

    1. Select the Runner target > Signing & Capabilities > + Capability > App Groups
    2. Add a group identifier (e.g., group.com.yourcompany.yourapp)
    3. Select your extension target > Signing & Capabilities > + Capability > App Groups
    4. Add the same group identifier

    4. Configure the extension's Info.plist

    Add the App Group identifier to the extension's Info.plist:

    <key>UpscopeAppGroupId</key>
    <string>group.com.yourcompany.yourapp</string>
    

    5. Implement the extension

    Replace the contents of the extension's SampleHandler.swift with:

    import UpscopeBroadcastExtension
    
    class SampleHandler: UpscopeSampleHandler {}
    

    All frame capture and forwarding is handled by UpscopeSampleHandler.

    6. Configure the SDK

    Pass the App Group and extension bundle identifiers when initializing the SDK:

    import 'package:upscopeio_flutter_sdk/upscopeio_flutter_sdk.dart';
    
    await Upscope.instance.initialize(
      UpscopeConfiguration(
        apiKey: 'YOUR_API_KEY',
        broadcastAppGroupId: 'group.com.yourcompany.yourapp',
        broadcastExtensionBundleId: 'com.yourcompany.yourapp.broadcast',
      ),
    );
    

    If you do not set broadcastAppGroupId, the SDK will not advertise full device support on iOS, and agent requests for it are declined automatically.

    Android setup

    Add the screen-capture permissions to android/app/src/main/AndroidManifest.xml:

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
    

    The SDK already declares the capture service and activity. It detects these permissions at runtime — if they are missing, full device screen sharing is disabled regardless of the dashboard setting. No further configuration is required; Android shows the system screen-capture permission dialog when sharing starts.

    Responding to full device requests

    Unlike the native iOS SDK (which can present the system picker automatically), the Flutter SDK always routes full device requests to your Dart code. You must listen on onFullDeviceRequest and respond, or requests will never proceed:

    final requestSub = Upscope.instance.onFullDeviceRequest.listen((requestId) {
      // Optionally show your own confirmation UI here, then respond:
      Upscope.instance.respondToFullDeviceRequest(requestId, true); // false to decline
    });
    
    final stateSub = Upscope.instance.fullDeviceSharingStateStream.listen((state) {
      debugPrint('Full device sharing: $state'); // FullDeviceSharingState.active / .inactive
    });
    
    // Cancel both subscriptions in dispose().
    

    After you accept, iOS shows the system broadcast picker (the user taps Start Broadcast) and Android shows the screen-capture dialog (the user taps Start now). End sharing programmatically at any time:

    Upscope.instance.stopFullDeviceSharing();
    

    The user can also stop sharing from iOS Control Center or the Android capture notification; the SDK reports this via fullDeviceSharingStateStream.

    Limitations

    • Works on physical devices only (not the iOS Simulator or Android emulators)
    • Element masking is not available in full device mode (the SDK cannot inspect views outside your app)
    • Remote control only works within your app, not on the home screen or other apps
    • Drawing annotations are not displayed in full device mode
    • The user must explicitly start the broadcast/capture via the system prompt — it cannot be started programmatically