Chuyển đến nội dung chính

レッスン 15: プラットフォーム チャネルとネイティブ統合

メソッドチャネル、イベントチャネル。 Flutter (iOS/Android) からネイティブ コードを呼び出します。ピジョンコードの生成。 C/C++ ライブラリの FFI。プラグイン開発。

💻 プログラミング — レッスン 15 レッスン 15: プラットフォーム チャネルとネイティブ 統合

フラッター&ダーツ: 基本から上級まで

パート 4: 高度な UI と機能

xdev.asia

1.メソッドチャネル

// Dart side
class BatteryService {
  static const _channel = MethodChannel('com.example.app/battery');

  Future<int> getBatteryLevel() async {
    final level = await _channel.invokeMethod<int>('getBatteryLevel');
    return level ?? -1;
  }
}
// Android — MainActivity.kt
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 ->
                when (call.method) {
                    "getBatteryLevel" -> {
                        val batteryManager = getSystemService(BATTERY_SERVICE) as BatteryManager
                        val level = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
                        result.success(level)
                    }
                    else -> result.notImplemented()
                }
            }
    }
}
// iOS — AppDelegate.swift
@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: "com.example.app/battery", binaryMessenger: controller.binaryMessenger)

        channel.setMethodCallHandler { (call, result) in
            if call.method == "getBatteryLevel" {
                UIDevice.current.isBatteryMonitoringEnabled = true
                let level = Int(UIDevice.current.batteryLevel * 100)
                result(level)
            } else {
                result(FlutterMethodNotImplemented)
            }
        }

        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

2. EventChannel — ネイティブからのストリーム

// Dart side — lắng nghe sensor
class AccelerometerService {
  static const _channel = EventChannel('com.example.app/accelerometer');

  Stream<AccelerometerData> get stream {
    return _channel.receiveBroadcastStream().map((event) {
      final data = event as Map;
      return AccelerometerData(
        x: data['x'] as double,
        y: data['y'] as double,
        z: data['z'] as double,
      );
    });
  }
}

3. Pigeon — タイプセーフなコード生成

// pigeons/messages.dart
import 'package:pigeon/pigeon.dart';

class SearchRequest {
  String? query;
  int? limit;
}

class SearchResponse {
  List<String?>? results;
}

@HostApi()
abstract class SearchApi {
  SearchResponse search(SearchRequest request);
}
# Generate
dart run pigeon --input pigeons/messages.dart \
    --dart_out lib/src/generated/messages.g.dart \
    --kotlin_out android/app/src/main/kotlin/Messages.g.kt \
    --swift_out ios/Runner/Messages.g.swift

4.ダーツFFI

import 'dart:ffi';

typedef NativeAdd = Int32 Function(Int32, Int32);
typedef DartAdd = int Function(int, int);

final dylib = DynamicLibrary.open('libnative.so');

final add = dylib.lookupFunction<NativeAdd, DartAdd>('add');

void main() {
  print(add(3, 5)); // 8
}

次の記事: プッシュ通知とバックグラウンドタスク。