Módulo 04: Ecosistema Flutter Profesional

Method Channels

Integracion Nativa

# Method Channels: Comunicación con Nativo Aunque Flutter pinta sus propios píxeles, a veces necesitas acceder a APIs de la plataforma (cámara, GPS, sensores, batería) o usar librerías nativas existentes en Android (Java/Kotlin) o iOS (Obj-C/Swift). Los **Method Channels** son el puente para esto. ## Arquitectura La comunicación es asíncrona y basada en mensajes. 1. **Flutter (Cliente):** Envía un mensaje a través de un canal. 2. **Plataforma (Host):** Recibe el mensaje, ejecuta código nativo y devuelve una respuesta. ## Implementación en Flutter (Dart) ```dart import 'package:flutter/services.dart'; class BatteryService { // 1. Definir el canal (nombre único) static const platform = MethodChannel('com.example.app/battery'); Future getBatteryLevel() async { try { // 2. Invocar método final int result = await platform.invokeMethod('getBatteryLevel'); return 'Battery level: $result%'; } on PlatformException catch (e) { return "Failed to get battery level: '${e.message}'."; } } } ``` ## Implementación en Android (Kotlin) En tu `MainActivity.kt`: ```kotlin import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity: FlutterActivity() { private val CHANNEL = "com.example.app/battery" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "getBatteryLevel") { val batteryLevel = getBatteryLevel() // Tu lógica nativa if (batteryLevel != -1) { result.success(batteryLevel) } else { result.error("UNAVAILABLE", "Battery level not available.", null) } } else { result.notImplemented() } } } private fun getBatteryLevel(): Int { // Lógica real de Android... return 100 } } ``` ## Implementación en iOS (Swift) En tu `AppDelegate.swift`: ```swift import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let batteryChannel = FlutterMethodChannel(name: "com.example.app/battery", binaryMessenger: controller.binaryMessenger) batteryChannel.setMethodCallHandler({ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in if call.method == "getBatteryLevel" { // Tu lógica nativa result(100) } else { result(FlutterMethodNotImplemented) } }) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } ``` ## Tipos de Datos Flutter serializa automáticamente los tipos de datos comunes: | Dart | Android (Kotlin) | iOS (Swift) | |------|------------------|-------------| | null | null | nil | | bool | Boolean | Bool | | int | Int/Long | Int/NSNumber | | double | Double | Double/NSNumber | | String | String | String | | List | List | Array | | Map | HashMap | Dictionary | ## Event Channels Si necesitas un flujo continuo de datos (ej. datos del acelerómetro), usa `EventChannel`. - **Flutter:** `EventChannel('...').receiveBroadcastStream().listen(...)` - **Nativo:** Implementa `StreamHandler` (onListen, onCancel). ## Pigeon (Generación de Código) Escribir Method Channels manualmente es propenso a errores (typos en nombres, tipos incorrectos). **Pigeon** es una herramienta oficial que genera el código de "pegamento" (glue code) type-safe automáticamente. 1. Defines la interfaz en Dart. 2. Ejecutas Pigeon. 3. Implementas la interfaz generada en Android/iOS. 4. Llamas a la clase generada en Dart. ## Conclusión - Method Channels permiten a Flutter hablar con el mundo nativo. - Es comunicación asíncrona. - Usa `MethodChannel` para llamadas puntuales. - Usa `EventChannel` para streams de datos. - Considera **Pigeon** para proyectos grandes para garantizar seguridad de tipos.

Este apartado profundiza en los conceptos clave, proporcionando ejemplos prácticos y mejores prácticas para su aplicación en proyectos reales.

Al comprender estos detalles, podrás diseñar soluciones más robustas, mantenibles y escalables en tus aplicaciones Flutter y Dart.