Code spécifique à la plateforme Flutter
Cette section présentera comment utiliser les canaux de plateforme pour appeler du code natif de plateforme dans Flutter.
Aperçu des canaux de plateforme
Les canaux de plateforme permettent au code Dart de communiquer avec les plateformes natives (iOS/Android).
| Type | Description |
|---|---|
| MethodChannel | Canaux de méthode, utilisés pour appeler des méthodes de plateforme |
| EventChannel | Canaux d'événements, utilisés pour le streaming de données |
Appel côté Dart
Exemple : utilisation de MethodChannel
import 'package:flutter/services.dart';
// Définir le canal
class PlatformChannel {
static const MethodChannel _channel = MethodChannel('my_app/channel');
// Appeler la méthode native - obtenir le niveau de batterie
static Future<int> getBatteryLevel() async {
try {
final int batteryLevel = await _channel.invokeMethod('getBatteryLevel');
return batteryLevel;
} on PlatformException catch (e) {
print('Impossible d'obtenir le niveau de batterie : ${e.message}');
return -1;
}
}
// Appeler la méthode native - afficher un Toast
static Future<void> showToast(String message) async {
try {
await _channel.invokeMethod('showToast', {'message': message});
} on PlatformException catch (e) {
print('Échec de l’affichage du Toast : ${e.message}');
}
}
// Appeler la méthode native - obtenir les informations de l’appareil
static Future<Map<String, dynamic>> getDeviceInfo() async {
try {
final result = await _channel.invokeMapMethod('getDeviceInfo');
return result ?? {};
} on PlatformException catch (e) {
print(Échec de l’obtention des informations de l’appareil : ${e.message});
return {};
}
}
}
// Exemple d'utilisation
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async {
final battery = await PlatformChannel.getBatteryLevel();
print(Niveau de la batterie : $battery%);
},
child: const Text(Obtenir le niveau de la batterie),
);
}
}
// Définir le canal
class PlatformChannel {
static const MethodChannel _channel = MethodChannel('my_app/channel');
// Appeler la méthode native - obtenir le niveau de batterie
static Future<int> getBatteryLevel() async {
try {
final int batteryLevel = await _channel.invokeMethod('getBatteryLevel');
return batteryLevel;
} on PlatformException catch (e) {
print('Impossible d'obtenir le niveau de batterie : ${e.message}');
return -1;
}
}
// Appeler la méthode native - afficher un Toast
static Future<void> showToast(String message) async {
try {
await _channel.invokeMethod('showToast', {'message': message});
} on PlatformException catch (e) {
print('Échec de l’affichage du Toast : ${e.message}');
}
}
// Appeler la méthode native - obtenir les informations de l’appareil
static Future<Map<String, dynamic>> getDeviceInfo() async {
try {
final result = await _channel.invokeMapMethod('getDeviceInfo');
return result ?? {};
} on PlatformException catch (e) {
print(Échec de l’obtention des informations de l’appareil : ${e.message});
return {};
}
}
}
// Exemple d'utilisation
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async {
final battery = await PlatformChannel.getBatteryLevel();
print(Niveau de la batterie : $battery%);
},
child: const Text(Obtenir le niveau de la batterie),
);
}
}
Implémentation Android (Kotlin)
Exemple : code côté Android
// MainActivity.kt
package com.example.my_app
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
private val CHANNEL = "my_app/channel"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"getBatteryLevel" -> {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Impossible d'obtenir le niveau de la batterie", null)
}
}
"showToast" -> {
val message = call.argument<String>("message")
showToast(message!!)
result.success(null)
}
else -> {
result.notImplemented()
}
}
}
}
private fun getBatteryLevel(): Int {
return try {
val batteryManager = getSystemService(BATTERY_SERVICE) as BatteryManager
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} catch (e: Exception) {
-1
}
}
private fun showToast(message: String) {
android.widget.Toast.makeText(this, message, android.widget.Toast.LENGTH_SHORT).show()
}
}
package com.example.my_app
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
private val CHANNEL = "my_app/channel"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"getBatteryLevel" -> {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Impossible d'obtenir le niveau de la batterie", null)
}
}
"showToast" -> {
val message = call.argument<String>("message")
showToast(message!!)
result.success(null)
}
else -> {
result.notImplemented()
}
}
}
}
private fun getBatteryLevel(): Int {
return try {
val batteryManager = getSystemService(BATTERY_SERVICE) as BatteryManager
batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} catch (e: Exception) {
-1
}
}
private fun showToast(message: String) {
android.widget.Toast.makeText(this, message, android.widget.Toast.LENGTH_SHORT).show()
}
}
Implémentation iOS (Swift)
Exemple : code côté iOS
// AppDelegate.swift
import Flutter
import UIKit
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
private let CHANNEL = "my_app/channel"
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(
name: CHANNEL,
binaryMessenger: controller.binaryMessenger
)
channel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
switch call.method {
case "getBatteryLevel":
self.getBatteryLevel(result: result)
case "showToast":
if let args = call.arguments as? [String: Any],
let message = args["message"] as? String {
self.showToast(message: message)
result(nil)
}
default:
result(FlutterMethodNotImplemented)
}
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func getBatteryLevel(result: @escaping FlutterResult) {
UIDevice.current.isBatteryMonitoringEnabled = true
let batteryLevel = UIDevice.current.batteryLevel
if batteryLevel < 0 {
result(FlutterError(code: "UNAVAILABLE", message: "Impossible d'obtenir le niveau de la batterie", details: nil))
} else {
result(Int(batteryLevel * 100))
}
}
private func showToast(message: String) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
present(alert, animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
alert.dismiss(animated: true)
}
}
}
import Flutter
import UIKit
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
private let CHANNEL = "my_app/channel"
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(
name: CHANNEL,
binaryMessenger: controller.binaryMessenger
)
channel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
switch call.method {
case "getBatteryLevel":
self.getBatteryLevel(result: result)
case "showToast":
if let args = call.arguments as? [String: Any],
let message = args["message"] as? String {
self.showToast(message: message)
result(nil)
}
default:
result(FlutterMethodNotImplemented)
}
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func getBatteryLevel(result: @escaping FlutterResult) {
UIDevice.current.isBatteryMonitoringEnabled = true
let batteryLevel = UIDevice.current.batteryLevel
if batteryLevel < 0 {
result(FlutterError(code: "UNAVAILABLE", message: "Impossible d'obtenir le niveau de la batterie", details: nil))
} else {
result(Int(batteryLevel * 100))
}
}
private func showToast(message: String) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
present(alert, animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
alert.dismiss(animated: true)
}
}
}
autres extensionsLes canaux de plateforme sont le principal moyen pour Flutter de communiquer avec du code natif, couramment utilisés pour appeler des API système, des fonctionnalités matérielles ou utiliser des SDK natifs tiers.