Skip to main content

Conch API Reference

1. Core APIs​

1.1 runAppWrapper - Application startup wrapper​

1.1.1 Overview​

runAppWrapper is the core startup method of the Conch SDK. It wraps the Flutter app startup flow and automatically handles patch loading, app initialization, and global exception capture.

1.1.2 Workflow​

  1. Exception handler installation: Installs global exception handlers inside runZonedGuarded to capture three types of exceptions:

    • Flutter framework synchronous exceptions (FlutterError.onError)
    • Engine asynchronous exceptions (PlatformDispatcher.instance.onError)
    • Zone fallback exceptions (runZonedGuarded onError)
  2. Initialization phase: Automatically completes SDK initialization and sets configuration parameters and callbacks

  3. Patch handling: Loads patches according to configuration

  4. App startup: Calls appBuilder() to start the app

1.1.3 Function signature​

static void runAppWrapper(
FutureOr<ConchParams> Function() paramsBuilder, {
required FutureOr<void> Function() appBuilder,
PatchInstallCallback? patchInstallCallback,
PatchLoadCallback? patchLoadCallback,
AppErrorHandlingConfig errorConfig = const AppErrorHandlingConfig(),
bool useZonedGuarded = true,
})

1.1.4 Parameters​

ConchParams details​
ParameterTypeRequiredDescription
appIdStringYesUnique app identifier from the Shiply platform
appKeyStringYesObtained from the Shiply release platform; must match platform configuration for security validation
moduleNameStringYesModule name; must match the Shiply platform
appVersionStringYesApp version used for patch delivery version matching
envStringNoEnvironment identifier; defaults to "online" (production)
deviceIdStringNoDevice identifier for staged rollout and allowlists

Note: appId, appKey, and moduleName must exactly match Shiply platform configuration; otherwise patches cannot be fetched.

runAppWrapper parameters​
ParameterTypeRequiredDefaultDescription
paramsBuilderFutureOr<ConchParams> Function()Yes-Builder that returns ConchParams including appId, appKey, moduleName, etc.
appBuilderFutureOr<void> Function()Yes-App startup function; caller must call runApp inside. Supports sync or async execution. Called after patch loading completes. Typical usage: appBuilder: () => runApp(MyApp())
patchInstallCallbackPatchInstallCallback?NonullCallback when patch installation completes; returns PatchInstallResult with result code, version, etc.
patchLoadCallbackPatchLoadCallback?NonullCallback when patch loading completes; returns PatchLoadResult with result code, module name, version, etc.
errorConfigAppErrorHandlingConfigNoconst AppErrorHandlingConfig()App-level exception capture and handling configuration for customizing the three exception types
useZonedGuardedboolNotrueWhether to wrap app startup with runZonedGuarded
errorConfig details​

errorConfig is an AppErrorHandlingConfig object used to configure app-level exception handling:

class AppErrorHandlingConfig {
/// Flutter framework synchronous exception handler
/// Return value: true if handled (stops propagation); false if unhandled (delegates to the system default handler)
final bool Function(FlutterErrorDetails details)? onFlutterError;

/// Engine asynchronous exception handler
/// Return value: true if handled (stops propagation); false if unhandled (delegates to the system default handler)
final bool Function(Object error, StackTrace stackTrace)? onPlatformError;

/// Zone fallback exception handler
/// Return value: true if handled (stops propagation); false if unhandled (forwards to the parent Zone)
final bool Function(Object error, StackTrace stackTrace)? onZonedError;
}

Exception handling flow:

  1. Conch logs the exception first (for patch safe-mode management)
  2. Calls the callback configured by the app
  3. Decides whether to propagate the exception based on the callback return value

Return value:

  • Type: void
  • Description: No return value. This method calls runApp() internally, so you do not need to call runApp() again externally

1.1.5 Examples​

Basic usage (no exception handling)​
void main() {
ConchLoaderAPI.runAppWrapper(
() => params,
appBuilder: () => runApp(const MyApp()),
patchInstallCallback: (result) {
print('Patch install result: ${result.resultCode}');
},
patchLoadCallback: (result) {
print('Patch load result: ${result.resultCode}');
},
);
}
Full usage (with exception handling)​
void main() {
ConchLoaderAPI.runAppWrapper(
() => params,
appBuilder: () => runApp(const MyApp()),
patchInstallCallback: (result) {
print('Patch install result: ${result.resultCode}');
},
patchLoadCallback: (result) {
print('Patch load result: ${result.resultCode}');
},
errorConfig: AppErrorHandlingConfig(
// Handle Flutter framework synchronous exceptions
onFlutterError: (FlutterErrorDetails details) {
// Record the exception in the monitoring system
Crashlytics.recordFlutterError(details);

// Show a user-friendly error message
if (isCriticalError(details.exception)) {
showErrorDialog(details.exception.toString());
return true; // Prevent the default red error screen
}

return false; // Let the system continue handling
},

// Handle engine asynchronous exceptions
onPlatformError: (Object error, StackTrace stack) {
// Report the exception
Crashlytics.recordError(error, stack);

// Handle specific exceptions
if (error is NetworkException) {
showNetworkErrorToast();
return true;
}

return false;
},

// Handle Zone fallback exceptions
onZonedError: (Object error, StackTrace stackTrace) {
debugPrint('Unhandled app exception: $error');

// Emergency recovery strategy
if (shouldRestartApp(error)) {
restartApp();
return true;
}

return false;
},
),
);
}

