Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Synheart Behavior Flutter SDK provides real-time behavioral signal inference from digital interactions for cross-platform mobile applications.

Installation

Add to pubspec.yaml:
dependencies:
  synheart_behavior: ^0.2.1
Install:
flutter pub get

Requirements

  • Flutter >= 3.10.0
  • Dart >= 3.0.0

Quick Start

Basic Usage

import 'package:synheart_behavior/synheart_behavior.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize SDK
  final behavior = await SynheartBehavior.initialize(
    config: const BehaviorConfig(
      enableInputSignals: true,
      enableAttentionSignals: true,
      enableMotionLite: true, // Enable motion state inference (LAYING, MOVING, SITTING, STANDING)
    ),
  );

  runApp(MyApp(behavior: behavior));
}

class MyApp extends StatelessWidget {
  final SynheartBehavior behavior;

  const MyApp({super.key, required this.behavior});

  @override
  Widget build(BuildContext context) {
    return behavior.wrapWithGestureDetector(
      MaterialApp(
        title: 'My App',
        home: HomePage(behavior: behavior),
      ),
    );
  }
}

Real-Time Event Tracking

// Listen to real-time events
behavior.onEvent.listen((event) {
  print('Event: ${event.eventType} at ${event.timestamp}');
  print('Metrics: ${event.metrics}');

  // Handle different event types
  switch (event.eventType) {
    case BehaviorEventType.scroll:
      final velocity = event.metrics['velocity'] as double?;
      print('Scroll velocity: $velocity px/s');
      break;
    case BehaviorEventType.tap:
      final duration = event.metrics['tap_duration_ms'] as int?;
      print('Tap duration: $duration ms');
      break;
    case BehaviorEventType.swipe:
      final direction = event.metrics['direction'] as String?;
      print('Swipe direction: $direction');
      break;
    case BehaviorEventType.typing:
      final speed = event.metrics['typing_speed'] as double?;
      final tapCount = event.metrics['typing_tap_count'] as int?;
      print('Typing speed: $speed, tap count: $tapCount');
      break;
    default:
      break;
  }
});

Session Management

// Start a session
final session = await behavior.startSession();
print('Session started: ${session.sessionId}');

// ... user interacts with app ...

// End session and get summary
final summary = await session.end();
print('Session duration: ${summary.durationMs}ms');
print('Total events: ${summary.activitySummary.totalEvents}');
print('Focus hint: ${summary.behavioralMetrics.focusHint}');
print('Distraction score: ${summary.behavioralMetrics.distractionScore}');

On-Demand Metrics Calculation

Calculate behavioral metrics for a custom time range within a session:
// Calculate metrics for a specific time range
final metrics = await behavior.calculateMetricsForTimeRange(
  startTimestampSeconds: 1767688063,  // Unix timestamp in seconds
  endTimestampSeconds: 1767688130,     // Unix timestamp in seconds
  sessionId: 'SESS-1767688063415',     // Optional: uses current session if not provided
);

// Access the calculated metrics
print('Total events: ${metrics['activity_summary']['total_events']}');
print('App switches: ${metrics['activity_summary']['app_switch_count']}');
print('Interaction intensity: ${metrics['behavioral_metrics']['interaction_intensity']}');
print('Distraction score: ${metrics['behavioral_metrics']['behavioral_distraction_score']}');
print('Focus hint: ${metrics['behavioral_metrics']['focus_hint']}');

// Motion state (if motion data is available)
if (metrics['motion_state'] != null) {
  print('Motion state: ${metrics['motion_state']['major_state']}');
  print('Confidence: ${metrics['motion_state']['confidence']}');
}

// Device context
print('Screen brightness: ${metrics['device_context']['avg_screen_brightness']}');
print('Orientation: ${metrics['device_context']['start_orientation']}');

// System state
print('Internet: ${metrics['system_state']['internet_state']}');
print('Do not disturb: ${metrics['system_state']['do_not_disturb']}');
Note: The time range must be within the session’s start and end times. The SDK automatically validates this and will throw an error if the range is out of bounds.

API Reference

SynheartBehavior

Main Methods:
MethodDescriptionReturns
initialize({config})Initialize SDKFuture<SynheartBehavior>
wrapWithGestureDetector(widget)Wrap app to enable gesture trackingWidget
startSession({sessionId})Start a new sessionFuture<BehaviorSession>
calculateMetricsForTimeRange(...)Calculate metrics for custom time rangeFuture<Map<String, dynamic>>
getCurrentStats()Get current statisticsFuture<BehaviorStats>
onEventStream of behavioral eventsStream<BehaviorEvent>
dispose()Clean up resourcesvoid

calculateMetricsForTimeRange()

Calculate behavioral metrics for a custom time range within a session. Parameters:
ParameterTypeRequiredDescription
startTimestampSecondsintYesStart time as Unix timestamp in seconds
endTimestampSecondsintYesEnd time as Unix timestamp in seconds
sessionIdString?NoSession ID (uses current session if not provided)
Returns: Future<Map<String, dynamic>> - Map containing all behavioral metrics for the specified time range Throws: Exception if time range is out of session bounds or session not found Example:
final metrics = await behavior.calculateMetricsForTimeRange(
  startTimestampSeconds: DateTime.now().subtract(Duration(minutes: 5)).millisecondsSinceEpoch ~/ 1000,
  endTimestampSeconds: DateTime.now().millisecondsSinceEpoch ~/ 1000,
);

