[Android] Method Channel

Minji Jeong·2023년 12월 31일
0

Android

목록 보기
38/39
post-thumbnail

플러터로 개발을 하다보면 종종 블루투스 같은 네이티브(Android, iOS) 플랫폼의 기능이 필요할 때가 있습니다. 네이티브 플랫폼의 기능을 사용하기 위해 플러터에서 네이티브 메서드를 호출해야할 때도 있고, 역의 기능이 필요할 때도 있습니다. 이렇게 네이티브 - 플러터 간 커뮤니케이션이 필요한 경우, 우리는 Host Platform Language(Kotlin, Swift)와 Dart 간 다리 역할을 하는 플랫폼 채널을 이용해야합니다.

Platform Channel


Platform Channel은 Dart와 Host Platform Language 간 비동기로 통신할 수 있도록 메커니즘을 제공하는 커뮤니케이션 채널입니다. 이 Platform Channel을 통해 플러터에서 호스트 플랫폼의 API를 사용할 수 있습니다.

플러터에서 제공하는 3가지의 플랫폼 채널은 다음과 같습니다.

  1. MethodChannel
  2. EventChannel
  3. BasicMessageChannel

주로 사용되는 것은 MethodChannel과 EventChannel입니다. MethodChannel 및 EventChannel 모두 양방향 통신이 가능하지만, MethodChannel은 단기적 이벤트를 발생시키는 채널이고, EventChannel은 Stream 비동기 방식으로 변경이 발생할 때마다 이벤트를 발생시킨다는 점에서 차이가 있습니다. 해당 포스팅에선 MethodChannel에 대해 소개하며, 예제 코드로 사용되는 호스트 플랫폼은 안드로이드입니다.

MethodChannel

MethodChannel은 플러터와 호스트 플랫폼 간 커뮤니케이션, 즉 각 사이드에 있는 특정 method를 단발적으로 호출하여 원하는 동작을 실행하거나 그에 대한 결과값을 수신 할 수 있도록 해주는 채널입니다.

Method Channel의 특징은 다음과 같습니다.

  1. 양방향 통신 지원
  • 호스트 플랫폼의 메서드를 호출하거나 호스트 플랫폼에서 플러터의 메서드를 호출하여 결과를 비동기적으로 수신할 수 있습니다.
  1. Flutter-to-Native
  • 호스트 플랫폼의 메서드를 호출하기 위해 invokeMethod를 호출합니다.
  1. Native-to-Flutter
  • 플러터의 메서드를 호출하기 위해 invokeMethod를 호출합니다.
  • 호출한 코드가 실행이 끝난 후, 결과값을 받아 플러터에서 사용할 수 있습니다.

Method Channel을 사용하기 위해서 고유하고 설명이 포함된 채널명을 정의해야 하며, 채널명은 플러터와 호스트 플랫폼 모두에서 동일해야 합니다.

// dart
class MethodChannel {
    static const MAIN_CHANNEL = "com.example.flutter.main.service"
}

// kotlin
companion object {
    const val MAIN_CHANNEL = "com.example.flutter.main.service"
}

아래와 같은 방식으로 플러터에서 호스트 플랫폼의 메서드를 호출할 수 있습니다.

Future<void> _directToMethodChannel() async {
   final methodChannel = MethodChannel(MethodChannel.MAIN_CHANNEL);
   await methodChannel.invokeMethod('method_name', null);
}

만약 호스트 플랫폼 메서드에 인자를 전달해야 한다면 다음과 같이,

Future<void> _saveUserName(String userName) async {
   methodChannel.invokeMethod('method_name', userName);
}

호스트 플랫폼 메서드로부터 값을 받고 싶다면 다음과 같이 작성합니다.

Future<String> _loadUserName() async {
   final response = await methodChannel.invokeMethod('method_name', null);
   return response;
}

이제 호스트 플랫폼-안드로이드에서 사용할 Method channel을 등록하기 위해 FlutterActivity를 상속한 액티비티에서 configureFlutterEngine을 오버라이드 해준 후, method call handler를 등록해줍니다.

class ExampleActivity: FlutterActivity() {

// Android
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, MAIN_CHANNEL).setMethodCallHandler {
      call, result ->
      // This method is invoked on the main thread.
      // TODO
    }
  }
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, MAIN_CHANNEL).setMethodCallHandler {
      call, result ->
        if (call.method == "method_name") {
           val userName = "Lina"
           result.success(userName)
        } else {
           result.error(..)
        }
  }

Method channel은 여러 메서드 시그니처들로 구성된 네임스페이스와 같으므로 하나의 Method channel로 여러 메서드들을 실행할 수 있습니다. Method channel의 특정 메서드가 플러터 쪽에서 호출되었을 때 원하는 작업을 실행하기 위해 다음과 같이 분기문을 사용하여 안드로이드 쪽에서 결과값 또는 에러를 핸들링할 수 있도록 합니다.

if (call.method == "method_name") {
    val userName = "Lina"
    result.success(userName)
}

만약 안드로이드에서 플러터의 특정 메서드를 호출하고 싶다면 FlutterActivity 내에서 invokeMethod를 사용해 해당 메서드를 호출합니다.

methodChannel.invokeMethod('method_name')

References

https://blog.logrocket.com/using-flutters-methodchannel-invoke-kotlin-code-android/
https://medium.com/@sdycode/event-channel-method-channel-in-flutter-e6f697472189
https://velog.io/@tygerhwang/FlutterKotlinSwift-%EC%98%88%EC%A0%9C%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%ED%86%B5%EC%8B%A0-Platform-Channel%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

profile
Mobile Software Engineer

0개의 댓글