Flutter에서 Native 코드와 통신하기
Flutter는 Android와 iOS 네이티브 코드와의 통신을 지원하여 플랫폼별 기능을 활용할 수 있습니다. 이를 통해 카메라, 위치 서비스, 센서 데이터 등 Flutter에서 직접 제공하지 않는 네이티브 기능을 사용할 수 있습니다. 이번 글에서는 Flutter에서 네이티브 코드와 통신하는 방법과 주요 기법을 소개합니다.
1. 플랫폼 채널 (Platform Channel) 소개
Flutter와 네이티브 코드(Android: Kotlin/Java, iOS: Swift/Objective-C) 간 데이터와 명령을 주고받기 위해 **플랫폼 채널 (Platform Channel)**을 사용합니다.
플랫폼 채널 흐름
- Flutter 코드에서 MethodChannel을 통해 네이티브 코드 호출
- 네이티브 코드에서 명령 처리 후 결과 반환
- Flutter 코드가 결과 수신 후 UI 업데이트
2. 플랫폼 채널 기본 구현
Flutter 코드 작성
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
class NativeCommunicationExample extends StatefulWidget {
@override
_NativeCommunicationExampleState createState() => _NativeCommunicationExampleState();
}
class _NativeCommunicationExampleState extends State<NativeCommunicationExample> {
static const platform = MethodChannel('com.example/native');
String _batteryLevel = 'Unknown battery level';
Future<void> _getBatteryLevel() async {
try {
final int result = await platform.invokeMethod('getBatteryLevel');
setState(() {
_batteryLevel = 'Battery level: $result%';
});
} on PlatformException catch (e) {
setState(() {
_batteryLevel = "Failed to get battery level: '${e.message}'";
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Native Communication Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_batteryLevel),
ElevatedButton(
onPressed: _getBatteryLevel,
child: Text('Get Battery Level'),
),
],
),
),
);
}
}
Android 코드 작성 (Kotlin)
MainActivity.kt 파일에 네이티브 코드 추가:
package com.example.app
import android.os.BatteryManager
import android.content.Context
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/native"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
} else {
result.notImplemented()
}
}
}
private fun getBatteryLevel(): Int {
val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
}
}
iOS 코드 작성 (Swift)
AppDelegate.swift 파일에 네이티브 코드 추가:
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "com.example/native",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
if call.method == "getBatteryLevel" {
self.receiveBatteryLevel(result: result)
} else {
result(FlutterMethodNotImplemented)
}
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func receiveBatteryLevel(result: FlutterResult) {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
if device.batteryState == .unknown {
result(FlutterError(code: "UNAVAILABLE",
message: "Battery level not available.",
details: nil))
} else {
result(Int(device.batteryLevel * 100))
}
}
}
3. 에러 처리 및 디버깅
플랫폼 코드 오류 처리
- Android: result.error("CODE", "MESSAGE", null)으로 오류 반환
- iOS: FlutterError 객체로 오류 반환
디버깅 팁
- adb logcat 명령어로 Android 로그 확인
- Xcode Debugger로 iOS 로그 확인
4. 플러그인 개발 시 고려 사항
- 플랫폼 별 코드 관리:
네이티브 코드가 복잡해질 경우 별도의 파일로 분리하여 유지보수성을 높입니다. - 비동기 처리:
네이티브 작업이 오래 걸리는 경우 반드시 비동기 처리를 사용해 UI 블록을 방지합니다. - 테스트:
Flutter 쪽 테스트뿐만 아니라 네이티브 코드에 대한 단위 테스트도 작성합니다.
5. 결론
Flutter에서 네이티브 코드와 통신하면 플랫폼 고유의 기능을 활용하여 더 강력한 앱을 개발할 수 있습니다. 이번 글에서 소개한 플랫폼 채널 기법을 활용해 다양한 네이티브 기능을 프로젝트에 통합해 보세요.
'Flutter' 카테고리의 다른 글
Flutter에서 앱 아이콘 변경하기 (0) | 2025.02.19 |
---|---|
Flutter에서 SOLID 원칙을 따르는 코드 작성법 (0) | 2025.02.02 |
Flutter WebRTC: 실시간 통신 앱 개발 가이드 (0) | 2025.01.31 |
Flutter에서의 프로파일링(Profiling) 기법 및 성능 최적화 방법 (0) | 2025.01.31 |
Flutter에서 스플래시 화면(Splash Screen) 만들기 (0) | 2025.01.31 |