Friday, October 21, 2022
HomeWeb DevelopmentUtilizing Flutter’s MethodChannel to invoke Kotlin code for Android

Utilizing Flutter’s MethodChannel to invoke Kotlin code for Android


Creating a Flutter cellular app entails rendering some UI components that get modified in keeping with the user-initiated contact occasions , so we regularly want to make use of the person system’s {hardware} parts through platform-specific SDKs.

Each cellular platform provides inbuilt APIs to entry {hardware} parts and core working system options. For instance, for those who construct a local Android app with Kotlin, you need to use the Vibratorclass from the Android SDK to make the person’s system vibrate.

You should utilize your current Kotlin/Java-based shared libraries inside native Kotlin-based Android apps. However what if it’s essential name this platform-specific Kotlin code out of your Flutter app?

Flutter enables you to use Dart’s inbuilt cross-platform normal library for general-purpose programming necessities (i.e., I/O, Math, and so on.). It additionally provides the platform channels API to speak with platform-specific code to make use of operating-system-level APIs or invoke code segments written within the native app improvement language.

On this tutorial, I’ll clarify how one can name Kotlin code from the Dart aspect through the Flutter platform channels’ MethodChannel class. Additionally, I’ll clarify how one can do event-driven Flutter-Native communications through EventChannel.

Soar forward:

Highlighted options of MethodChannel

Flutter provides the MethodChannel Dart class for builders to invoke platform-specific native code from the Flutter atmosphere. Additionally, Flutter provides you the required APIs to ship knowledge again to Flutter from the native host app code. Test the next highlighted options that MethodChannel provides:

Cross-platform assist

We’ll focus on how one can invoke Kotlin code from Flutter, however the Flutter framework implementation enables you to name native code on iOS, Linux, macOS, and Home windows. So, calling Swift/Goal-C and C/C++ code can be attainable.

Efficiency-first design

Flutter doesn’t use embedded JavaScript execution environments, not like different standard cross-platform app improvement frameworks. Additionally, it makes use of AOT (ahead-of-time) compilation for launch binaries to realize near-native efficiency.

Equally, the Flutter workforce designed the Flutter-Native communication technique with a performance-first, binary messaging protocol for higher app efficiency. So, utilizing Kotlin and Dart on Android for accessing the Android SDK has no seen efficiency distinction!

Bi-directional communication assist

The Dart-based MethodChannel class helps you name platform-specific code from Flutter. Alternatively, Flutter exposes platform-specific MethodChannel API to name Dart code from the native aspect. So, you can also make a bi-directional communication line between your Dart code and platform-specific native code.

Automated data-type mapping

Flutter’s low-level platform channels API makes use of a binary messaging protocol, so all technique calls are remodeled right into a byte stream through the Dart-to-Native communication (see how Android type-conversion implementation makes use of ByteBuffer right here). Flutter routinely removes knowledge information from the byte stream and generates language-specific knowledge varieties within the Dart and native finish. So, you possibly can switch your Dart-based knowledge to Kotlin/Java knowledge, and vice-versa as you’re employed with one language, though there are two totally different environments. Furthermore, the kind conversion characteristic is on the market for all supported platforms.

Error-handling options

Platform-specific APIs usually throw exceptions or return error codes for sudden or failure occasions. On the native aspect, we will simply use native SDK error-handling methods, however what can we do from the Dart aspect? MethodChannel comes with inbuilt-error dealing with assist and throws Dart exceptions. Additionally, you need to use error codes from exception cases to enhance the error-handling technique in order for you.

Flutter MethodChannel‘s structure

You’ve presumably simply learn an summary of MethodChannel and the Flutter platform channels API’s objectives. The Flutter framework is comprised of two key parts: the Dart framework and the Flutter engine.

The Dart framework consists of an inbuilt widgets toolkit implementation, and the Flutter engine implements native host apps that embed the Dart framework. The platform channels API connects these two parts along with a bi-directional communication line.

