Wrap native methods

This section describe how to create a native method handler for the Nabla SDK, so that you can call methods from your Dart code and have them implemented natively.

See the Flutter documentation for more details about how to write platform channels.

Android

Create NablaMethodCallHandler

In android/app/src/main/kotlin create the NablaMethodHandler:

class NablaMethodCallHandler(
    private val activity: ComponentActivity,
) : MethodChannel.MethodCallHandler {

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        when(call.method) {
            // TODO implement any method you'd like to wire here
            else -> result.notImplemented()
        }
    }
}

Wire NablaMethodCallHandler

In the MainActivity kotlin file (that should be in android/app/src/main/kotlin/your/package/name/MainActivity.kt), register the method handler:

class MainActivity: FlutterFragmentActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "nabla")
            .setMethodCallHandler(NablaMethodCallHandler(this))
    }
}

iOS

Create NablaMethodCallHandler

In ios/Runner create a new NablaMethodCallHandler.swift file:

class NablaMethodCallHandler {

    func handleCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch(call.method) {
        // TODO implement any method you'd like to wire here
        default: result(FlutterMethodNotImplemented)
        }
    }
}

Wire NablaMethodCallHandler

In ios/Runner, open the AppDelegate.swift file and wire the NablaMethodCallHandler:

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  private var nablaMethodCallHandler: NablaMethodCallHandler!

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    nablaMethodCallHandler = NablaMethodCallHandler()

    let nablaChannel = FlutterMethodChannel(name: "nabla", binaryMessenger: controller.binaryMessenger)
    nablaChannel.setMethodCallHandler(nablaMethodCallHandler.handleCall)

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Flutter

In your Dart code, you should now be able to call the native bridge, and can create a class to embed all of that code:

class NablaNativeBridge {
  static const _nablaChannel = MethodChannel('nabla');

  // TODO implement Nabla methods here
}

A complete example

This section provides a full example of how to wire native call via Dart code with Nabla SDK initialization:

Android:

class NablaMethodCallHandler(
    private val activity: ComponentActivity,
) : MethodChannel.MethodCallHandler {

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        when(call.method) {
            "initialize" -> handleInitialize(call, result)
            else -> result.notImplemented()
        }
    }

    private fun handleInitialize(call: MethodCall, result: MethodChannel.Result) {
        try {
            val apiKey = call.argument<String>("apiKey") ?: throw IllegalStateException("Null apiKey")

            NablaClient.initialize(
                configuration = Configuration(
                    publicApiKey = apiKey,
                ),
                modules = listOf(
                    NablaMessagingModule(), // if you want the messaging feature
                    NablaVideoCallModule(), // if you want to add video call capabilities
                    NablaSchedulingModule(), // if you want the scheduling feature
                ),
            )

            result.success(null)
        } catch (e: Exception) {
            result.error("initialize", e.message, null)
        }
    }
}

iOS

class NablaMethodCallHandler {
    func handleCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch(call.method) {
        case "initialize": handleInitialize(call: call, result: result)
        default: result(FlutterMethodNotImplemented)
        }
    }

    private func handleInitialize(call: FlutterMethodCall, result: FlutterResult) {
        guard let arguments = call.arguments as? Dictionary<String, AnyObject> else {
            result(FlutterError(code: "initialize", message: "unable to get arguments", details: nil))
            return
        }

        guard let apiKey = arguments["apiKey"] as? String else {
            result(FlutterError(code: "initialize", message: "unable to get apiKey", details: nil))
            return
        }

        NablaClient.initialize(
            apiKey: apiKey,
            modules: [
                NablaMessagingModule(), // if you want the messaging feature
                NablaVideoCallModule(), // if you want to add video call capabilities
                NablaSchedulingModule() // if you want the scheduling feature
            ]
        )

        result(nil)
    }
}

Flutter

class NablaNativeBridge {
  static const _nablaChannel = MethodChannel('nabla');

  Future<void> initialize(String apiKey) async {
    try {
      await _nablaChannel.invokeMethod('initialize', {'apiKey' : apiKey});
      debugPrint('NablaNativeBridge.initialize successful');
    } on PlatformException catch (e) {
      debugPrint('Unable to initialize Nabla SDK: ${e.message}');
    }
  }
}