• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

optimizely / optimizely-flutter-sdk / 17865830556

19 Sep 2025 05:48PM UTC coverage: 81.201% (-3.8%) from 84.952%
17865830556

Pull #83

github

web-flow
Merge 6336b0c53 into bbb47903d
Pull Request #83: [FSSDK-11853] add flutter logger support

2 of 36 new or added lines in 3 files covered. (5.56%)

4 existing lines in 1 file now uncovered.

622 of 766 relevant lines covered (81.2%)

1.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.2
/lib/src/optimizely_client_wrapper.dart
1
/// **************************************************************************
2
/// Copyright 2022-2023, Optimizely, Inc. and contributors                   *
3
///                                                                          *
4
/// Licensed under the Apache License, Version 2.0 (the "License");          *
5
/// you may not use this file except in compliance with the License.         *
6
/// You may obtain a copy of the License at                                  *
7
///                                                                          *
8
///    http://www.apache.org/licenses/LICENSE-2.0                            *
9
///                                                                          *
10
/// Unless required by applicable law or agreed to in writing, software      *
11
/// distributed under the License is distributed on an "AS IS" BASIS,        *
12
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13
/// See the License for the specific language governing permissions and      *
14
/// limitations under the License.                                           *
15
///**************************************************************************/
16

17
import 'dart:async';
18
import 'package:flutter/foundation.dart';
19
import 'package:flutter/services.dart';
20
import 'package:optimizely_flutter_sdk/optimizely_flutter_sdk.dart';
21
import 'package:optimizely_flutter_sdk/package_info.dart';
22
import 'package:optimizely_flutter_sdk/src/data_objects/activate_listener_response.dart';
23
import 'package:optimizely_flutter_sdk/src/data_objects/activate_response.dart';
24
import 'package:optimizely_flutter_sdk/src/data_objects/base_response.dart';
25
import 'package:optimizely_flutter_sdk/src/data_objects/get_variation_response.dart';
26
import 'package:optimizely_flutter_sdk/src/data_objects/get_vuid_response.dart';
27
import 'package:optimizely_flutter_sdk/src/data_objects/optimizely_config_response.dart';
28
import 'package:optimizely_flutter_sdk/src/utils/constants.dart';
29
import 'package:optimizely_flutter_sdk/src/utils/utils.dart';
30
import 'package:optimizely_flutter_sdk/src/logger/flutter_logger.dart';
31
import 'package:optimizely_flutter_sdk/src/logger/logger_bridge.dart';
32

33
enum ListenerType { activate, track, decision, logEvent, projectConfigUpdate }
34

35
enum ClientPlatform { iOS, android }
36

37
typedef ActivateNotificationCallback = void Function(
38
    ActivateListenerResponse msg);
39
typedef DecisionNotificationCallback = void Function(
40
    DecisionListenerResponse msg);
41
typedef TrackNotificationCallback = void Function(TrackListenerResponse msg);
42
typedef LogEventNotificationCallback = void Function(
43
    LogEventListenerResponse msg);
44
typedef MultiUseCallback = void Function(dynamic msg);
45

