Interakce mezi kódem Dart a nativními platformami je klíčovým úkolem při vývoji Flutter aplikací vyžadujících přístup k možnostem zařízení. Podle Flutter Team, 2026 zůstává Platform Channel hlavním mechanismem pro takovou integraci, zajišťující přenos zpráv mezi Dart a nativním kódem Android a iOS bez zapojení dalších nativních knihoven.
Hlavní body
Platform Channel je technologie Flutter, která zajišťuje obousměrnou komunikaci mezi kódem Dart aplikace a nativním kódem operačních systémů Android a iOS. Bez Platform Channel je Flutter aplikace omezena na možnosti poskytované frameworkem a nemůže přímo přistupovat k API kamery, senzorům, Bluetooth, souborovému systému a dalším nízkoúrovňovým funkcím zařízení.
Architektura Platform Channel je postavena na principu asynchronní výměny zpráv. Strana Dart odesílá požadavek kanálem, nativní strana jej zpracuje a vrátí výsledek. Všechny zprávy jsou serializovány do binárního formátu a přenášeny přes vyrovnávací paměť zpráv Flutter Engine, což zajišťuje minimální zpoždění při přenosu dat mezi běhovými prostředími.
Každý Platform Channel je identifikován jedinečným logickým názvem — řetězcem, který slouží jako adresa pro směrování zpráv. Strana Dart a nativní strana musí používat stejný název kanálu, aby byla komunikace správně navázána. Flutter podporuje libovolný počet kanálů v jedné aplikaci a každý kanál pracuje nezávisle na ostatních.
Podle oficiální dokumentace Flutter, Platform Channel zpracovává zprávy ve stejném pořadí, v jakém byly odeslány, což zaručuje předvídatelnost pořadí volání. To je kritické ve scénářích, kde pořadí zpracování ovlivňuje správnost fungování, například při sekvenční inicializaci nativních modulů nebo řetězci závislých operací.
Mechanismus přenosu zpráv prostřednictvím Platform Channel se skládá ze tří klíčových vrstev: strana Dart odesílá zprávu ve formě Map nebo List pomocí invokeMethod, Flutter Engine ji serializuje pomocí StandardMethodCodec a nativní strana přijímá volání ve svém handleru. Výsledek se vrací stejnou cestou v opačném směru.
Proces serializace automaticky převádí datové typy Dart na ekvivalenty na nativních platformách. Čísla, řetězce, booleovské hodnoty, seznamy a slovníky jsou podporovány bez dodatečné konfigurace ze strany vývojáře. Vlastní datové typy musí být serializovány ručně, například do JSON řetězce, před odesláním kanálem.
Na straně Flutter Engine zpráva vstupuje do fronty hlavního vlákna nativní platformy. V Android je to hlavní vlákno aplikace, v iOS — hlavní smyčka běhu. To znamená, že dlouhotrvající operace v handleru kanálu blokují uživatelské rozhraní a vedou k zamrzání. Vývojářům se doporučuje provádět těžké úlohy na vláknech na pozadí a vracet výsledek asynchronně prostřednictvím callbacku.
Výkon Platform Channel je dostatečně vysoký pro většinu scénářů použití: doba přenosu jedné zprávy je méně než 1 milisekunda na moderních zařízeních. Pro vysoce zatížené operace, jako je zpracování video streamu v reálném čase, se však doporučuje použít Dart FFI nebo nativní pluginy s přímým přístupem k paměti zařízení.
Klíčové omezení architektury: Platform Channel nepodporuje přenos deskriptorů souborů, paměťových ukazatelů nebo nativních objektů. Všechna data musí být serializovatelná do binárního formátu. Pro přenos velkého množství dat o velikosti megabajtů použijte dočasné soubory s přenosem cesty k nim kanálem.
Flutter poskytuje tři typy Platform Channel, každý určený pro specifický scénář interakce. Výběr správného typu kanálu určuje architekturu integrace a pohodlí údržby kódu na obou stranách — Dart a nativní, proto je důležité porozumět rozdílům mezi MethodChannel, EventChannel a BasicMessageChannel.
MethodChannel je nejrozšířenější typ Platform Channel, implementující vzor vzdáleného volání procedur. Dart odesílá název metody a argumenty, nativní strana provádí operaci a vrací výsledek. Každé volání vrací Future, což umožňuje použití konstrukcí async a await v kódu Dart pro pohodlnou asynchronní práci.
Tento typ kanálu je vhodný pro operace typu požadavek-odpověď: získání úrovně baterie, čtení dat senzorů, provádění výpočtů na nativní straně nebo vyžádání dat ze systémových služeb. MethodChannel podporuje standardní datové typy prostřednictvím StandardMethodCodec, včetně null hodnot díky podpoře Null safety v moderním Dart.
V reálných projektech se MethodChannel používá ve většině oficiálních Flutter pluginů. Například balíčky camera, battery a path_provider pracují právě prostřednictvím tohoto typu kanálu, poskytují přístup k nativním API bez nutnosti psát vlastní integrační kód pro každou platformu.
EventChannel je určen pro scénáře, kde nativní strana generuje nepřetržitý tok událostí v čase. Data jsou přenášena do Dart prostřednictvím Stream, umožňující odběr aktualizací v reálném čase. Typické příklady použití: údaje akcelerometru, GPS souřadnice, změny stavu Bluetooth a oznámení od systémových služeb.
Na rozdíl od MethodChannel, EventChannel používá model publikace-odběru. Nativní strana odesílá události, jak vznikají, bez explicitního požadavku z kódu Dart. Odběratel na straně Dart přijímá každou událost v samostatném prvku streamu a může filtrovat nebo transformovat přijatá data před použitím v rozhraní.
Při použití EventChannel je nutné správně spravovat odběry a jejich zrušení. Každé volání StreamSubscription by mělo být zrušeno po dokončení práce s kanálem, aby se předešlo úniku paměti na nativní straně. Platforma Flutter automaticky ruší stream při zničení widgetu, ale explicitní správa odběrů zvyšuje spolehlivost aplikace v dlouhodobých scénářích.
BasicMessageChannel je nejflexibilnější typ Platform Channel, určený pro libovolnou asynchronní výměnu zpráv. Na rozdíl od MethodChannel, kde každá zpráva obsahuje název metody a argumenty, BasicMessageChannel přenáší pouze užitečné zatížení bez vestavěného směrování. Odesílající strana pošle zprávu, přijímající strana ji zpracuje a vrátí odpověď.
Tento typ kanálu je vhodný pro vlastní protokoly interakce, kde se struktura zpráv může dynamicky měnit v závislosti na stavu aplikace. BasicMessageChannel standardně používá StandardMessageCodec, ale podporuje nahrazení libovolným MessageCodec pro nestandardní formáty serializace dat.
V praxi se BasicMessageChannel používá méně často než MethodChannel, protože vyžaduje ruční zpracování směrování zpráv bez vestavěného vzoru pojmenování. Je však nepostradatelný při integraci s nativními knihovnami, které očekávají specifický formát zpráv, odlišný od standardního vzoru požadavek-odpověď implementovaného v MethodChannel.
Podívejme se na praktickou implementaci Platform Channel na příkladu získání úrovně baterie zařízení. Tento příklad demonstruje celý pracovní cyklus: deklaraci MethodChannel na straně Dart, implementaci handleru na Android a iOS a také správné zpracování chyb při nedostupnosti dat nebo chybějících potřebných oprávněních.
Na straně Dart je vytvořena instance MethodChannel s jedinečným názvem kanálu jako řetězcem. Metoda invokeMethod odesílá požadavek na nativní stranu a očekává výsledek ve formě Future. Zpracování chyb se provádí zachycením PlatformException, kterou nativní strana vrací při výjimce v procesu zpracování požadavku.
import 'package:flutter/services.dart';
class BatteryPlugin {
static const _channel = MethodChannel(
'samples.flutter.dev/battery',
);
Future<String> getBatteryLevel() async {
try {
final result = await _channel.invokeMethod<int>(
'getBatteryLevel',
);
return 'Battery level: $result%';
} on PlatformException catch (e) {
return 'Failed: ${e.message}';
}
}
}
Na straně Android je handler registrován v MainActivity prostřednictvím metody configureFlutterEngine. Uvnitř setMethodCallHandler je zkontrolován název příchozí metody, provedeno nativní volání BatteryManager pro získání úrovně baterie a výsledek je vrácen prostřednictvím objektu result. Pro metody nepodporované kanálem je voláno result.notImplemented.
import android.os.BatteryManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
override fun configureFlutterEngine(
flutterEngine: FlutterEngine
) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
CHANNEL
).setMethodCallHandler { call, result ->
if (call.method == "getBatteryLevel") {
val level = getBatteryLevel()
if (level != -1) {
result.success(level)
} else {
result.error(
"UNAVAILABLE",
"Battery level not available",
null
)
}
} else {
result.notImplemented()
}
}
}
private fun getBatteryLevel(): Int {
val manager = getSystemService(BATTERY_SERVICE) as BatteryManager
return manager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY
)
}
}
Na platformě iOS je handler registrován ve třídě AppDelegate prostřednictvím FlutterMethodChannel. Swift kód přijímá příchozí volání, přistupuje k systémovému API UIDevice pro získání úrovně baterie a vrací výsledek do Flutter. Asynchronní zpracování s weak self umožňuje provádět požadavky bez rizika udržení cyklu silných referencí v paměti.
import UIKit
import Flutter
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
override func application(
application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(
name: "samples.flutter.dev/battery",
binaryMessenger: controller.binaryMessenger
)
channel.setMethodCallHandler { [weak self] call, result in
if call.method == "getBatteryLevel" {
let level = self?.getBatteryLevel() ?? -1
if level >= 0 {
result(level)
} else {
result(FlutterError(
code: "UNAVAILABLE",
message: "Battery level not available",
details: nil
))
}
} else {
result(FlutterMethodNotImplemented)
}
}
return super.application(
application: application,
didFinishLaunchingWithOptions: launchOptions
)
}
private func getBatteryLevel() -> Int {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
return Int(device.batteryLevel * 100)
}
}
Platform Channel je nezbytný v každém případě, kdy Flutter aplikace vyžaduje přístup k možnostem zařízení, které nejsou implementovány ve standardních balíčcích. Vývojář by měl vytvořit vlastní kanál při integraci s nativními SDK pro kameru, biometrii, NFC, Bluetooth Low Energy nebo při práci se souborovým systémem mimo sandbox aplikace.
První typický scénář — použití nativních API, ke kterým není přímý přístup z Dart. To zahrnuje systémové služby Android a iOS, hardwarové senzory s nestandardními protokoly přenosu dat, push oznámení s vlastní logikou zpracování a kryptografické operace vyžadující použití Hardware Security Module pro bezpečné ukládání klíčů.
Druhý scénář — integrace existujícího nativního kódu do Flutter projektu. Pokud společnost již vyvinula nativní knihovnu pro Android nebo iOS, Platform Channel umožňuje její opětovné použití bez portování na Dart. To urychluje migraci hybridních aplikací na Flutter a zachovává investice do existujícího nativního kódu a nahromaděné obchodní logiky.
Třetí scénář — publikace vlastního Flutter pluginu na pub.dev. Všechny populární pluginy používají Platform Channel pro poskytování jednotného API v Dart, které pod kapotou volá nativní kód každé platformy. Toto je standardní přístup doporučený týmem Flutter pro vytváření znovupoužitelných balíčků s podporou obou mobilních platforem.
Při výběru mezi vytvořením vlastního Platform Channel a použitím hotového balíčku z pub.dev se doporučuje nejprve zkontrolovat dostupnost hotového řešení. Balíčky camera, geolocator, shared_preferences a path_provider pokrývají většinu typických potřeb. Vlastní Platform Channel je ospravedlnitelný pouze při absenci vhodného balíčku nebo při potřebě hlubokého přizpůsobení nativního chování, které stávající řešení neposkytuje.
Často kladené otázky
MethodChannel implementuje vzor požadavek-odpověď s jednorázovým voláním metody a vrácením výsledku prostřednictvím Future. EventChannel používá streamový model: nativní strana odesílá události, jak vznikají, a Dart je přijímá prostřednictvím Stream. MethodChannel je vhodný pro jednorázové operace s očekáváním výsledku, EventChannel — pro nepřetržité datové toky v reálném čase.
Platform Channel podporuje základní typy Dart: int, double, bool, String, List a Map. Tyto typy jsou automaticky serializovány do nativních ekvivalentů prostřednictvím StandardMethodCodec a StandardMessageCodec bez účasti vývojáře. Pro přenos vlastních objektů je vyžadována ruční serializace do JSON nebo použití libovolného MessageCodec s podporou nestandardních formátů.
Ano, Flutter podporuje neomezený počet Platform Channel v jedné aplikaci. Každý kanál je identifikován jedinečným řetězcovým názvem, který musí souhlasit na straně Dart a nativní platformy. Lze vytvářet samostatné kanály pro různé moduly: jeden pro kameru, druhý pro Bluetooth, třetí pro senzory — všechny pracují nezávisle a neovlivňují vzájemný výkon.
Na straně Dart jsou chyby zpracovávány prostřednictvím PlatformException, kterou nativní strana vrací při výjimce. Blok try-catch zachycuje výjimku a poskytuje přístup ke kódu, zprávě a podrobnostem chyby. Na nativní straně volání result.error odesílá chybu zpět do Dart. K dispozici je také metoda result.notImplemented pro metody nepodporované kanálem.
Ano, handler Platform Channel se provádí na hlavním vlákně nativní platformy. Pokud handler provádí dlouhotrvající operaci — síťový požadavek, čtení z disku nebo těžké výpočty — uživatelské rozhraní může zamrznout. Doporučuje se spouštět těžké úlohy na vlákně na pozadí na nativní straně a volat result až po dokončení. Strana Dart přitom není blokována díky asynchronní povaze invokeMethod.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.