1.1.6 Notes​

  • You must call runApp() inside appBuilder: runAppWrapper no longer calls runApp() automatically; call it inside appBuilder, e.g. appBuilder: () => runApp(MyApp())
  • Exception handler return values: Return values in errorConfig callbacks are important:
    • true: Business handled the exception; Conch stops propagation
    • false: Business did not handle it; Conch delegates to the original handler
  • Debug mode limitation: Conch patch functionality only works in Release mode, but exception handling also works in Debug mode
  • Defensive programming: Wrap logic inside errorConfig callbacks with try/catch to avoid the handler itself throwing

1.2 requestPatch - Patch request API​

1.2.1 Overview​

Fetches patches from the server and installs them locally only; does not load them into the runtime.

1.2.2 Function signature​

static Future<PatchInstallResult> requestPatch()

1.2.3 Core characteristics​

  • Network-only operation: Downloads and decrypts patches locally without loading into the runtime
  • Async execution: Non-blocking; suitable for background execution
  • Independent invocation: Can be called at any time; not tied to app startup
  • Pre-download: Download patches in advance for loading after cold start

Return value:

Type: Future<PatchInstallResult>

PatchInstallResult fields:

  • resultCode: Install status code (SUCCESS, FETCH_NO_PATCH, NOT_INIT, INSTALL_FAIL, etc.)
  • moduleName: Module name
  • version: Patch version
  • taskId: Task ID

1.2.4 Example​

// Pre-download patch in the background (non-blocking)
ConchLoaderAPI.requestPatch().then((result) {
if (result.resultCode == PatchInstallResultCode.SUCCESS) {
print('Patch downloaded and installed locally: ${result.version}');
} else {
print('Patch install failed or no patch available: ${result.resultCode}');
}
});

1.2.5 Notes​

  • This method only downloads and installs patches; it does not load them into the runtime
  • Downloaded patches are loaded automatically on the next app startup

1.3 queryPatchLoadResult - Patch load status query​

1.3.1 Overview​

Synchronously queries the current patch load result without triggering any load flow.

1.3.2 Function signature​

static PatchLoadResult? queryPatchLoadResult()

1.3.3 Core characteristics​

  • Query only: Does not trigger network requests or patch loading

Return value:

Type: PatchLoadResult?

Return value description:

  • Non-null: Contains current patch load status
    • resultCode: Load status code (SUCCESS, NO_PATCH, PATCH_LOAD_FAIL, etc.)
    • moduleName: Module name
    • version: Patch version
    • taskId: Task ID
  • null: Returned when:
    • Patch loading has not started or the load flow is not complete

1.3.4 Examples​

// Basic usage
final result = ConchLoaderAPI.queryPatchLoadResult();
if (result != null) {
if (result.resultCode == PatchLoadResultCode.SUCCESS) {
print('Currently loaded patch version: ${result.version}');
} else {
print('Patch not loaded or load failed: ${result.resultCode}');
}
} else {
print('SDK not initialized, patch loading not started, or load flow incomplete');
}

// Use in business logic
Widget build(BuildContext context) {
final patchResult = ConchLoaderAPI.queryPatchLoadResult();
final version = patchResult?.version ?? 'Unknown';

return Text('Current patch version: $version');
}

1.3.5 Notes​

  • Synchronous method; does not block the thread
  • Status query only; does not change runtime state
  • Recommended to call after app startup completes

2. Safe mode configuration APIs​

The Conch SDK provides a safe-mode mechanism to automatically detect and block faulty patches and protect app stability. Use the following APIs to configure safe-mode behavior.

Version requirement

Available in SDK 1.7.2 and later.

2.1 Core concepts​

How safe mode works:

  • Exception detection window: Time range from app startup; only exceptions in this window count
  • Exception count: Consecutive exceptions for a patch within the detection window (a success resets the count)
  • Success count: Consecutive successful runs for a patch (an exception resets the count)
  • Marked unsafe: When consecutive exceptions reach the threshold, the patch is marked unsafe and blocked from loading
  • Marked safe: When consecutive successes reach the threshold, the patch is marked safe and safe mode will not block it

2.2 API list​

setMarkPatchUnsafeThreshold - Set patch exception threshold​

Description:

  • Sets the consecutive exception threshold that triggers safe mode
  • When consecutive exceptions reach the threshold, the patch is marked unsafe and blocked from loading

Function signature:

static bool setMarkPatchUnsafeThreshold(int threshold)

Parameters:

ParameterTypeRequiredDescription
thresholdintYesConsecutive exception threshold; must be >= 1

Return value:

  • true: Setting succeeded
  • false: Setting failed (threshold < 1)

Example:

// Set consecutive exception threshold to 5
bool success = ConchLoaderAPI.setMarkPatchUnsafeThreshold(5);
if (success) {
print('Exception threshold set successfully');
}

setMarkPatchSafeThreshold - Set patch consecutive success threshold​

Description:

  • Sets the consecutive success threshold for a patch
  • When consecutive successes reach the threshold, the patch is marked safe; safe mode allows loading by default

Function signature:

static bool setMarkPatchSafeThreshold(int threshold)

Parameters:

ParameterTypeRequiredDescription
thresholdintYesConsecutive success threshold; must be >= 1

Return value:

  • true: Setting succeeded
  • false: Setting failed (threshold < 1)

Example:

// Set consecutive success threshold to 10
bool success = ConchLoaderAPI.setMarkPatchSafeThreshold(10);
if (success) {
print('Safe threshold set successfully');
}

setSafeModeWindowSeconds - Set safe mode detection window​

Description:

  • Sets the safe mode app detection window in seconds
  • Configures the exception detection time window from app startup
  • Only exceptions within this window count toward safe-mode exception counting

Function signature:

static bool setSafeModeWindowSeconds(int windowSeconds)

Parameters:

ParameterTypeRequiredDescription
windowSecondsintYesTime window in seconds; range [1, 60]

Return value:

  • true: Setting succeeded
  • false: Setting failed (windowSeconds not in [1, 60])

Example:

// Set detection window to 5 seconds
bool success = ConchLoaderAPI.setSafeModeWindowSeconds(5);
if (success) {
print('Detection window set successfully');
}

getSafeModeWindowSeconds - Get safe mode detection window​

Description:

  • Returns the current safe mode app detection window in seconds

Function signature:

static int getSafeModeWindowSeconds()

Return value:

  • Safe mode app detection window in seconds

Example:

int windowSeconds = ConchLoaderAPI.getSafeModeWindowSeconds();
print('Current detection window: $windowSeconds seconds');

getMarkPatchSafeThreshold - Get patch consecutive success threshold​

Description:

  • Returns the current patch consecutive success threshold

Function signature:

static int getMarkPatchSafeThreshold()

Return value:

  • Patch consecutive success threshold

Example:

int threshold = ConchLoaderAPI.getMarkPatchSafeThreshold();
print('Current safe threshold: $threshold');

getMarkPatchUnsafeThreshold - Get patch exception threshold​

Description:

  • Returns the current patch exception threshold

Function signature:

static int getMarkPatchUnsafeThreshold()

Return value:

  • Patch consecutive exception threshold

Example:

int threshold = ConchLoaderAPI.getMarkPatchUnsafeThreshold();
print('Current consecutive exception threshold: $threshold');

2.3 Full configuration example​

void main() {
// Configure safe mode parameters (recommended before runAppWrapper)
ConchLoaderAPI.setMarkPatchUnsafeThreshold(5); // Mark unsafe after 5 consecutive exceptions
ConchLoaderAPI.setMarkPatchSafeThreshold(10); // Mark safe after 10 consecutive successes
ConchLoaderAPI.setSafeModeWindowSeconds(5); // Detection window: 5 seconds
// Start the app
ConchLoaderAPI.runAppWrapper(
() => params,
appBuilder: () => runApp(const MyApp()),
errorConfig: AppErrorHandlingConfig(
onFlutterError: (details) {
// Business exception handling logic
return false;
},
),
);
}

2.4 Notes​

  • Call timing: Configure safe mode before runAppWrapper
  • Defaults: If not configured, defaults are:
    • Consecutive exception threshold: 3
    • Consecutive success threshold: 5
    • Detection window: 3 seconds
  • Release mode only: Safe mode only applies in Release mode; Debug mode does not block patches
  • Persistent storage: Safe-mode counters persist across app restarts
  • Patch updates: Counters reset automatically when the patch version changes (MD5 change)
Was this page helpful?