본문 바로가기
flutter

플러터 - BasicMessageChannel

by 들풀민들레 2023. 3. 13.

 

본 글은 [Do it! 깡샘의 플러터&다트 프로그래밍] 의 내용을 발췌한 것입니다.

 

 

책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.

 

플러터 앱에서 네이티브와 연동하는 방법으로 메시지 채널, 메서드 채널, 이벤트 채널을 제공합니다. 먼저 메시지 채널을 살펴보겠습니다. 메시지 채널은 다트와 네이티브 간에 문자열을 주고받을 때 사용합니다.


다트에서 네이티브로 보내기


메시지 채널을 이용해 다트에서 네이티브에 문자열 데이터를 보내는 방법을 살펴보겠습니다.


다트 코드
먼저 메시지 채널을 사용하는 다트 코드를 살펴보겠습니다. 플러터는 BasicMessageChannel 클래스를 제공합니다. 이 클래스를 이용해 네이티브와 연동할 수 있는 채널을 만들고 이 채널을 통해 데이터를 보냅니다.
다음 코드에서 BasicMessageChannel 생성자의 첫 번째 매개변수로 지정한 문자열은 채널의 이름입니다. 두 번째 매개변수에 지정한 StringCodec() 함수는 다트와 네이티브 간에 주고받는 바이너리와 문자열을 변환해 줍니다.

const channel = BasicMessageChannel<String>('myMessageChannel', StringCodec());
String? result = await channel.send('Hello from Dart');

채널 이름은 임의로 작성하며 네이티브 코드에서는 이 이름으로 채널을 선언해야 합니다. 즉, 다트의 채널 이름과 네이티브의 채널 이름이 같아야 합니다. 그리고 채널 이름을 다르게 해서 한 앱에서 네이티브와 연동하는 여러 채널을 이용해도 됩니다.
채널을 만들었으면 채널 객체의 send() 함수로 문자열 데이터를 네이티브에 보냅니다. 또한 네이티브에서 문자열 데이터를 받아서 로직을 실행한 후 결괏값을 send() 함수의 반환 타입으로 받을 수 있습니다.

 

안드로이드 코드
안드로이드에서 플랫폼 채널을 이용하려면 MainActivity에 configureFlutterEngine() 함수를 재정의합니다. 이 함수에서 다트 코드에 지정한 채널과 같은 이름으로 채널을 생성합니다. 그리고 다트에서 보내는 메시지를 받으려고 setMessageHandler() 함수의 매개변수에 데이터가 전달될 때 자동으로 호출할 함수를 지정합니다.
다음 코드에서 message 매개변수는 다트에서 보낸 문자열이며, reply 매개변수는 로직을 실행한 후 결과를 보낼 때 사용합니다. reply의 reply() 함수를 호출하면 매개변숫값을 다트로 보냅니다.

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)
        val channel = BasicMessageChannel<String>(flutterEngine.dartExecutor,
        	"myMessageChannel", StringCodec.INSTANCE )
        channel.setMessageHandler { message, reply ->
            Log.d("msg", "receive: $message")
            reply.reply("Reply from Android")
        }
    }
}

 

iOS 코드
다트에서 보낸 데이터를 iOS에서 받는 스위프트 코드도 안드로이드 코드와 유사합니다. App Delegate 클래스에 application() 함수가 선언되어 있으며 이 함수에 FlutterBasicMessage Channel 클래스의 객체를 생성하여 채널을 만듭니다. 이 객체의 name에 지정한 문자열이 채널 이름이며 다트에서 지정한 채널 이름과 같아야 합니다.
채널 객체를 만든 후 setMessageHandler() 함수의 매개변수에 문자열을 받을 때 자동으로 실행할 함수를 지정합니다. 이 함수의 첫 번째 매개변수는 다트에서 보낸 데이터이며, 두 번째 매개변수는 실행 결과를 다시 다트에 보내는 FlutterReply 객체입니다.

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller: FlutterViewController =
        	window?.rootViewController as! FlutterViewController
        let channel = FlutterBasicMessageChannel(
            name: "myMessageChannel",
            binaryMessenger: controller.binaryMessenger,
            codec: FlutterStringCodec.sharedInstance()
        )
        channel.setMessageHandler {
        	(message: Any?, reply: FlutterReply) -> Void in reply("Hi from iOS")
        }
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

 

네이티브에서 다트로 보내기


이번에는 메시지 채널을 이용해 네이티브에서 다트에 문자열 데이터를 보내는 방법을 살펴보겠습니다. 다트에서는 채널에 데이터를 받을 때 실행할 함수를 핸들러로 지정하고, 네이티브 코드에서는 채널을 이용해 데이터를 보내면 됩니다.


다트 코드
다음은 네이티브에서 보낸 문자열을 받는 다트 코드입니다. BasicMessageChannel을 이용해 채널을 만들고 데이터가 전달될 때 호출할 함수를 setMessageHandler() 함수의 매개변수로 지정합니다. setMessageHandler()에 지정한 함수의 반환값은 다시 네이티브로 보냅니다

const channel = BasicMessageChannel<String>('myMessageChannel', StringCodec());
channel.setMessageHandler((String? message) async {
    ... (생략) ...
    return 'Reply from Dart';
});

 

안드로이드 코드
다음은 메시지 채널을 이용해 다트에 문자열을 보내는 안드로이드 코드입니다. BasicMessage Channel 객체로 채널을 만들고 이 채널 객체의 send() 함수로 다트에 문자열을 보냅니다. send() 함수의 두 번째 매개변수는 다트에서 반환하는 결과를 받는 함수입니다.

val channel = BasicMessageChannel<String>(flutterEngine.dartExecutor,
	"myMessageChannel", StringCodec.INSTANCE )
... (생략) ...
channel.send("Hello from Android"){replay -> Log.d("msg", "reply : $replay")

 

iOS 코드
메시지 채널을 이용해 다트에 문자열을 보내는 iOS 코드입니다. FlutterBasicMessageChannel을 이용해 채널 객체를 만들고 이 객체의 sendMessage() 함수를 호출하여 다트에 문자열을 보냅니다.

let controller: FlutterViewController =
	window?.rootViewController as! FlutterViewController
let channel = FlutterBasicMessageChannel(
    name: "myMessageChannel",
    binaryMessenger: controller.binaryMessenger,
    codec: FlutterStringCodec.sharedInstance()
)
... (생략) ...
channel.sendMessage("Hello i am ios native") {
	(reply: Any?) -> Void in print("%@", reply as! String)
}

 

 

 

책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.

 

 

'flutter' 카테고리의 다른 글

플러터 - FCM  (0) 2023.03.13
플러터 - image_picker  (0) 2023.03.13
플러터 - GetX로 상태 관리하기  (0) 2023.03.13
플러터 - Bloc Cubit  (0) 2023.03.13
플러터 - Provider  (0) 2023.03.13