upscopeio_flutter_sdk 2026.4.9
upscopeio_flutter_sdk: ^2026.4.9 copied to clipboard
Flutter SDK for Upscope cobrowsing — screen sharing, annotations, and remote control
Upscope Flutter SDK #
Flutter plugin for Upscope cobrowsing — lets support agents view and interact with your users' screens in real-time, with no extra permissions required.
Requirements #
- Flutter 3.19+
- Dart SDK 3.3+
- iOS 14.0+
- Android API 26+ (Android 8.0)
Installation #
flutter pub add upscopeio_flutter_sdk
Or add it manually to your pubspec.yaml:
dependencies:
upscopeio_flutter_sdk: ^2026.4.8
Then run:
flutter pub get
Quick Start #
1. Initialize #
Call initialize once, early in your app lifecycle (e.g. in main or your root widget's initState):
import 'package:upscopeio_flutter_sdk/upscopeio_flutter_sdk.dart';
await Upscope.instance.initialize(
UpscopeConfiguration(apiKey: 'your_api_key'),
);
By default autoConnect: true, so the SDK connects immediately after initialization.
2. Identify the visitor #
await Upscope.instance.updateConnection(
uniqueId: 'user-123',
callName: 'Jane Smith',
tags: ['premium', 'mobile'],
);
Call this any time visitor identity changes (e.g. after sign-in).
3. Show a lookup code to the user #
The lookup code lets a support agent start a session by entering a short code in the Upscope dashboard:
Upscope.instance.lookupCode.listen((code) {
if (code != null) {
print('Share this code with support: $code');
}
});
That's all. The agent can now initiate a cobrowsing session from the dashboard.
Core Concepts #
Connection vs. Session #
- Connection — persistent WebSocket link to Upscope servers. Established via
connect(), torn down viadisconnect(). Required before any session can start. - Session — an active cobrowsing window with an agent. Begins when an agent joins (or when
requestAgent()is called), ends when either party stops it.
Reactive streams #
All state is exposed as Streams so you can drive your UI reactively without polling.
// Show connection status in a StreamBuilder
StreamBuilder<ConnectionState>(
stream: Upscope.instance.connectionState,
builder: (context, snapshot) {
return Text(switch (snapshot.data) {
ConnectionState.connected => 'Ready',
ConnectionState.connecting => 'Connecting…',
ConnectionState.reconnecting => 'Reconnecting…',
ConnectionState.error => 'Error',
_ => 'Offline',
});
},
);
Masking sensitive widgets #
Wrap any widget in UpscopeMasked to hide it from the agent's view. The region is replaced with a black rectangle in the screen capture; your users see the real content as normal.
UpscopeMasked(
child: CreditCardField(),
)
UpscopeMasked tracks position automatically — it handles layout changes, device rotation, and scroll without any extra wiring.
Common Tasks #
Listen for session lifecycle events #
Upscope.instance.onSessionStarted.listen((_) {
showBanner('Screen sharing started');
});
Upscope.instance.onSessionEnded.listen((reason) {
showBanner('Session ended: $reason');
});
React to observer changes #
Upscope.instance.onObserverJoined.listen((observer) {
print('Agent joined: ${observer.name}');
});
Upscope.instance.onObserverCountChanged.listen((count) {
print('Observers watching: $count');
});
Request an agent #
Proactively ask for a support agent without waiting for them to initiate:
await Upscope.instance.requestAgent();
// Cancel if the user changes their mind
await Upscope.instance.cancelAgentRequest();
Stop a session #
await Upscope.instance.stopSession();
Send a custom message to the agent #
await Upscope.instance.sendCustomMessage('{"event": "checkout_started"}');
Receive messages from the agent:
Upscope.instance.onCustomMessageReceived.listen((msg) {
print('From ${msg.observerId}: ${msg.message}');
});
Reset the connection #
Clears stored identity and reconnects (useful on sign-out):
// Reset and reconnect
await Upscope.instance.reset();
// Reset without reconnecting
await Upscope.instance.reset(reconnect: false);
Handle errors #
Upscope.instance.onError.listen((error) {
print('Upscope error [${error.code}]: ${error.message}');
});
Configuration Reference #
All options are set once in UpscopeConfiguration passed to initialize:
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
String |
required | Your Upscope API key |
autoConnect |
bool |
true |
Connect automatically on initialize |
requireAuthorizationForSession |
bool |
true |
Prompt user before allowing agent to view screen |
authorizationPromptTitle |
String |
'Screen Sharing Request' |
Title of the consent dialog |
authorizationPromptMessage |
String |
'An agent wants to view your screen. Do you accept?' |
Body of the consent dialog |
showBanner |
bool |
true |
Show an in-app banner while a session is active |
showTerminateButton |
bool |
true |
Show a stop-sharing button in the banner |
stopSessionText |
String |
'Stop Sharing' |
Label on the stop-sharing button |
endOfSessionMessage |
String? |
null |
Message shown to the user when the session ends |
allowRemoteClick |
bool? |
null |
Override server-side remote click permission |
allowRemoteScroll |
bool? |
null |
Override server-side remote scroll permission |
requireControlRequest |
bool? |
null |
Require explicit user approval before agent can interact |
region |
String? |
null |
Force a specific Upscope server region |
API Reference #
Upscope.instance — methods #
| Method | Returns | Description |
|---|---|---|
initialize(UpscopeConfiguration) |
Future<void> |
Initialize and optionally auto-connect |
connect() |
Future<void> |
Connect to Upscope servers |
disconnect() |
Future<void> |
Disconnect from Upscope servers |
reset({bool reconnect}) |
Future<void> |
Clear identity and optionally reconnect |
updateConnection({uniqueId, callName, tags, identities, metadata}) |
Future<void> |
Update visitor identity |
stopSession() |
Future<void> |
End the current cobrowsing session |
requestAgent() |
Future<void> |
Request a support agent |
cancelAgentRequest() |
Future<void> |
Cancel a pending agent request |
getLookupCode() |
Future<void> |
Trigger a lookup code refresh |
getShortId() |
Future<String?> |
Get the persistent visitor short ID |
getWatchLink() |
Future<String?> |
Get a direct watch link for the current session |
sendCustomMessage(String) |
Future<void> |
Send a custom string to all connected agents |
Upscope.instance — streams #
| Stream | Type | Emits |
|---|---|---|
connectionState |
Stream<ConnectionState> |
Connection state changes |
sessionState |
Stream<SessionState> |
Session state changes |
lookupCode |
Stream<String?> |
Current lookup code (refreshes periodically) |
shortId |
Stream<String?> |
Persistent visitor short ID |
onSessionStarted |
Stream<String?> |
Session ID when a session begins |
onSessionEnded |
Stream<SessionEndReason> |
Reason the session ended |
onObserverJoined |
Stream<Observer> |
Agent joined the session |
onObserverLeft |
Stream<String> |
Agent ID when an agent leaves |
onObserverCountChanged |
Stream<int> |
Current number of watching agents |
onCustomMessageReceived |
Stream<CustomMessage> |
Custom message from an agent |
onError |
Stream<UpscopeError> |
SDK-level errors |
Enums #
ConnectionState — inactive, connecting, connected, reconnecting, error
SessionState — inactive, pendingRequest, active, paused, ended
SessionEndReason — userStopped, agentStopped, timeout, error
Widgets #
UpscopeMasked({required Widget child}) — Wraps a child and masks its screen region during cobrowsing. Handles position tracking, rotation, and scroll automatically. No configuration needed.
Troubleshooting #
Sessions never start / connection stays inactive
- Confirm
autoConnect: true(default) or that you calledconnect()explicitly. - Verify the API key is correct for your Upscope account.
- Check that the device has internet access.
Streams receive no events
- Subscribe to streams before calling
initialize, or use aStreamControllerwithsync: falseto avoid missing the first emission.
Masked widget position is wrong after navigation
UpscopeMaskedtracks metrics changes and scroll, but not route transitions. If you push/pop routes while a masked widget is off-screen, the rect will be corrected on the next frame when the widget is visible again. This is typically transparent to the agent.
iOS build fails with missing plugin
- Ensure you have run
pod install(orflutter pub getwhich runs it for you). - The plugin class is
UpscopePluginregistered under theio.upscope.flutternamespace.
Android build fails
- Minimum supported API is 26. Check
minSdkin your app-levelbuild.gradle.
Support #
- Documentation: Flutter Docs
- Email: team@upscope.io
License #
Proprietary. See your agreement with Upscope for details.