Kiedy pracujemy z cross-platformowym frameworkiem, nie można zagwarantować, że będziemy pracować tylko z tym frameworkiem bez żadnej pracy w natywnym kodzie. Deweloperzy najprawdopodobniej będą uciekać się do natywnego albo z powodu funkcji, których framework jeszcze nie dostarczył, albo z powodu problemów z wydajnością, które mogą być rozwiązane tylko w natywnym. Kanały platformy są metodą, w której można napisać specyficzny dla danej platformy natywny kod do wykorzystania w swoich aplikacjach Flutter.
Standardowe kanały platformy używają standardowego kodeka wiadomości, który obsługuje wydajną binarną serializację prostych wartości podobnych do JSON, takich jak booleans, liczby, Strings, bufory bajtowe, a także listy i mapy tych. Serializacja i deserializacja tych wartości do i z wiadomości dzieje się automatycznie podczas wysyłania i odbierania wartości.
Platform Channel składa się z trzech części: Klasa MethodChannel na Flutter, Klasa MethodChannel na Android i Klasa FlutterMethodChannel na iOS.
Zaletą Fluttera jest to, że wykorzystuje elastyczny system, który pozwala na wywołanie API specyficznych dla danej platformy, czy to dostępnych w kodzie Kotlin lub Java na Androidzie, czy w kodzie Swift lub Objective-C na iOS.
Ten tutorial pokazuje jak stworzyć funkcję Fluttera, która wywołuje natywny kod Androida i iOS.
Wywoływanie natywne z Flutter
Aplikacja będzie wywoływała funkcję zgodnie z jej nazwą, a program będzie szukał jej implementacji w kodzie Androida lub iOS.
Na początek utwórz MethodChannel.
Strony klienta i hosta kanału są połączone poprzez nazwę kanału przekazaną w konstruktorze kanału. Wszystkie nazwy kanałów używane w jednej aplikacji muszą być unikalne.
static final channelName = 'example.channel/native'; const methodChannel = MethodChannel(channelName);
Następnie należy utworzyć metodę, która będzie wywoływała określoną metodę na kanale platformy.
Future<void> _getBatteryLevel() async { String batteryLevel; try { batteryLevel = await platform.invokeMethod('getBatteryLevel'); } on PlatformException catch (e) { batteryLevel = e.message; } }
Android
Przejdź do katalogu z aplikacją Flutter i otwórz folder android w Android Studio.
Otwórz plik MainActivity.kt. Utwórz ten sam kanał, który zadeklarowałeś w swojej części Flutter.
private val channelName ='example.channel/native'
Następnie wewnątrz configureFlutterEngine() dodajemy handler wywołania metody.
MethodChannel(flutterEngine.dartExecutor.binaryMessage, channelName) .setMethodCallHandler { call, result -> if (call.method == "getBatteryLevel") { val batteryLevel = getBatteryLevel() result.success(batteryLevel) } else { result.notImplemented() } }
Następnie dodaj implementację metody, którą chcesz wywołać (w przykładzie funkcja getBatteryLevel() ).
iOS
Otwórz folder ios w XCode. Przejdź do pliku AppDelegate.swift i wewnątrz funkcji application:didFinishLaunchingWithOptions utwórz kanał.
override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let channelName = "example.channel/native" let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController let methodChannel = FlutterMethodChannel(name: channelName, binaryMessage: rootViewController) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) }
Następnie dodajemy handler wywołania metody.
methodChannel.setMethodCallHandler( {(call: FlutterMethodCall, result: FlutterResult) -> Void in guard call.method == "getBatteryLevel" else { result(FlutterMethodNotImplemented) return } self?.getBatteryLevel(result: result) })
Wytworzenie implementacji metody (na przykład getBatteryLevel).
Przykład odwrotny
Jeśli potrzebujesz wywołać metodę Flutter z natywnego kodu, wtedy wywołujesz te same metody z wcześniejszych, ale na odwrót.
Kod Flutter
static final channelName = 'example.channel/native'; const methodChannel = MethodChannel(channelName); methodChannel.setMethodCallHandler(_nativeMethodCallHandler); Future<dynamic> _nativeMethodCallHandler(MethodCall call) async { switch(call.method) { case "exampleMethod": //function call } }
Kod Android
val channelName = 'example.channel/native' val methodChannel = MethodChannel(flutterView, channelName) methodChannel.invokeMethod("exampleMethod")
Kod iOS
let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController let channelName ="example.channel/native" let methodChannel = FlutterEventChannel(name: channelName, binaryMessenger: rootViewController) methodChannel.invokeMethod("exampleMethod")