Skip to main content
DocumentationFlutter
Version 0.2.0Flutter 3.22.3 and Dart 3.4 or later

Integrate the DobroDesk Flutter SDK

Add in-app customer support with dobrodesk_sdk, a host-issued customer token and the native iOS or Android widget.

On this page

Your Flutter app uses one Dart API backed by the native iOS and Android engines with the same widget behavior as the web integration.

Install the published Flutter package

Pin the published package version in pubspec.yaml or add it with the Flutter CLI before configuring the native host projects.

Shell
flutter pub add dobrodesk_sdk:0.2.0

Configure the Android host

The published Flutter package links the Android engine and UI from its bundled local Maven repository. Add this repository to the root Android build before the first Gradle sync. Set compileSdk 36, minSdk 26 and Java/Kotlin toolchains to 17. These settings are required by the 0.2.0 native artifacts.

Older Flutter templates can carry Android Gradle Plugin or Kotlin settings below this floor. Upgrade the Android Gradle Plugin and Kotlin plugin together using versions supported by your installed Flutter release before building. Do not silently patch the generated project during integration.

The tested Flutter 3.22.3 host tuple is Android Gradle Plugin 8.13.2, Kotlin Gradle Plugin 2.2.0, Gradle 8.14.3 and JDK 17. Flutter 3.44.2 generated hosts use a newer compatible tuple. Keep the versions generated by that Flutter release instead of downgrading them.

android/build.gradle.kts or android/build.gradle and android/app/*
// Kotlin DSL root template: android/build.gradle.kts
allprojects {
  repositories {
    google()
    mavenCentral()
    maven { url = uri(project(":dobrodesk_sdk").projectDir.resolve("../native/maven")) }
  }
}

// android/app/build.gradle.kts
android {
  compileSdk = 36
  defaultConfig { minSdk = 26 }
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
  }
}
kotlin { jvmToolchain(17) }

// Groovy root template: android/build.gradle
allprojects {
  repositories {
    google()
    mavenCentral()
    maven { url = uri(new File(project(":dobrodesk_sdk").projectDir, "../native/maven")) }
  }
}

// Keep the equivalent compileSdk/minSdk, Java 17 and Kotlin 17 settings in
// android/app/build.gradle when the generated app uses Groovy DSL.

Use FlutterFragmentActivity on Android

Keep the package declaration generated by Flutter and change the Android entry activity to FlutterFragmentActivity. The widget bridge needs the fragment activity's ActivityResultRegistryOwner. Leaving the generated FlutterActivity can crash when the widget opens with No ActivityResultRegistryOwner.

android/app/src/main/kotlin/.../MainActivity.kt
package com.example.app // keep the package generated for your app

import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity : FlutterFragmentActivity()

Configure the iOS host

Set the Flutter app target and every CocoaPods target to iOS 15.1 or later before pod install. Keep the generated Flutter Podfile and add the deployment setting in post_install so the SDK and host use the same floor.

The published iOS binary uses Swift concurrency. Use Xcode 16.4 or newer, keep the Swift version supported by your installed Flutter release and set the Xcode Runner target deployment value to 15.1 as well.

ios/Podfile and Xcode target
platform :ios, '15.1'

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.1'
    end
  end
end

# Also set Runner > Deployment Target to 15.1 in Xcode.

Configure and present the widget

The package supports Flutter 3.22.3 or later, Dart 3.4 through 3.x, Android API 26 and iOS 15.1. The credentialProvider callback is an application function. It must return a short-lived customer identity JWT from your backend. Do not embed a signing secret or support API token in the Flutter bundle.

Dart client
import "package:dobrodesk_sdk/dobrodesk_sdk.dart";

final client = DobroDeskFlutterClient(
  integrationId: "wgt_0123456789abcdef0123456789abcdef",
  apiOrigin: "https://dobrodesk.com",
  accountScope: currentCustomer.id,
  locale: "en",
  credentialProvider: () async => loadDobroDeskToken(),
);

await client.presentWidget();

Render inline or use a custom trigger

DobroDeskWidgetView embeds the native iOS or Android surface in the Flutter layout. Give its parent a stable bound so authentication and first content loading do not reflow the surrounding screen. Use client.presentWidget() from a host Button when the app needs a modal surface.

The view uses the same client, session and offline outbox as modal presentation. Removing the view releases its inline owner without resetting the session or discarding the draft. Reuse the client when a route remounts. Set visible to false while a kept-alive route or overlay is hidden. The native surface pauses visible work while preserving the client, session and draft. Omit onError to use the SDK's localized recovery surface or pass the typed callback from the host.

DobroDeskWidgetView is included in the published Mobile SDK 0.2.0 package. Use it for inline presentation and keep visibility changes on the same client so the session, draft and offline outbox are preserved.

Dart inline widget
import "package:flutter/widgets.dart";
import "package:dobrodesk_sdk/dobrodesk_sdk.dart";

Widget buildSupportPanel(
  DobroDeskFlutterClient client, {
  bool routeIsVisible = true,
}) {
  return SizedBox(
    height: 560,
    child: DobroDeskWidgetView(
      client: client,
      options: const NativeWidgetOptions(
        locale: "en",
        view: "home",
      ),
      visible: routeIsVisible,
    ),
  );
}

Use the shared native lifecycle

The widget is native on both platforms and does not use the web renderer in a WebView. Use client.resetSession() when the customer discards a conversation and client.logout() before switching accountScope. logout also disposes any attached optional voice capability.

Omit reduceMotion from presentWidget unless your app has an explicit customer setting that you are passing through. The native SDK honors the system reduced-motion preference by default.

Handle loading, detachment and accessibility

The native view owns message loading, assistant waiting and retry indicators. Use the client's typed events for a surrounding Flutter loading state and errorBuilder or onError for a recoverable host notice. Keep the widget input and keyboard in the normal Flutter layout rather than adding an overlay spinner.

Keep one DobroDeskWidgetView for each client. A route detach or rebuild must preserve the client and draft, while disposeInlineWidget only releases the inline owner. Native iOS and Android follow system reduced-motion and animation scale preferences, and the Flutter host remains responsible for safe-area and keyboard insets.

  1. Give the parent a stable height and rebuild with the same client after a route remount.
  2. Do not call resetSession or logout when the view is temporarily hidden.
  3. Call logout and dispose the client only when the account ends, then create a new client for the next account.

Verify the Flutter flow

  1. Present from a visible Flutter route and confirm that repeated taps do not stack native presentations.
  2. Exercise startSession, resumeSession, sendMessage with a stable idempotencyKey, refresh and flushOutbox from a development screen.
  3. Switch the device reduced-motion setting and repeat the open and close flow. Confirm that the widget does not introduce motion when the system asks for reduced motion.