The MethodChannel implementation, part of the platform channels API enables you to execute and extract the results of named strategies on Dart and native code.

Now, you understand the architectural points of MethodChannel. You may learn extra about the whole Flutter structure from this text and the official documentation.

Let’s get began with sensible functions!

Establishing a brand new mission

On this part, we’ll construct a pattern Flutter app and prolong it in keeping with varied sensible necessities to know how one can use MethodChannel for connecting Kotlin and Dart collectively.

First, create a brand new Flutter mission with the next command:

flutter create flutter_platform_channels_demo
cd flutter_platform_channels_demo

Run the newly generated app with the flutter run command to test that every thing works.

You may examine the native Android host app supply by opening the android/app listing. By default, the flutter create command generates a Kotlin-based host app , and you could find the Android app’s Kotlin code in MainActivity.kt. You gained’t see a lot code there, however you’ll discover it implements the FlutterActivityclass, part of the Flutter engine.

Now, we will begin modifying the MainActivity Kotlin class to construct up a technique channel to attach with the Dart aspect.

Calling Kotlin code from Dart

We all know that we will generate a random quantity inside Dart, however let’s name the Kotlin normal library’s random quantity generator from the Dart aspect to get began with MethodChannel.

First, we have to register a technique name handler from the Kotlin aspect. Add the next code to your MainActivity.kt:

package deal com.instance.flutter_platform_channels_demo

import kotlin.random.Random
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.widespread.MethodChannel

class MainActivity: FlutterActivity() {
  override enjoyable configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    tremendous.configureFlutterEngine(flutterEngine)
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "instance.com/channel").setMethodCallHandler {
      name, end result ->
        if(name.technique == "getRandomNumber") {
          val rand = Random.nextInt(100)
          end result.success(rand)
        }
        else {
          end result.notImplemented()
        }
    }
  }
}

Right here, we override the configureFlutterEngine technique from the FlutterActivity class to register a technique channel for constructing a communication line with Dart. The configureFlutterEngine technique will get invoked when the Flutter engine is initialized with a selected Android Exercise occasion, so Flutter recommends utilizing it to register technique channel handlers.

A way channel is sort of a namespace that consists of a number of technique signatures, so you need to use one technique channel to implement a number of native strategies. On this state of affairs, we applied the getRandomNumber technique for demonstration functions. When the actual technique channel receives a technique name, we will determine the strategy title utilizing a conditional assertion:

if(name.technique == "getRandomNumber") {
    val rand = Random.nextInt(100)
    end result.success(rand)
}
// ---
// ---

Right here, we use the end result.success technique to return the generated random quantity to the Dart atmosphere. Although we don’t present invalid technique names intentionally from Dart, it’s all the time good to deal with unknown technique calls as follows:

// ---
else {
   end result.notImplemented()
}

Now, the native implementation is able to obtain technique calls from Dart. We’ll modify Flutter’s default demo app to show a random quantity generated from Kotlin. After we press the floating motion button, we see a brand new random quantity.


Extra nice articles from LogRocket:


Add the next code to your fundamental.dart:

import 'package deal:flutter/providers.dart';
import 'package deal:flutter/materials.dart';