46
/// The internal client class for the Optimizely Flutter SDK used by the main OptimizelyFlutterSdk class.
47
class OptimizelyClientWrapper {
48
  static const MethodChannel _channel = MethodChannel('optimizely_flutter_sdk');
49
  static int nextCallbackId = 0;
50
  static Map<String, Map<int, ActivateNotificationCallback>>
51
      activateCallbacksById = {};
3✔
52
  static Map<String, Map<int, DecisionNotificationCallback>>
53
      decisionCallbacksById = {};
1✔
54
  static Map<String, Map<int, TrackNotificationCallback>> trackCallbacksById =
1✔
UNCOV
55
      {};
×
56
  static Map<String, Map<int, LogEventNotificationCallback>>
57
      logEventCallbacksById = {};
1✔
58
  static Map<String, Map<int, MultiUseCallback>> configUpdateCallbacksById = {};
1✔
59

60
  /// Starts Optimizely SDK (Synchronous) with provided sdkKey and options.
61
  static Future<BaseResponse> initializeClient(
1✔
62
      String sdkKey,
63
      EventOptions eventOptions,
64
      int datafilePeriodicDownloadInterval,
65
      Map<ClientPlatform, DatafileHostOptions> datafileHostOptions,
66
      Set<OptimizelyDecideOption> defaultDecideOptions,
67
      OptimizelyLogLevel defaultLogLevel,
68
      SDKSettings sdkSettings,
69
      OptimizelyLogger? logger) async {
70
    _channel.setMethodCallHandler(methodCallHandler);
1✔
71
    final convertedOptions = Utils.convertDecideOptions(defaultDecideOptions);
1✔
72
    final convertedLogLevel = Utils.convertLogLevel(defaultLogLevel);
1✔
73
    const sdkVersion = PackageInfo.version;
74

75
    Map<String, dynamic> requestDict = {
1✔
76
      Constants.sdkKey: sdkKey,
77
      Constants.sdkVersion: sdkVersion,
78
      Constants.datafilePeriodicDownloadInterval:
79
          datafilePeriodicDownloadInterval,
80
      Constants.optimizelyDecideOption: convertedOptions,
81
      Constants.defaultLogLevel: convertedLogLevel,
82
      Constants.eventBatchSize: eventOptions.batchSize,
1✔
83
      Constants.eventTimeInterval: eventOptions.timeInterval,
1✔
84
      Constants.eventMaxQueueSize: eventOptions.maxQueueSize,
1✔
85
      Constants.customLogger: logger != null,
86
    };
87

88
    // Odp Request params
89
    Map<String, dynamic> optimizelySdkSettings = {
1✔
90
      Constants.segmentsCacheSize: sdkSettings.segmentsCacheSize,
1✔
91
      Constants.segmentsCacheTimeoutInSecs:
92
          sdkSettings.segmentsCacheTimeoutInSecs,
1✔
93
      Constants.timeoutForSegmentFetchInSecs:
94
          sdkSettings.timeoutForSegmentFetchInSecs,
1✔
95
      Constants.timeoutForOdpEventInSecs: sdkSettings.timeoutForOdpEventInSecs,
1✔
96
      Constants.disableOdp: sdkSettings.disableOdp,
1✔
97
      Constants.enableVuid: sdkSettings.enableVuid,
1✔
98
    };
99
    requestDict[Constants.optimizelySdkSettings] = optimizelySdkSettings;
1✔
100

101
    // clearing notification listeners, if they are mapped to the same sdkKey.
102
    activateCallbacksById.remove(sdkKey);
2✔
103
    decisionCallbacksById.remove(sdkKey);
2✔
104
    trackCallbacksById.remove(sdkKey);
2✔
105
    logEventCallbacksById.remove(sdkKey);
2✔
106
    configUpdateCallbacksById.remove(sdkKey);
2✔
107

108
    datafileHostOptions.forEach((platform, datafileoptions) {
2✔
109
      // Pass datafile host only if non empty value for current platform is provided
110
      if (platform.name == defaultTargetPlatform.name &&
4✔
111
          datafileoptions.datafileHostPrefix.isNotEmpty &&
2✔
112
          datafileoptions.datafileHostSuffix.isNotEmpty) {
2✔
113
        requestDict[Constants.datafileHostPrefix] =
1✔
114
            datafileoptions.datafileHostPrefix;
1✔
115
        requestDict[Constants.datafileHostSuffix] =
1✔
116
            datafileoptions.datafileHostSuffix;
1✔
117
      }
118
    });
119

120
    final result = Map<String, dynamic>.from(
1✔
121
        await _channel.invokeMethod(Constants.initializeMethod, requestDict));
1✔
122
    return BaseResponse(result);
1✔
123
  }
124

125
  /// Use the activate method to start an experiment.
126
  ///  The activate call will conditionally activate an experiment for a user based on the provided experiment key and a randomized hash of the provided user ID.
127
  ///  If the user satisfies audience conditions for the experiment and the experiment is valid and running, the function returns the variation the user is bucketed into.
128
  ///  Otherwise, activate returns empty variationKey. Make sure that your code adequately deals with the case when the experiment is not activated (e.g. execute the default variation).
129
  static Future<ActivateResponse> activate(
1✔
130
      String sdkKey, String experimentKey, String userId,
131
      [Map<String, dynamic> attributes = const {}]) async {
132
    final result = Map<String, dynamic>.from(
1✔
133
        await _channel.invokeMethod(Constants.activate, {
2✔
134
      Constants.sdkKey: sdkKey,
135
      Constants.experimentKey: experimentKey,
136
      Constants.userId: userId,
137
      Constants.attributes: Utils.convertToTypedMap(attributes)
1✔
138
    }));
139
    return ActivateResponse(result);
1✔
140
  }
141

142
  /// Get variation for experiment and user ID with user attributes.
143
  static Future<GetVariationResponse> getVariation(
1✔
144
      String sdkKey, String experimentKey, String userId,
145
      [Map<String, dynamic> attributes = const {}]) async {
146
    final result = Map<String, dynamic>.from(
1✔
147
        await _channel.invokeMethod(Constants.getVariation, {
2✔
148
      Constants.sdkKey: sdkKey,
149
      Constants.experimentKey: experimentKey,
150
      Constants.userId: userId,
151
      Constants.attributes: Utils.convertToTypedMap(attributes)
1✔
152
    }));
153
    return GetVariationResponse(result);
1✔
154
  }
155

156
  /// Get forced variation for experiment and user ID.
157
  static Future<GetVariationResponse> getForcedVariation(
1✔
158
      String sdkKey, String experimentKey, String userId) async {
159
    final result = Map<String, dynamic>.from(
1✔
160
        await _channel.invokeMethod(Constants.getForcedVariation, {
2✔
161
      Constants.sdkKey: sdkKey,
162
      Constants.experimentKey: experimentKey,
163
      Constants.userId: userId,
164
    }));
165
    return GetVariationResponse(result);
1✔
166
  }
167

168
  /// Set forced variation for experiment and user ID to variationKey.
169
  static Future<BaseResponse> setForcedVariation(
1✔
170
      String sdkKey, String experimentKey, String userId,
171
      [String variationKey = ""]) async {
172
    Map<String, dynamic> request = {
1✔
173
      Constants.sdkKey: sdkKey,
174
      Constants.experimentKey: experimentKey,
175
      Constants.userId: userId,
176
    };
177
    if (variationKey != "") {
1✔
178
      request[Constants.variationKey] = variationKey;
1✔
179
    }
180
    final result = Map<String, dynamic>.from(
1✔
181
        await _channel.invokeMethod(Constants.setForcedVariation, request));
1✔
182
    return BaseResponse(result);
1✔
183
  }
184

185
  /// Returns a snapshot of the current project configuration.
186
  static Future<OptimizelyConfigResponse> getOptimizelyConfig(
1✔
187
      String sdkKey) async {
188
    final result = Map<String, dynamic>.from(await _channel.invokeMethod(
2✔
189
        Constants.getOptimizelyConfigMethod, {Constants.sdkKey: sdkKey}));
1✔
190
    return OptimizelyConfigResponse(result);
1✔
191
  }
192

193
  /// Send an event to the ODP server.
194
  static Future<BaseResponse> sendOdpEvent(String sdkKey, String action,
1✔
195
      {String? type,
196
      Map<String, String> identifiers = const {},
197
      Map<String, dynamic> data = const {}}) async {
198
    Map<String, dynamic> request = {
1✔
199
      Constants.sdkKey: sdkKey,
200
      Constants.action: action,
201
      Constants.identifiers: identifiers,
202
      Constants.data: Utils.convertToTypedMap(data)
1✔
203
    };
204
    if (type != null) {
205
      request[Constants.type] = type;
1✔
206
    }
207

208
    final result = Map<String, dynamic>.from(
1✔
209
        await _channel.invokeMethod(Constants.sendOdpEventMethod, request));
1✔
210
    return BaseResponse(result);
1✔
211
  }
212

213
  /// Returns the device vuid (read only)
214
  static Future<GetVuidResponse> getVuid(String sdkKey) async {
1✔
215
    final result = Map<String, dynamic>.from(
1✔
216
        await _channel.invokeMethod(Constants.getVuidMethod, {
2✔
217
      Constants.sdkKey: sdkKey,
218
    }));
219
    return GetVuidResponse(result);
1✔
220
  }
221

222
  /// Remove notification listener by notification id.
223
  static Future<BaseResponse> removeNotificationListener(
1✔
224
      String sdkKey, int id) async {
225
    Map<String, dynamic> request = {Constants.sdkKey: sdkKey, Constants.id: id};
1✔
226

227
    activateCallbacksById[sdkKey]?.remove(id);
3✔
228
    decisionCallbacksById[sdkKey]?.remove(id);
3✔
229
    logEventCallbacksById[sdkKey]?.remove(id);
3✔
230
    configUpdateCallbacksById[sdkKey]?.remove(id);
3✔
231
    trackCallbacksById[sdkKey]?.remove(id);
3✔
232

233
    final result = Map<String, dynamic>.from(await _channel.invokeMethod(
2✔
234
        Constants.removeNotificationListenerMethod, request));
235
    return BaseResponse(result);
1✔
236
  }
237

238
  /// Remove notification listeners by notification type.
239
  static Future<BaseResponse> clearNotificationListeners(
1✔
240
      String sdkKey, ListenerType listenerType) async {
241
    var callbackIds = _clearAllCallbacks(sdkKey, listenerType);
1✔
242
    Map<String, dynamic> request = {
1✔
243
      Constants.sdkKey: sdkKey,
244
      Constants.type: listenerType.name,
1✔
245
      Constants.callbackIds: callbackIds
246
    };
247
    final result = Map<String, dynamic>.from(await _channel.invokeMethod(
2✔
248
        Constants.clearNotificationListenersMethod, request));
249
    return BaseResponse(result);
1✔
250
  }
251

252
  /// Removes all notification listeners.
253
  static Future<BaseResponse> clearAllNotificationListeners(
1✔
254
      String sdkKey) async {
255
    var callbackIds = _clearAllCallbacks(sdkKey);
1✔
256
    Map<String, dynamic> request = {
1✔
257
      Constants.sdkKey: sdkKey,
258
      Constants.callbackIds: callbackIds
259
    };
260
    final result = Map<String, dynamic>.from(await _channel.invokeMethod(
2✔
261
        Constants.clearAllNotificationListenersMethod, request));
262
    return BaseResponse(result);
1✔
263
  }
264

265
  /// Returns a success true if optimizely client closed successfully.
266
  static Future<BaseResponse> close(String sdkKey) async {
1✔
267
    final result = Map<String, dynamic>.from(await _channel
1✔
268
        .invokeMethod(Constants.close, {Constants.sdkKey: sdkKey}));
2✔
269
    return BaseResponse(result);
1✔
270
  }
271

272
  /// Creates a context of the user for which decision APIs will be called.
273
  ///
274
  /// A user context will only be created successfully when the SDK is fully configured using initializeClient.
275
  static Future<OptimizelyUserContext?> createUserContext(String sdkKey,
1✔
276
      {String? userId, Map<String, dynamic> attributes = const {}}) async {
277
    Map<String, dynamic> request = {
1✔
278
      Constants.sdkKey: sdkKey,
279
      Constants.attributes: Utils.convertToTypedMap(attributes)
1✔
280
    };
281
    if (userId != null) {
282
      request[Constants.userId] = userId;
1✔
283
    }
284
    final result = Map<String, dynamic>.from(await _channel.invokeMethod(
2✔
285
        Constants.createUserContextMethod, request));
286

287
    if (result[Constants.responseSuccess] == true) {
2✔
288
      final response =
289
          Map<String, dynamic>.from(result[Constants.responseResult]);
2✔
290
      return OptimizelyUserContext(
1✔
291
          sdkKey, response[Constants.userContextId], _channel);
1✔
292
    }
293
    return null;
294
  }
295

296
  static List<int> _clearAllCallbacks(String sdkKey,
1✔
297
      [ListenerType? listenerType]) {
298
    var callbackIds = <int>[];
1✔
299
    if (listenerType == null || listenerType == ListenerType.activate) {
1✔
300
      if (activateCallbacksById.containsKey(sdkKey)) {
2✔
301
        callbackIds.addAll(activateCallbacksById[sdkKey]!.keys);
4✔
302
        activateCallbacksById[sdkKey]!.clear();
3✔
303
      }
304
    }
305
    if (listenerType == null || listenerType == ListenerType.decision) {
1✔
306
      if (decisionCallbacksById.containsKey(sdkKey)) {
2✔
307
        callbackIds.addAll(decisionCallbacksById[sdkKey]!.keys);
4✔
308
        decisionCallbacksById[sdkKey]!.clear();
3✔
309
      }
310
    }
311
    if (listenerType == null || listenerType == ListenerType.logEvent) {
1✔
312
      if (logEventCallbacksById.containsKey(sdkKey)) {
2✔
313
        callbackIds.addAll(logEventCallbacksById[sdkKey]!.keys);
4✔
314
        logEventCallbacksById[sdkKey]!.clear();
3✔
315
      }
316
    }
317
    if (listenerType == null ||
318
        listenerType == ListenerType.projectConfigUpdate) {
1✔
319
      if (configUpdateCallbacksById.containsKey(sdkKey)) {
2✔
320
        callbackIds.addAll(configUpdateCallbacksById[sdkKey]!.keys);
4✔
321
        configUpdateCallbacksById[sdkKey]!.clear();
3✔
322
      }
323
    }
324
    if (listenerType == null || listenerType == ListenerType.track) {
1✔
325
      if (trackCallbacksById.containsKey(sdkKey)) {
2✔
326
        callbackIds.addAll(trackCallbacksById[sdkKey]!.keys);
4✔
327
        trackCallbacksById[sdkKey]!.clear();
3✔
328
      }
329
    }
330
    return callbackIds;
331
  }
332

333
  static bool checkCallBackExist(String sdkKey, dynamic callback) {
1✔
334
    if (activateCallbacksById.containsKey(sdkKey)) {
2✔
335
      for (var k in activateCallbacksById[sdkKey]!.keys) {
4✔
336
        if (activateCallbacksById[sdkKey]![k] == callback) {
4✔
337
          return true;
338
        }
339
      }
340
    }
341
    if (decisionCallbacksById.containsKey(sdkKey)) {
2✔
342
      for (var k in decisionCallbacksById[sdkKey]!.keys) {
4✔
343
        if (decisionCallbacksById[sdkKey]![k] == callback) {
4✔
344
          return true;
345
        }
346
      }
347
    }
348
    if (trackCallbacksById.containsKey(sdkKey)) {
2✔
349
      for (var k in trackCallbacksById[sdkKey]!.keys) {
4✔
350
        if (trackCallbacksById[sdkKey]![k] == callback) {
4✔
351
          return true;
352
        }
353
      }
354
    }
355
    if (logEventCallbacksById.containsKey(sdkKey)) {
2✔
356
      for (var k in logEventCallbacksById[sdkKey]!.keys) {
4✔
357
        if (logEventCallbacksById[sdkKey]![k] == callback) {
4✔
358
          return true;
359
        }
360
      }
361
    }
362
    if (configUpdateCallbacksById.containsKey(sdkKey)) {
2✔
363
      for (var k in configUpdateCallbacksById[sdkKey]!.keys) {
4✔
364
        if (configUpdateCallbacksById[sdkKey]![k] == callback) {
4✔
365
          return true;
366
        }
367
      }
368
    }
369
    return false;
370
  }
371

372
  static Future<int> addActivateNotificationListener(
1✔
373
      String sdkKey, ActivateNotificationCallback callback) async {
374
    _channel.setMethodCallHandler(methodCallHandler);
1✔
375

376
    if (checkCallBackExist(sdkKey, callback)) {
1✔
377
      // ignore: avoid_print
378
      return -1;
1✔
379
    }
380

381
    int currentListenerId = nextCallbackId++;
1✔
382
    activateCallbacksById.putIfAbsent(sdkKey, () => {});
4✔
383
    activateCallbacksById[sdkKey]?[currentListenerId] = callback;
3✔
384
    final listenerTypeStr = ListenerType.activate.name;
1✔
385
    await _channel.invokeMethod(Constants.addNotificationListenerMethod, {
2✔
386
      Constants.sdkKey: sdkKey,
387
      Constants.id: currentListenerId,
388
      Constants.type: listenerTypeStr
389
    });
390
    // Returning an id that allows the user to remove the added notification listener.
391
    return currentListenerId;
392
  }
393

394
  static Future<int> addDecisionNotificationListener(
1✔
395
      String sdkKey, DecisionNotificationCallback callback) async {
396
    _channel.setMethodCallHandler(methodCallHandler);
1✔
397

398
    if (checkCallBackExist(sdkKey, callback)) {
1✔
399
      // ignore: avoid_print
UNCOV
400
      print("callback already exists.");
×
UNCOV
401
      return -1;
×
402
    }
403

404
    int currentListenerId = nextCallbackId++;
1✔
405
    decisionCallbacksById.putIfAbsent(sdkKey, () => {});
4✔
406
    decisionCallbacksById[sdkKey]?[currentListenerId] = callback;
3✔
407
    final listenerTypeStr = ListenerType.decision.name;
1✔
408
    await _channel.invokeMethod(Constants.addNotificationListenerMethod, {
2✔
409
      Constants.sdkKey: sdkKey,
410
      Constants.id: currentListenerId,
411
      Constants.type: listenerTypeStr
412
    });
413
    // Returning an id that allows the user to remove the added notification listener
414
    return currentListenerId;
415
  }
416

417
  static Future<int> addTrackNotificationListener(
1✔
418
      String sdkKey, TrackNotificationCallback callback) async {
419
    _channel.setMethodCallHandler(methodCallHandler);
1✔
420

421
    if (checkCallBackExist(sdkKey, callback)) {
1✔
422
      // ignore: avoid_print
423
      return -1;
1✔
424
    }
425

426
    int currentListenerId = nextCallbackId++;
1✔
427
    trackCallbacksById.putIfAbsent(sdkKey, () => {});
4✔
428
    trackCallbacksById[sdkKey]?[currentListenerId] = callback;
3✔
429
    final listenerTypeStr = ListenerType.track.name;
1✔
430
    await _channel.invokeMethod(Constants.addNotificationListenerMethod, {
2✔
431
      Constants.sdkKey: sdkKey,
432
      Constants.id: currentListenerId,
433
      Constants.type: listenerTypeStr
434
    });
435
    // Returning an id that allows the user to remove the added notification listener
436
    return currentListenerId;
437
  }
438

439
  static Future<int> addLogEventNotificationListener(
1✔
440
      String sdkKey, LogEventNotificationCallback callback) async {
441
    _channel.setMethodCallHandler(methodCallHandler);
1✔
442

443
    if (checkCallBackExist(sdkKey, callback)) {
1✔
444
      // ignore: avoid_print
445
      return -1;
1✔
446
    }
447

448
    int currentListenerId = nextCallbackId++;
1✔
449
    logEventCallbacksById.putIfAbsent(sdkKey, () => {});
4✔
450
    logEventCallbacksById[sdkKey]?[currentListenerId] = callback;
3✔
451
    final listenerTypeStr = ListenerType.logEvent.name;
1✔
452
    await _channel.invokeMethod(Constants.addNotificationListenerMethod, {
2✔
453
      Constants.sdkKey: sdkKey,
454
      Constants.id: currentListenerId,
455
      Constants.type: listenerTypeStr
456
    });
457
    // Returning an id that allows the user to remove the added notification listener
458
    return currentListenerId;
459
  }
460

461
  /// Allows user to listen to supported notifications.
462
  static Future<int> addConfigUpdateNotificationListener(
1✔
463
      String sdkKey, MultiUseCallback callback) async {
464
    _channel.setMethodCallHandler(methodCallHandler);
1✔
465

466
    if (checkCallBackExist(sdkKey, callback)) {
1✔
467
      // ignore: avoid_print
468
      return -1;
1✔
469
    }
470

471
    int currentListenerId = nextCallbackId++;
1✔
472
    configUpdateCallbacksById.putIfAbsent(sdkKey, () => {});
4✔
473
    configUpdateCallbacksById[sdkKey]?[currentListenerId] = callback;
3✔
474
    final listenerTypeStr = ListenerType.projectConfigUpdate.name;
1✔
475
    await _channel.invokeMethod(Constants.addNotificationListenerMethod, {
2✔
476
      Constants.sdkKey: sdkKey,
477
      Constants.id: currentListenerId,
478
      Constants.type: listenerTypeStr
479
    });
480
    // Returning an id that allows the user to remove the added notification listener
481
    return currentListenerId;
482
  }
483

484
  static Future<void> methodCallHandler(MethodCall call) async {
1✔
485
    final id = call.arguments[Constants.id];
2✔
486
    final sdkKey = call.arguments[Constants.sdkKey];
2✔
487
    final payload = call.arguments[Constants.payload];
2✔
488
    if (id is int && payload != null) {
1✔
489
      switch (call.method) {
1✔
490
        case Constants.activateCallBackListener:
1✔
491
          final response =
492
              ActivateListenerResponse(Map<String, dynamic>.from(payload));
2✔
493
          if (activateCallbacksById.containsKey(sdkKey) &&
2✔
494
              activateCallbacksById[sdkKey]!.containsKey(id)) {
3✔
495
            activateCallbacksById[sdkKey]![id]!(response);
4✔
496
          }
497
          break;
498
        case Constants.decisionCallBackListener:
1✔
499
          final response =
500
              DecisionListenerResponse(Map<String, dynamic>.from(payload));
2✔
501
          if (decisionCallbacksById.containsKey(sdkKey) &&
2✔
502
              decisionCallbacksById[sdkKey]!.containsKey(id)) {
3✔
503
            decisionCallbacksById[sdkKey]![id]!(response);
4✔
504
          }
505
          break;
506
        case Constants.trackCallBackListener:
1✔
507
          final response =
508
              TrackListenerResponse(Map<String, dynamic>.from(payload));
2✔
509
          if (trackCallbacksById.containsKey(sdkKey) &&
2✔
510
              trackCallbacksById[sdkKey]!.containsKey(id)) {
3✔
511
            trackCallbacksById[sdkKey]![id]!(response);
4✔
512
          }
513
          break;
514
        case Constants.logEventCallbackListener:
1✔
515
          final response =
516
              LogEventListenerResponse(Map<String, dynamic>.from(payload));
2✔
517
          if (logEventCallbacksById.containsKey(sdkKey) &&
2✔
518
              logEventCallbacksById[sdkKey]!.containsKey(id)) {
3✔
519
            logEventCallbacksById[sdkKey]![id]!(response);
4✔
520
          }
521
          break;
522
        case Constants.configUpdateCallBackListener:
1✔
523
          if (configUpdateCallbacksById.containsKey(sdkKey) &&
2✔
524
              configUpdateCallbacksById[sdkKey]!.containsKey(id)) {
3✔
525
            configUpdateCallbacksById[sdkKey]![id]!(payload);
4✔
526
          }
527
          break;
528
        default:
529
          // ignore: avoid_print
UNCOV
530
          print('Method ${call.method} not implemented.');
×
531
      }
532
    }
533
  }
534
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc