SMKitUI Flutter Plugin (v1.5.2)

A Flutter plugin for integrating Sency's SMKitUI SDK, supporting both iOS and Android. Run fitness, body360, strength, cardio, and custom assessments and workouts with unified user data, summary options, skeleton visualization, and runtime modifications.

Requirements

  • Flutter: 3.44.0+
  • Dart: 3.12.0+
  • iOS: 16.0+, SMKitUI 2.0.3, SMKit 2.0.3
  • Android: minSdk 26, compileSdk 36, SMKitUI 1.7.1, SMKit 1.7.1, Gradle 8.14, AGP 8.13.2, Kotlin 2.2.20, Java 17

Getting Started

1. Configure

final _smkitUiFlutterPlugin = SmkitUiFlutterPlugin();
await _smkitUiFlutterPlugin.configure(
  key: apiPublicKey,
  poseModelChoice: SmKitPoseModelChoice.adaptiveChoice,
  configureLanguage: SMKitLanguage.english,
  includesHighlights: false, // iOS only
);

Available Android pose choices: adaptiveChoice, prime, pro, lite, ultraLite, basic. On iOS this parameter is accepted for API parity and currently ignored. configureLanguage defaults to English and controls configure-time voice feedback asset selection.

2. Apply SDK Config (Optional)

await _smkitUiFlutterPlugin.setConfig(
  config: SMKitConfig(
    enableIntelligenceRest: true,
    startTimerOnFirstActivity: true,
    workoutContinuationTimerDuration: 10,
    colorTheme: SMKitColorTheme.green,
    playPhoneCalibrationAudio: true,
    allowAudioMixing: false,
    instructionVideoConfig: InstructionVideoConfig(
      displayMode: InstructionVideoDisplayMode.mediumCycle,
      mediumSizeCycles: 2,
    ),
    skeletonConfig: SkeletonConfig(preset: SkeletonPreset.neonGlow),
    pauseTypes: [SMKitPauseType.resume, SMKitPauseType.quit],
  ),
);

3. Set Preferences (Optional)

_smkitUiFlutterPlugin.setSessionLanguage(language: SMKitLanguage.english);
_smkitUiFlutterPlugin.setCounterPreferences(counterPreferences: SMKitCounterPreferences.perfectOnly);
_smkitUiFlutterPlugin.setEndExercisePreferences(endExercisePrefernces: SMKitEndExercisePreferences.targetBased);

4. Start an Assessment

_smkitUiFlutterPlugin.startAssessment(
  type: AssessmentTypes.body360, // fitness, body360, strength, cardio, custom
  userData: {
    'gender': 'Male', // or 'Female', 'Idle'
    'birthday': DateTime(1990, 1, 1).millisecondsSinceEpoch,
  },
  showSummary: true,
  forceShowUserDataScreen: false,
  modifications: {
    'primaryColor': '#4CAF50',
    'phoneCalibration': {'enabled': true},
  },
  onHandle: (status) {
    if (status.operation == SMKitOperation.assessmentSummaryData) {
      final summary = status.data as SMKitAssessmentSummaryData;
    } else if (status.operation == SMKitOperation.error) {
      final error = status.data as SMKitError;
    }
  },
);

5. Start a Customized Workout

_smkitUiFlutterPlugin.startCustomizedWorkout(
  workout: SMKitWorkout(
    id: '1',
    name: 'My Workout',
    exercises: [
      SMKitExercise(
        detector: 'SquatRegular',
        prettyName: 'Squat',
        totalSeconds: 30,
        uiElements: [SMKitUIElement.repsCounter, SMKitUIElement.timer],
        shortIntro: true,
        adaptiveRomFeedbackEnabled: true,
      ),
    ],
    continuation: SMKitWorkoutContinuation(
      interactionUnlockSoundKey: 'ContinueWorkoutPrompt',
      exercises: [
        SMKitExercise(detector: 'Rest', prettyName: 'Rest', totalSeconds: 10),
      ],
    ),
  ),
  modifications: {'primaryColor': '#2196F3'},
  onHandle: (status) { ... },
);

6. Start a Customized Assessment

final targetReps = 5;
await _smkitUiFlutterPlugin.setEndExercisePreferences(
  endExercisePrefernces: SMKitEndExercisePreferences.targetBased,
);

_smkitUiFlutterPlugin.startCustomizedAssessment(
  assessment: SMKitWorkout(
    id: 'assessment-1',
    name: 'Target Reps Assessment',
    exercises: [
      SMKitExercise(
        detector: 'SquatRegular',
        prettyName: 'Squat',
        totalSeconds: 30, // still required by the native model
        uiElements: [SMKitUIElement.repsCounter, SMKitUIElement.gaugeOfMotion],
        showTargetProgress: true,
        scoringParams: ScoringParams.targetReps(
          targetReps: targetReps,
          scoreFactor: 0.5,
        ),
      ),
    ],
  ),
  showSummary: true,
  forceShowUserDataScreen: false,
  modifications: {'primaryColor': '#FF9800'},
  onHandle: (status) { ... },
);