void fundamental() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({tremendous.key});
  @override
  Widget construct(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colours.blue,
      ),
      residence: const MyHomePage(title: 'Flutter Demo Dwelling Web page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({tremendous.key, required this.title});
  remaining String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  static const platform = MethodChannel('instance.com/channel');
Future<void> _generateRandomNumber() async {
    int random;
    attempt {
      random = await platform.invokeMethod('getRandomNumber');
    } on PlatformException catch (e) {
      random = 0;
    }
setState(() {
      _counter = random;
    });
  }
  @override
  Widget construct(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Textual content(widget.title),
      ),
      physique: Middle(
        youngster: Column(
          mainAxisAlignment: MainAxisAlignment.middle,
          youngsters: <Widget>[
            const Text(
              'Kotlin generates the following number:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _generateRandomNumber,
        tooltip: 'Generate',
        youngster: const Icon(Icons.refresh),
      ),
    );
  }
}

We created a MethodChannel occasion within the Dart atmosphere as follows:

static const platform = MethodChannel('instance.com/channel');

Notice that we should always go the precise technique channel title we used within the Kotlin code — in any other case, the particular technique name will throw a MissingPluginException.

We invoke the _generateRandomNumber technique when the person presses the floating motion button. When the actual technique will get invoked, the app sends a message to the strategy channel through platform.invokeMethod(‘getRandomNumber’). Internally, the Flutter engine triggers the strategy channel handler and executes the Kotlin-based random quantity era code we wrote earlier than.

Run the app and see the pattern app in motion:

Flutter sample app

Returning knowledge from Kotlin to Dart

Within the earlier instance, we returned an integer from Kotlin to Dart. After we present a Kotlin Int sort to a selected technique name, Flutter routinely converts it to a Dart int sort.

Equally, Flutter’s Technique Channel implementation routinely converts all atomic varieties and a few complicated inbuilt objects as properly, akin to Kotlin Listing and HashMap. The next desk from the Flutter documentation lists all supported computerized sort conversions:

Dart Kotlin
null null
bool Boolean
int Int
int Lengthy
double Double
String String
Uint8List ByteArray
Int32List IntArray
Int64List LongArray
Float32List FloatArray
Float64List DoubleArray
Listing Listing
Map HashMap

Let’s attempt to use Kotlin’s String sort and see what occurs from the Dart aspect. Use the next code to generate a random string from Kotlin in MainActivity.kt:

override enjoyable configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    tremendous.configureFlutterEngine(flutterEngine)
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "instance.com/channel").setMethodCallHandler {
      name, end result ->
        if(name.technique == "getRandomString") {
          val rand = ('a'..'z').shuffled().take(4).joinToString("")
          end result.success(rand)
        }
        else {
          end result.notImplemented()
        }
    }
  }

We return a four-character-long random string for the getRandomString technique for the Dart aspect. Now, modify your fundamental.dart file to simply accept a string worth from Kotlin as follows:

import 'package deal:flutter/providers.dart';
import 'package deal:flutter/materials.dart';

