플러터만으로도 대부분의 기능들을 편리하게 사용할 수 있지만, 안드로이드 시스템 API를 사용해야 한다거나, 성능상의 문제로 native 코드를 작성해야 하는 경우가 있다. native code 와 병행해서 만들어진 flutter package 들도 아주 많다. 어떻게 flutter 에서 native 로 작성된 코드를 호출할 수 있는지 정리해 보았다.
Android Native 와 통신
위 구조에서 확인할 수 있듯이 MethodChannel을 통해 iOS 또는 Android 플랫폼과 데이터를 주고 받을 수 있으며, MethodChannel 은 비동기적으로 동작하므로 await 를 사용한다.
- flutter 코드 예제
class _NativeAppState extends State<NativeApp> {
static const platform = MethodChannel('insomnia.example.native/info', 'model');
String _deviceInfo = 'Unknown info';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Native 통신 예제'),
),
body: Center(
child: Text(
_deviceInfo,
style: const TextStyle(
fontSize: 30,
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_getDeviceInfo();
},
child: const Icon(Icons.get_app),
),
);
}
Future<void> _getDeviceInfo() async {
String deviceInfo;
try {
final String result = await platform.invokeMethod('getDeviceInfo');
deviceInfo = 'Device info:\n$result';
}
on PlatformException catch (e) {
deviceInfo = 'Failed to get Device info : ${e.message}.';
}
on MissingPluginException catch (e) {
deviceInfo = 'No Method : ${e.message}.';
}
setState(() {
_deviceInfo = deviceInfo;
});
}
}
- MethodChannel(key) 형태로 사용하여 채널 객체를 얻어오고, _getDeviceInfo() 함수에서 채널 객체의 invokeMethod(methodName, argument) 를 사용하여 안드로이드 native 의 API를 호출한다.
- 여러개의 argument 를 전달하기 위해서는 argument들을 List type 으로 묶어 보내주면 된다.
(여러개의 결과값을 받으려면 invokeMethod 대신 invokeListMethod 를 사용할 수 있다.) - MethodChannel 의 parameter 로 입력하는 key 값은 임의의 String 을 입력하여도 문제없이 동작한다.
- invokeMethod 는 비동기이므로 return 값을 받으려면 await 가 필요하다. (.then을 사용하여도 될 것이다..)
- kotlin 코드 예제
class MainActivity: FlutterActivity() {
private val CHANNEL = "insomnia.example.native/info"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call, result ->
if(call.method == "getDeviceInfo") {
val deviceInfo = getDeviceInfo(call.arguments.toString())
result.success(deviceInfo)
}
}
}
private fun getDeviceInfo(): String {
return when(arg) {
"device" -> Build.DEVICE
"brand" -> Build.BRAND
"model" -> Build.MODEL
"product" -> Build.PRODUCT
else -> {
val sb = StringBuffer()
sb.append(Build.DEVICE + "\n")
sb.append(Build.BRAND + "\n")
sb.append(Build.MODEL + "\n")
sb.append(Build.PRODUCT + "\n")
sb.toString()
}
}
}
}
- flutter 에서 invokeMethod 를 호출하면 configureFlutterEngine 함수가 호출되는데 invokeMethod 사용시 입력한 parameter 가 각각 call.method, call.arguments 로 넘어오게 된다.
- call.method 를 통해 동작을 구현한 kotlin 코드를 실행할 수 있고, call.arguments 를 통해 flutter로부터 넘겨받은 데이터를 처리할 수 있다.
- kotiln 코드 작업시에는 flutter project 에서 작업하지 말고 flutter project 폴더 하위의 android 폴더를 android project 로 별도로 open 해야 kotlin class 들을 편집하기가 편리하다. 그냥 flutter project 에서 kotlin 파일 작업시 intellisense 가 작동하지 않는다.
iOS native 와 통신
아마 안드로이드 네이티브 통신과 비슷한 방식으로 구현할 수 있지 않을까 싶다. ㅋㅋㅋ
관련 링크 (공식 홈피)
https://flutter.dev/docs/development/platform-integration/platform-channels
반응형
'프로그래밍 > flutter' 카테고리의 다른 글
GoogleSignInPlugin.java uses or overrides a deprecated API. 오류처리 (0) | 2021.12.12 |
---|---|
Stateful Widget Lifecycle (위젯 생명주기) (0) | 2021.12.06 |
android simulator 에서 dart process stop 불가 현상 (0) | 2021.10.12 |
android studio project window color 의미 (0) | 2021.10.11 |
flutter 에서 page 이동시 argument 전달 (0) | 2021.10.03 |