// Access metrics
final totalEvents = metrics['activity_summary']['total_events'] as int;
final intensity = metrics['behavioral_metrics']['interaction_intensity'] as double;
Properties:
PropertyTypeDescription
isInitializedboolWhether SDK is initialized
currentSessionIdString?Current active session ID

BehaviorConfig

Parameters:
ParameterTypeDefaultDescription
enableInputSignalsbooltrueEnable scroll, tap, swipe, typing tracking
enableAttentionSignalsbooltrueEnable app switching, idle gaps
enableMotionLiteboolfalseEnable motion state inference
sessionIdPrefixString?nullPrefix for session IDs (null = auto-generated)
userIdString?nullOptional user identifier
deviceIdString?nullOptional device identifier
eventBatchSizeint10Events per batch
maxIdleGapSecondsdouble10.0Max idle time before task drop

BehaviorEvent

Properties:
PropertyTypeDescription
eventIdStringUnique event identifier
sessionIdStringAssociated session ID
timestampDateTimeEvent timestamp
eventTypeBehaviorEventTypeType of event
metricsMap<String, dynamic>Event-specific metrics
Event Types:
  • BehaviorEventType.scroll - Scroll interactions
  • BehaviorEventType.tap - Tap interactions
  • BehaviorEventType.swipe - Swipe interactions
  • BehaviorEventType.appSwitch - Foreground / background app-switch events (app_switch)
  • BehaviorEventType.notification - Notification events
  • BehaviorEventType.call - Call events
  • BehaviorEventType.typing - Typing session events (timing only — never characters)
  • BehaviorEventType.clipboard - Clipboard activity (copy / paste / cut counts only — never content)

BehaviorSession

Methods:
MethodDescriptionReturns
end()End session and get summaryFuture<BehaviorSessionSummary>
Properties:
PropertyTypeDescription
sessionIdStringSession identifier

BehaviorSessionSummary

Properties:
PropertyTypeDescription
sessionIdStringSession identifier
startAtStringSession start time (ISO 8601)
endAtStringSession end time (ISO 8601)
durationMsint (getter)Session duration in milliseconds
behavioralMetricsBehavioralMetricsBehavioral metrics
activitySummaryActivitySummaryActivity summary
notificationSummaryNotificationSummaryNotification summary
typingSessionSummaryTypingSessionSummary?Typing aggregates (when typing was active)
appId / appNameStringHost app identifiers
osMap<String, dynamic>OS / device platform info
microSessionMicroSession?Micro-session metadata
sessionSpacingSessionSpacing?Spacing relative to previous session
deviceContextDeviceContext?Device-state context
systemStateSystemState?System-level state at session boundaries
performanceInfoPerformanceInfo?Per-session performance counters
Motion classification runs in the Synheart Runtime — consumers subscribe to onMotionSample and forward raw 50 Hz accelerometer batches to the Synheart Runtime’s motion classifier.

BehavioralMetrics

Properties (12 total):
PropertyTypeDescription
interactionIntensitydoubleOverall interaction rate (0-1)
taskSwitchRatedoubleApp-switching frequency
taskSwitchCostintTask-switch cost in milliseconds
idleTimeRatiodoubleProportion of session that was idle (0-1)
activeTimeRatiodoubleProportion of session that was active (0-1)
notificationLoaddoubleNotification pressure
burstinessdoubleTemporal clustering of events
behavioralDistractionScoredoubleDistraction proxy (0-1)
focusHintdoubleFocus quality proxy (0-1)
fragmentedIdleRatiodoubleFragmented vs. continuous idle
scrollJitterRatedoubleScroll pattern irregularity
deepFocusBlocksList<DeepFocusBlock>Sustained focus periods

TypingSessionSummary

The aggregated typing fields live on TypingSessionSummary, accessed via BehaviorSessionSummary.typingSessionSummary (null when typing was not active during the session).
PropertyTypeDescription
typingSpeeddoubleAverage typing speed (taps per second)
typingCadenceStabilitydoubleConsistency of typing rhythm (0-1)
typingCadenceVariabilitydoubleVariability in timing between taps
typingActivityRatiodoubleFraction of session with active typing (0-1)
typingGapRatiodoubleProportion of intervals that are gaps (0-1)
typingBurstinessdoubleTemporal clustering of typing events
typingInteractionIntensitydoubleOverall typing engagement (0-1)
clipboardActivityRatedouble(copy+paste+cut)/(typing+clipboard)
correctionRatedouble(backspace+delete)/(typing+backspace+delete)

Permissions

Notification Permission

// Check if permission is granted
final hasPermission = await behavior.checkNotificationPermission();

if (!hasPermission) {
  // Request permission
  final granted = await behavior.requestNotificationPermission();
  if (granted) {
    print('Notification permission granted');
  }
}

Call Permission

// Check if permission is granted
final hasPermission = await behavior.checkCallPermission();

if (!hasPermission) {
  // Request permission
  await behavior.requestCallPermission();
}

Configuration

Update Configuration at Runtime

 await behavior.updateConfig(const BehaviorConfig(
  enableInputSignals: true,
  enableAttentionSignals: true,
  enableMotionLite: true,  
));

Resources

For comprehensive documentation, see the full README on GitHub.