void fundamental() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({tremendous.key});
  @override
  Widget construct(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colours.blue,
      ),
      residence: const MyHomePage(title: 'Flutter Demo Dwelling Web page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({tremendous.key, required this.title});
  remaining String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _counter="";
  static const platform = MethodChannel('instance.com/channel');
Future<void> _generateRandomString() async {
    String random = '';
    attempt {
      random = await platform.invokeMethod('getRandomString');
      print(random.runtimeType);
    } on PlatformException catch (e) {
      random = '';
    }
setState(() {
      _counter = random;
    });
  }
  @override
  Widget construct(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Textual content(widget.title),
      ),
      physique: Middle(
        youngster: Column(
          mainAxisAlignment: MainAxisAlignment.middle,
          youngsters: <Widget>[
            const Text(
              'Kotlin generates the following string:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _generateRandomString,
        tooltip: 'Generate',
        youngster: const Icon(Icons.refresh),
      ),
    );
  }
}

The above code makes use of print(random.runtimeType) to test the output knowledge sort of the invokeMethod technique. On this case, we obtain a string from the Kotlin aspect and show on the Flutter app display screen. Run the above code and press the floating motion button to generate random strings through Kotlin:

generate random strings via Kotlin

When you test your terminal display screen, you need to see that the print operate outputs String as the information sort of the random variable; if that is so, then we all know the kind conversion labored.

Experiment with the opposite primitive knowledge varieties. I’ll clarify how one can switch complicated knowledge varieties and objects between Kotlin and Dart in an upcoming part of this tutorial.

Passing arguments from Dart to Kotlin

We already mentioned how one can return knowledge from Kotlin with success technique calls. What if it’s essential ship some knowledge to Kotlin from Dart?

We usually use technique parameters once we name a technique in a selected programming language  —  and the identical method works with Flutter technique channels! You may go named parameters through the invokeMethod technique utilizing a Dart dynamic map.

Assume that you must configure the random string era course of from the Dart aspect. For instance, we will ship the string size and a prefix from the Flutter app code.

First, determine the required parameters:

  • len: Random string size
  • prefix: A prefix for the random string

Ship these parameters with values through _generateRandomString:

Future<void> _generateRandomString() async {
    String random = '';
    attempt {
      var arguments = {
        'len': 3,
        'prefix': 'fl_',
      };
      random = await platform.invokeMethod('getRandomString', arguments);
    } on PlatformException catch (e) {
      random = '';
    }
setState(() {
      _counter = random;
    });
  }

Subsequent, replace the Kotlin code to devour the named parameters:

if(name.technique == "getRandomString") {
  val restrict = name.argument("len") ?: 4
  val prefix = name.argument("prefix") ?: ""
  val rand = ('a'..'z')
                .shuffled()
                .take(restrict)
                .joinToString(prefix = prefix, separator = "")
  end result.success(rand)
}

The above code makes use of Kotlin’s Elvis operator [?:]to set default values for restrict and prefix constants. Run the app. You will note random strings based mostly on parameters we’ve offered from the Dart aspect of the strategy channel:

Random strings based on parameters we’ve provided from the Dart side of the method channel

Experiment additional utilizing varied values for technique parameters and attempt to add extra parameters.
If it’s essential go one technique parameter, you possibly can straight go the actual parameter with out making a dynamic map for higher readability. See how the next code snippet sends the random string size:

// Dart:
random = await platform.invokeMethod('getRandomString', 3);

// Kotlin
val restrict = name.arguments() ?: 4
val rand = ('a'..'z')
              .shuffled()
              .take(restrict)
              .joinToString("")
end result.success(rand)

Error dealing with methods

There are two main error-handling methods in programming: error code-based and exceptions-based. Some programmers use a hybrid error-handling technique by mixing each.

MethodChannel has inbuilt assist to deal with exceptions from Dart for the Kotlin aspect’s error flows. Additionally, it provides a technique to distinguish native error varieties with error codes in exception cases. In different phrases, MethodChannel provides a hybrid error-handling technique for Flutter builders.

In earlier examples, we used the end result.success technique to return a price and end result.notImplemented to deal with unknown technique calls, which can throw MissingPluginException in Dart.

What if we have to make a Dart exception from the Kotlin aspect? The end result.error technique helps you throw a Dart PlatformException occasion from Kotlin. Assume that we have to throw an exception if we offer a destructive worth for the random string size within the earlier instance.

First, replace the Kotlin code as follows to inform Dart in regards to the exception:

if(name.technique == "getRandomString") {
  val restrict = name.arguments() ?: 4
  if(restrict < 0) {
    end result.error("INVALIDARGS", "String size shouldn't be a destructive integer", null)
  }
  else {
    val rand = ('a'..'z')
                  .shuffled()
                  .take(restrict)
                  .joinToString("")
    end result.success(rand)
  }
}

Right here, we offer a novel exception code and message through end result.error. Subsequent, catch the exception and use it throughout the Dart aspect as follows:

Future<void> _generateRandomString() async {
    String random = '';
    attempt {
      random = await platform.invokeMethod('getRandomString', -5);
    } on PlatformException catch (e) {
      random = '';
      print('PlatformException: ${e.code} ${e.message}');
    }
    setState(() {
      _counter = random;
    });
  }

While you run the app and press the floating motion button, you will notice the exception code and message in your terminal as a result of we handed -5 because the string size from the Dart aspect:

Exception code

As we noticed within the above instance, you possibly can catch PlatformException in Dart, and you may test the error code within the exception occasion for dealing with technique channel errors. One other extra summary method is to make your individual exception occasion based mostly on Kotlin error codes. Test the Flutter digital camera plugin’s CameraException as a reference implementation.

Invoking native SDK capabilities through MethodChannel

Now, we all know how one can use MethodChannel to invoke Kotlin code from Dart. We’ve used Kotlin’s normal library options in earlier demonstrations. Equally, you possibly can reuse your pre-implemented Kotlin/Java libraries with the Flutter platform channels. Utilizing native SDKs can be attainable with technique channels, and that’s the principle aim behind Flutter’s platform channels implementation.

Flutter already helps system darkish theme dealing with and has plugins for different native SDKs, however let’s invoke some native SDK APIs to know MethodChannel use instances additional.

We’ll write a local technique to test whether or not the darkish theme is on or not. First, implement a brand new technique in Flutter technique channels with Kotlin in your MainActivity.kt:

package deal com.instance.flutter_platform_channels_demo

import kotlin.random.Random
import androidx.annotation.NonNull
import android.content material.res.Configuration
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.widespread.MethodChannel

class MainActivity: FlutterActivity() {
  override enjoyable configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    tremendous.configureFlutterEngine(flutterEngine)
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "instance.com/channel").setMethodCallHandler {
      name, end result ->sucess
        if(name.technique == "isDarkMode") {
          val mode = getContext()
                        .getResources()
                        .getConfiguration().uiMode and Configuration.UI_MODE_NIGHT_MASK
          end result.success(mode == Configuration.UI_MODE_NIGHT_YES)
        }
        else {
          end result.notImplemented()
        }
    }
  }
}

