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")