Native APIs with Platform Channels

Flutter is a cross platform framework, meaning you must call native APIs to get access to native platform functions, such as telephony or camera services. Flutter does this, by creating a PlatformChannel, to the native platform. Through these channels, they can call methods.

Native Platform Channel

You need to setup a channel on each platform. These are called MethodChannels on Android, or FlutterMethodChannel on iOS. You can call the channel anything you want, in this example buildflutter.com/platform. Inside this channel, you can perform an action dependant upon a method you call. These method names are just strings, and are also entirely up to you, in regards to naming. In this example, I use getResult.

Android

In android > app > src > main > java > com.yourcompany.flutterapp > MainActivity.java you can add MethodChannel in your onCreate method.

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

...

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  GeneratedPluginRegistrant.registerWith(this);
  new MethodChannel(getFlutterView(), "buildflutter.com/platform").setMethodCallHandler(
          new MethodCallHandler()
          {
            @Override
            public void onMethodCall(MethodCall call, Result result) {
                if (call.method.equals("getResult"))
                  result.success(5);
            }
          });
}

iOS

In iOS > Runner > AppDelegate.m and in didFinishLaynchingWithOptions, create a FlutterMethodChannel, and handle the getResult method.

#import <Flutter/Flutter.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];

  FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;

  FlutterMethodChannel* channel = [FlutterMethodChannel
                                   methodChannelWithName:@"buildflutter.com/platform"
                                   binaryMessenger:controller];

  [batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    if ([@"getResult" isEqualToString:call.method]) {
          result(5);
        }
  }];

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

Call Platform Channel Method

After implementing the native platform code, we can now use the Channel buildflutter.com/platform to call the method getResult. Import the following.

import 'package:flutter/services.dart';
import 'dart:async';

In your state, create a new MethodChannel that is initialized to buildflutter.com/platform.

class _MyHomePageState extends State<MyHomePage> {
  static const platform = const MethodChannel('buildflutter.com/platform');
  int _counter = 0;

Create a new method that calls the MethodChannel and invokes getResult().

Future<Null> _callNativeMethod() async {
  int result = 0;
  try {
    result = await platform.invokeMethod('getResult');
  } on PlatformException catch (e) {
    result = 0;
  }

  setState(() {
    _counter = result;
  });
}

I now can call this method from my UI, and it will make a call on the Channel buildflutter.com/platform and invoke the method getResult(). The native platform specific code will run, and return the result.

Mobile Developer, Microsoft & Xamarin MVP

Share on
© 2018 Adam Pedley