Right here we used the uiMode bit masks from the Android SDK’s Configuration API to detect the system theme. Subsequent, use the isDarkMode technique from Dart by updating the _MyHomePageState implementation:

class _MyHomePageState extends State<MyHomePage> {
  String _theme="";
  static const platform = MethodChannel('instance.com/channel');
  Future<void> _findColorTheme() async {
    bool isDarkMode;
    attempt {
      isDarkMode = await platform.invokeMethod('isDarkMode');
    } on PlatformException catch (e) {
      isDarkMode = false;
      print('PlatformException: ${e.code} ${e.message}');
    }
  setState(() {
      _theme = isDarkMode ? 'darkish' : 'mild';
    });
  }

  @override
  Widget construct(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Textual content(widget.title),
      ),
      physique: Middle(
        youngster: Column(
          mainAxisAlignment: MainAxisAlignment.middle,
          youngsters: <Widget>[
            const Text(
              'System color theme:',
            ),
            Text(
              _theme,
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _findColorTheme,
        tooltip: 'Discover colour theme',
        youngster: const Icon(Icons.refresh),
      ),
    );
  }
}

Check the app by altering your system colour theme as follows:

Dark theme display

Equally, you possibly can name any Android SDK APIs from Dart through Flutter platform channels.

Utilizing the EventChannel class

The MethodChannel class offers a request-response-based communication resolution as conventional RESTful APIs do. What if we have to name purchasers from the server once we work with internet functions? Then, we have a tendency to decide on an event-driven communication mechanism like WebSockets. The EventChannel class provides an asynchronous occasion stream for constructing an event-driven communication line between the native host app and Flutter. The EventChannel class is usually used to ship native occasions to the Dart aspect.

For instance, we will dispatch the system theme change occasion from Kotlin to Dart. Additionally, we will use EventChannel to broadcast frequent occasions from the system’s sensors.

Earlier, we needed to press the floating motion button to detect the present system colour theme. Now, we’ll enhance our app by including an EventChannel occasion to deal with it routinely.

First, add the next code to your MainActivity.kt:

package deal com.instance.flutter_platform_channels_demo

import kotlin.random.Random
import androidx.annotation.NonNull
import android.os.Bundle
import android.content material.res.Configuration
import android.content material.pm.ActivityInfo
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.widespread.EventChannel
import io.flutter.plugin.widespread.EventChannel.EventSink
import io.flutter.plugin.widespread.EventChannel.StreamHandler

class MainActivity: FlutterActivity() {
  var occasions: EventSink? = null
  var oldConfig: Configuration? = null