For rep-scored dynamic assessments, targetReps stays available for scoring and summary data. Add showTargetProgress: true when the exercise should render completed/target reps and finish at the target without running the countdown timer; omit it to keep the normal timer behavior.

7. Start a Workout Program

_smkitUiFlutterPlugin.startWorkoutProgram(
  config: WorkoutConfig(
    programId: 'my-program-id',
    week: 1,
    bodyZone: BodyZone.fullBody,
    difficultyLevel: DifficultyLevel.midDifficulty,
    workoutDuration: WorkoutDuration.short,
    language: SencySupportedLanguage.english,
    shortIntro: true,
    phonePosition: SMKitPhonePosition.floor, // iOS only
  ),
  modifications: {'primaryColor': '#4CAF50'},
  onHandle: (status) { ... },
);

SMKitConfig Reference

Field Type Description
enableIntelligenceRest bool? Enable AI-based rest detection
enableHeartRateRest bool? Enable Apple Watch heart-rate rest suggestions on iOS
heartRateRestThreshold int? iOS heart-rate threshold for rest suggestions
allowAudioMixing bool? Allow app audio to mix with SDK audio
showExternalAudioControl bool? Show external audio control button
playPhoneCalibrationAudio bool? Play phone calibration audio
playBodyCalibrationAudio bool? Play body calibration audio
enableButtonTutorial bool? Enable hover-button tutorial
buttonTutorialCompletionAudioPath String? Local or URL audio for tutorial completion
enableWatchCompanion bool? Enable Apple Watch companion
accuratePoseEstimation bool? Enable high-accuracy pose estimation
showRowingPhoneCalibration bool? Show rowing phone calibration screen
enablePhoneMovementCountPrevention bool? Block counting while phone movement is detected
enableVariationMismatchFeedback bool? Play mismatch feedback for static/dynamic variation errors
startTimerOnFirstActivity bool? Start timer only after first rep or in-position frame
workoutContinuationTimerDuration int? Continuation prompt timer in seconds
colorTheme SMKitColorTheme? Direct SDK theme selection
skeletonConfig SkeletonConfig? Skeleton visualization settings
pauseTypes List<SMKitPauseType>? Pause overlay buttons
instructionVideoConfig InstructionVideoConfig? Instruction video display mode
useDefaultGuidanceMode bool? Android guidance default mode
guidanceDebugLogging bool? Native guidance debug logging
androidConfigString String? Android native flat config string
showDebugBoundingBox bool? iOS debug bounding box

Runtime Controls

await _smkitUiFlutterPlugin.quitWorkout();
await _smkitUiFlutterPlugin.pauseSdk();   // iOS only
await _smkitUiFlutterPlugin.resumeSdk();  // iOS only
await _smkitUiFlutterPlugin.clearAdaptiveRomCache(); // Android only
await _smkitUiFlutterPlugin.setFeedbacksUiToExclude(
  feedbacks: ['SquatHipCreaseDepth'],
);
await _smkitUiFlutterPlugin.setExcludedFeedbacks(
  feedbacks: ['SquatHipCreaseDepth'], // iOS only
);
final movements = await _smkitUiFlutterPlugin.getSupportedMovements(); // iOS only
final type = await _smkitUiFlutterPlugin.getExerciseType(detector: 'SquatRegular'); // iOS only

SkeletonConfig

Customize skeleton overlay: preset, connectionStyle, jointShape, dotsOpacity, connectionsOpacity, dotsInnerColor, dotsOuterColor, dotsGlow, connectionsGlow, lineWidthScale, outlineScale, softness, animationDuration, hidden.

Modifications Map

Key Type Description
primaryColor String Hex color for UI theme (maps to green/blue/orange/purple/silver/gold/pink)
phoneCalibration.enabled bool Show/hide phone calibration screen

Platform Notes

  • forceShowUserDataScreen is iOS-only.
  • pauseSdk, resumeSdk, setExcludedFeedbacks, getSupportedMovements, getExerciseType, includesHighlights, WorkoutConfig.phonePosition, and showDebugBoundingBox are iOS-only.
  • clearAdaptiveRomCache, useDefaultGuidanceMode, guidanceDebugLogging, and androidConfigString are Android-only.
  • SMKitPauseType.rest and switchExercise are Android-only.
  • WorkoutConfig enums use PascalCase on the wire (FullBody, MidDifficulty, Short, English).
  • Native SDK 2.0.3/1.7.1 support English and Hebrew. Configure defaults to English.

Changelog

See CHANGELOG.md for details.

License

MIT