Flutter SDK for ART - A Realtime Tech communication — a real-time messaging platform offering WebSocket-based channels, presence tracking, encrypted communication, shared object channels.
Features
- Websocket Connection Management — connect, reconnect, and disconnect with built-in reliability
- Channel Subscription — subscribe to broadcast, targeted, group, encrypted, and shared-object channels
- Push Messages — send structured payloads to channels with optional targeted delivery
- Listen & Bind — capture every event with
listen()or react to specific events viaemitter.on() - User Presence — track online users in real time
- Encrypted Channels — end-to-end encrypted messaging
- Interceptors — pre-process or post-process messages with custom logic
- Shared Object Channels — CRDT-backed collaborative data structures
Installation
Follow the steps to set up and start using the Flutter ADK in your project.
1. Install the ADK Package
Add the ADK to your Flutter project's pubspec.yaml:
dependencies:
art_adk: ^1.0.1
Then run:
flutter pub get
2. Import the ADK into your project
Import the ADK in your Dart files to use the features provided by ART:
import 'package:art_adk/art_adk.dart';
3. Generate Client Secret
Once you have access to the ART Live Dashboard, generate the Client Secret and place the credential file at assets/adk-services.json in your project. The JSON looks like this:
{
"Client-ID": "xxxxxxxxxx",
"Client-Secret": "xxxxxxxxxxx",
"Org-Title": "YOUR_ORG",
"ProjectKey": "YOUR_PROJECT_KEY",
"Environment": "YOUR_ENV_NAME"
}
Register the asset in your pubspec.yaml:
flutter:
assets:
- assets/adk-services.json
Note: The adk-services.json file needs to be updated with your ProjectKey and Environment, manually. To learn how to obtain these values, see the Workspace and Project guide.
4. Get Passcode
Before authenticating, obtain a passcode for the user. This passcode is used as the auth token when initialising the ADK:
import 'package:art_adk/art_adk.dart';
final credentials = await AppConfigLoader.loadCredentials();
final passcode = await AuthService.connectWithPasscode(
username: 'your_username',
firstName: 'first_name',
lastName: 'last_name',
credentials: credentials,
);
See the example/ folder for reference implementations of AppConfigLoader and AuthService.
5. Authenticate
Once the client credentials are loaded and you have a passcode, initialise the ADK and connect to the server:
final updatedCreds = credentials.copyWith(accessToken: passcode);
final config = AdkConfig(
uri: 'ws.arealtimetech.com', // Replace with your ART server WebSocket URI
authToken: passcode, // Use the passcode from step 4
getCredentials: () => updatedCreds,
);
final adk = Adk(adkConfig: config);
// Listen to lifecycle events
adk.on('connection', (_) => debugPrint('Connected'));
adk.on('close', (_) => debugPrint('Disconnected'));
await adk.connect();
For short-lived workflows, wrap connect / disconnect in a try / finally:
final adk = Adk(adkConfig: config);
try {
await adk.connect();
// Your logic here
} finally {
await adk.disconnect();
}
6. Subscribe to Channel
A Channel is a communication pathway that provides passage for data transfer. Subscribing to a channel lets you use real-time messaging in your application:
final subscription = await adk.subscribe(channel: 'your-channel-name');
The return type is BaseSubscription. For shared-object (CRDT) channels, downcast to LiveObjSubscription to access the CRDT API:
if (subscription is LiveObjSubscription) {
// CRDT-enabled channel: state(), query(), flush()…
}
7. Push Messages
Messages are pushed to a channel using the push() method. This method allows you to send various event types with associated data, and optionally target specific users within the channel for more granular delivery:
// Define the message payload
final payload = <String, dynamic>{'content': 'Hello from ART ADK!'};
// Optionally define specific target users within the channel
final targetUsers = <String>['username1', 'username2'];
try {
await subscription.push(
event: 'message',
data: payload,
options: PushConfig(to: targetUsers), // target specific recipients
);
debugPrint('Message acknowledged by ART');
} catch (error) {
debugPrint('Failed to push message: $error');
}
🔒 Important: Secure and Targeted channels require exactly one recipient in PushConfig(to: [...]).
8. Listen to All Events and Messages
Bind handlers to events on the subscription's emitter. This delivers every incoming payload for the bound event type:
subscription.emitter.on('message', (dynamic data) {
debugPrint('Received: $data');
});
To listen to every event on a default channel, cast to Subscription and call listen():
if (subscription is Subscription) {
subscription.listen((Map<String, dynamic> data) {
debugPrint("Event '${data['event']}' → ${data['content']}");
});
}
User Presence
Track users online in a channel in real time:
final cancel = await subscription.fetchPresence(
callback: (List<String> users) {
debugPrint('👥 Online: $users');
},
);
// Later, when you no longer need updates:
await cancel();
Note: Enable presence tracking when creating the channel on the ART Dashboard.
Encrypted Channels
Secure channels require a KeyPair. Generate one after connecting:
await adk.generateKeyPair();
Once generated, encryption and decryption on secure channels is automatic when you push or receive messages. Secure channels require exactly one recipient per push.
final secure = await adk.subscribe(channel: 'YOUR_ENCRYPTED_CHANNEL');
await secure.push(
event: 'message',
data: <String, dynamic>{'content': 'Hello privately'},
options: PushConfig(to: <String>['recipient-username']),
);
Shared Object Channels (CRDT)
CRDT-backed channels let multiple clients edit the same data structure with automatic conflict resolution.
final sub = await adk.subscribe(channel: 'YOUR_SHARED_OBJECT_CHANNEL');
if (sub is LiveObjSubscription) {
// Write
sub.state()['document']['title'].set('My Doc');
await sub.flush();
// Observe
final query = sub.query(path: 'document');
await query.listen((dynamic data) {
debugPrint('Doc changed: $data');
});
}
Supported operations on arrays: push, unshift, pop, removeAt, splice.
Interceptors
Plug custom logic into the message pipeline:
await adk.intercept(
interceptor: 'my-interceptor',
fn: (
Map<String, dynamic> payload,
void Function(dynamic data) resolve,
void Function(String error) reject,
) {
debugPrint('Intercepted: $payload');
resolve(payload); // or reject('reason')
},
);
🔒 Important: Encrypted channel types cannot be intercepted — ART preserves complete privacy on those channels.
Connection Lifecycle
adk.on('connection', (data) {
if (data is ConnectionDetail) {
debugPrint('connectionId: ${data.connectionId}');
}
});
adk.on('close', (reason) => debugPrint('Closed: $reason'));
// Manual controls
adk.pause(); // temporarily stop
await adk.resume(); // bring back online
await adk.disconnect(); // full teardown
adk.getState() returns one of: 'connected', 'retrying', 'paused', 'stopped'.
Example Usage
It demonstrates:
- Loading credentials from an asset JSON
- Passcode authentication
- Subscribing to secure, default, and CRDT channels
- Sending targeted messages
- Live multi-user cursor positions via shared objects
- Adding and removing interceptors at runtime
Run it:
cd example
flutter run
API Reference
| Class | Purpose |
|---|---|
Adk |
Top-level SDK facade — connect, subscribe, intercept, key management |
CredentialStore |
Immutable holder for org/project/client credentials |
BaseSubscription |
Base channel subscription — push, fetchPresence, unsubscribe |
Subscription |
Default / secure channel with emitter.on() and listen() |
LiveObjSubscription |
CRDT-backed shared-object channel with state() / query() / flush() |
CRDTProxy |
Chainable CRDT state accessor (state()['a']['b'].set(...)) |
PushConfig |
Push options — to: List<String> for targeted delivery |
KeyPairType |
KeyPair for secure channels |
ConnectionDetail |
Emitted on 'connection' — contains connectionId, instanceId, etc. |
Documentation
Full documentation is available at docs.arealtimetech.com/docs/adk.
| Topic | Link |
|---|---|
| Overview | ADK Overview |
| Installation | Flutter Installation |
| Publish & Subscribe | Pub/Sub Docs |
| Connection Management | Connection Docs |
| User Presence | Presence Docs |
| Encrypted Channels | Encryption Docs |
| Shared Object Channels | Shared Object Docs |
| Interceptors | Interceptor Docs |
License
MIT License. See LICENSE for details.