  override enjoyable onCreate(savedInstanceState: Bundle?) {
    tremendous.onCreate(savedInstanceState)
    oldConfig = Configuration(getContext().getResources().getConfiguration())
  }

  override enjoyable configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    tremendous.configureFlutterEngine(flutterEngine)
EventChannel(flutterEngine.dartExecutor.binaryMessenger, "instance.com/channel").setStreamHandler(
      object: StreamHandler {
        override enjoyable onListen(arguments: Any?, es: EventSink) {
          occasions = es
          occasions?.success(isDarkMode(oldConfig))
        }
        override enjoyable onCancel(arguments: Any?) {
        }
      }
    );
  }

  override enjoyable onConfigurationChanged(newConfig: Configuration) {
    tremendous.onConfigurationChanged(newConfig)
    if(isDarkModeConfigUpdated(newConfig)) {
      occasions?.success(isDarkMode(newConfig))
    }
    oldConfig = Configuration(newConfig)
  }

  enjoyable isDarkModeConfigUpdated(config: Configuration): Boolean {
    return (config.diff(oldConfig) and ActivityInfo.CONFIG_UI_MODE) != 0
      && isDarkMode(config) != isDarkMode(oldConfig);
  }

  enjoyable isDarkMode(config: Configuration?): Boolean {
    return config!!.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
  }
}

We use the EventChannel class to create an event-driven communication stream. As soon as the EventChannel handler is hooked up, we will use the EventSink occasion to ship occasions to the Dart aspect. Occasions happen within the following conditions:

  • When the Flutter app is initialized, the occasion channel will obtain a brand new occasion with the present theme standing
  • When the person goes again to the app after altering the system theme from the settings app, the occasion channel will obtain a brand new occasion with the present theme standing

Notice that right here we use a boolean worth because the occasion payload to determine whether or not the darkish mode is activated or not. Now, add the next code to your fundamental.dart file and full the implementation:

import 'package deal:flutter/providers.dart';
import 'package deal:flutter/materials.dart';

