MethodChannel in Flutter
This story is about platform-specific codes in Flutter. Sometimes we need to write Java or Kotlin for Android devices, and Swift or Objective-C for iOS devices. There are many reasons to do this like unavailable Flutter package about our needs or maybe we have already written native functions to use in native projects, and want to integrate that code into the Flutter app.
Today, I’ll send a model to the native side, and modify it there, and retrieve the newer model. First, I need to import services to define the MethodChannel:
import 'package:flutter/services.dart';static const platformMethodChannel =
const MethodChannel('com.methodchannel/test');
Then, I’m sending the model which contains ‘id’ and ‘title’ in any method with invokeMethod:
var response = await platformMethodChannel
.invokeMethod('getModel', {'id': 1, 'title': 'Story'});
On the native side, I have a Java model class. I override the ‘toString()’ method of this class to serialize a JSON like this:
class NewModel {
public int id;
public String title;
@Override
public String toString() {
return "{\"id\": " + id + ",\"title\": \"" + title + "\"}";
}
}
And in MainActivity.java, I defined the channel and override the ‘onCreate()’ method like this:
private static final String CHANNEL = "com.methodchannel/test";@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this); new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, Result result)
{
if (methodCall.method.equals("getModel"))
{
String title = methodCall.argument("title");
int id = methodCall.argument("id");
NewModel model = new NewModel();
model.id = id;
model.title = "Android model is here!
And passed argument: " + title;
result.success(model.toString());
}
}
}
);
}
In here, ‘methodCall.argument’ helps me to get the parameter from the Dart side.
After this, I can retrieve the result message by decoding the JSON:
NewModel _message = NewModel.fromJson(json.decode(response));
I’m not so familiar with Obj-C and Swift but this is a simple implementation of getting parameters and modifying and returning as a model in AppDelegate.m file:
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
FlutterViewController* controller =
(FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel* nativeChannel = [FlutterMethodChannel
methodChannelWithName:@"com.methodchannel/test"
binaryMessenger:controller];[nativeChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
if ([@"getModel" isEqualToString:call.method]) {
NSString* title = call.arguments[@"title"];
title =
[title stringByAppendingString:@" is coming from dart!"];
NSString *result = @"{\"id\":1,\"title\":\"";
result = [result stringByAppendingString:title];
result = [result stringByAppendingString:@"\"}"];
result(result);
} else {
result(FlutterMethodNotImplemented);
}
}]; [GeneratedPluginRegistrant registerWithRegistry:self];
return [super application:application
didFinishLaunchingWithOptions:launchOptions];
}
Here is demonstrated Dart values in other languages:
You can access the source code of this story on my Github repository. The next story is about importing a Flutter module into an existing Android app if I solve this issue.