handleIntentExecution method
Executes the registered handler for the given intent.
This method is called internally when an intent execution request is received from iOS, and can also be called directly for testing.
Throws AppIntentError if no handler is registered for the identifier.
Implementation
Future<Map<String, dynamic>> handleIntentExecution(
String identifier,
Map<String, dynamic> params,
) async {
final handler = _intentHandlers[identifier];
if (handler == null) {
throw AppIntentError.fromCode(
AppIntentErrorCode.handlerNotFound,
message: 'No handler registered for intent: $identifier',
details: {'identifier': identifier},
);
}
// An intent that opened a native execution scope (#130/#131) carries its
// id in the params. The handler reaches it through
// `AppIntentExecution.current` rather than an argument, so the context is
// installed in a Zone around the call — the generated handler signature is
// the intent's own parameters and must stay that way.
final executionId = params[intentExecutionIdKey] as String?;
final handlerParams = executionId == null
? params
: (Map<String, dynamic>.of(params)..remove(intentExecutionIdKey));
try {
if (executionId == null) return await handler(handlerParams);
final execution = AppIntentExecution(
executionId: executionId,
reportUnits: (completed, total) =>
reportIntentProgress(executionId, completed, total),
requestParameterValue: (parameter) =>
requestIntentValue(executionId, parameter),
);
_activeExecutions[executionId] = execution;
try {
return await runZoned(
() => handler(handlerParams),
zoneValues: {AppIntentExecution.zoneKey: execution},
);
} finally {
_activeExecutions.remove(executionId);
}
} catch (e) {
if (e is AppIntentError) rethrow;
debugPrint('Intent execution error for $identifier: $e');
throw AppIntentError(
code: 'execution_error',
message: 'An error occurred while executing the intent.',
details: {'identifier': identifier},
);
}
}