void fundamental() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({tremendous.key});
  @override
  Widget construct(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(),
      darkTheme: ThemeData.darkish(),
      themeMode: ThemeMode.system,
      residence: const MyHomePage(title: 'Flutter Demo Dwelling Web page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({tremendous.key, required this.title});
  remaining String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _theme="";
  static const occasions = EventChannel('instance.com/channel');

  @override
  void initState() {
    tremendous.initState();
    occasions.receiveBroadcastStream().hear(_onEvent);
  }
  void _onEvent(Object? occasion) {
    setState(() {
      _theme = occasion == true ? 'darkish' : 'mild';
    });
  }

  @override
  Widget construct(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Textual content(widget.title),
      ),
      physique: Middle(
        youngster: Column(
          mainAxisAlignment: MainAxisAlignment.middle,
          youngsters: <Widget>[
            const Text(
              'System color theme:',
            ),
            Text(
              _theme,
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
    );
  }
}

The above code connects with the occasion channel we created earlier than and shows the present theme. The EventChannel implementation triggers the _onEvent callback every time it receives a brand new occasion from the Kotlin aspect.

Run the app and activate/deactivate darkish mode. You need to see the theme title on the app display screen, as proven within the following preview:

Deactivating dark mode

You’ll discover the app colour scheme is modified based mostly on the present theme. This conduct occurs as a result of we used ThemeMode.system for themeMode to make the Flutter app conscious of the present system theme, and this conduct isn’t a results of the EventChannel API utilization.

Sending/receiving complicated objects

The Flutter platform channels API routinely converts inbuilt complicated varieties, like maps and lists. However, in some situations, we have to go much more complicated objects with many knowledge information. You may contemplate the next methods for sending/receiving such complicated objects:

  • Transferring the item knowledge as a map with primitive knowledge varieties. You could write a helper/utility technique to transform your complicated object to a map
  • Serializing the item to a platform-independent format like JSON and deserializing it earlier than use
  • Writing a customized codec for serialization/deserialization. Test FirestoreMessageCodec as a reference implementation

 

Packaging native code modifications

Flutter enables you to modify the native host app and construct a communication line with Dart through platform channels APIs. On this tutorial, we realized MethodChannel by updating the Kotlin-based host app straight. You can also use the identical method to reuse your Kotlin/Java libraries, name Android SDK APIs, or invoke any Kotlin code phase. You may reuse native code modifications in different Flutter apps, typically.

For instance, for those who use MethodChannel to vibrate the person’s system, it’s possible you’ll want the identical native implementation in your different apps. The Flutter SDK provides a fully-featured plugin system to create, publish, and combine shareable plugins.

Assume that it’s essential use the Kotlin-based random quantity generator technique in a number of Flutter apps. Then, you possibly can create a Flutter plugin and import it slightly than modifying each native host app. Test the official documentation to get began with Flutter plugin improvement and examine the shared_preferences plugin to be taught the really helpful Flutter plugin construction.

MethodChannel vs. EventChannel vs. BasicMessageChannel

The BasicMessageChannel class can be part of the Flutter platform channels API. It helps you implement low-level communication strains with customized codecs. Selecting essentially the most appropriate platform channels class for connecting Kotlin with Dart will assist encourage you to maintain your codebase readable, environment friendly, and minimal.

Take a look at the next comparability desk:

Comparability issue MethodChannel EventChannel BasicMessageChannel
Communication sort Request-response (RPC-like) sort technique invocation Occasion-driven stream Low-level messages
Path Bi-directional Bi-directional Bi-directional
An instance generic use case Calling native codes Subscribing to native occasions Implementing customized codecs

Conclusion

We studied the Flutter platform channels API and examined the MethodChannel class with sensible examples on this tutorial. Additionally, we turned accustomed to the EventChannel class that helps us create event-driven communication streams with the native host app. This tutorial targeted on calling Kotlin code from Flutter, however the Flutter framework enables you to name different platform languages too.

We usually should name Kotlin code both to reuse it or to name Android SDK capabilities. When you’ve migrated to Flutter from a local Android app, however you continue to have a number of enterprise logic written in a Kotlin/Java package deal or it’s essential reuse your Java-based internet API’s enterprise logic, you need to use MethodChannel for calling your current Kotlin code effectively. For many Android SDK capabilities, you could find pre-implemented plugins. So, test current open supply group plugins earlier than making a MethodChannel for calling native SDKs.

The MethodChannel API doesn’t provide code era, so we’ve got to make use of conditional statements to differentiate technique calls and go arguments through dynamic Dart maps. Moreover, it doesn’t assure sort security. When you search such options, take a look at the pigeonpackage deal.

Total, the MethodChannel API is an environment friendly, minimal, dynamic, and inbuilt mechanism that we will use to name Kotlin code out of your Flutter app.

: Full visibility into your internet and cellular apps

LogRocket is a frontend utility monitoring resolution that allows you to replay issues as in the event that they occurred in your individual browser. As a substitute of guessing why errors occur, or asking customers for screenshots and log dumps, LogRocket enables you to replay the session to shortly perceive what went improper. It really works completely with any app, no matter framework, and has plugins to log extra context from Redux, Vuex, and @ngrx/retailer.

Along with logging Redux actions and state, LogRocket information console logs, JavaScript errors, stacktraces, community requests/responses with headers + our bodies, browser metadata, and customized logs. It additionally devices the DOM to file the HTML and CSS on the web page, recreating pixel-perfect movies of even essentially the most complicated single-page and cellular apps.

.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments