꿈꾸는 시스템 디자이너

Flutter 강좌 - 플랫폼간 메소드 호출 #3 - Flutter에서 안드로이드 메소드 호출하기 | MethodChannel 사용법 | How to use MethodChannel 본문

Development/Flutter

Flutter 강좌 - 플랫폼간 메소드 호출 #3 - Flutter에서 안드로이드 메소드 호출하기 | MethodChannel 사용법 | How to use MethodChannel

독행소년 2020. 4. 20. 18:07

Flutter Code Examples 강좌를 추천합니다.

  • 제 블로그에서 Flutter Code Examples 프로젝트를 시작합니다.
  • Flutter의 다양한 예제를 소스코드와 실행화면으로 제공합니다.
  • 또한 모든 예제는 Flutter Code Examples 앱을 통해 테스트 가능합니다.

Flutter Code Examples 강좌로 메뉴로 이동

Flutter Code Examples 강좌 목록 페이지로 이동

Flutter Code Examples 앱 설치 | Google Play Store로 이동

 

Flutter Code Examples - Google Play 앱

Are you a beginner at Flutter? Check out the various features of Flutter through the demo. Source code for all demos is also provided.

play.google.com


Flutter 강좌 시즌2 목록 : https://here4you.tistory.com/149

 

 

지난 강좌에서는 안드로이드에서 NDK를 이용해 네이티브 라이브러리를 작성하고 호출하는 방법에 대해서 알아봤다.

 

이번 강좌에너는 Flutter에서 안드로이드 메소드를 호출하는 방법에 대해서 알아본다.

 

Flutter에서 안드로이드의 메소드를 호출할 때 사용되는 것이 MethodChannel이다.

 

 

1. Flutter Application 프로젝트 생성

새로운 Flutter Application 프로젝트를 선택한다.

프로젝트명으로 method_channel_test를 입력한다.

기본 패키지명으로 프로젝트 생성을 완료한다.

 

2. main.dart 작성

main.dart를 다음과 같이 작성한다.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Method Channel Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const MethodChannel _channel =
      const MethodChannel('com.example.methodchanneltest');

  String _platformVersion = 'Unknown';

  Future<String> getPlatformVersion() async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Method Channel Test"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text("Get Platform Version"),
              onPressed: () async {
                String result = await getPlatformVersion();
                setState(() {
                  _platformVersion = result;
                });
              },
            ),
            Text(_platformVersion),
          ],
        ),
      ),
    );
  }
}

 

Flutter에서의 MethodChannel은 다음과 같이 생성한다. MethodChannel의 생성자에 파라미터로 메소드채널의 이름을 입력하는데 Android측의 MethodChannel 생성시에도 같은 이름으로 부여해야 통신이 가능해 진다. 더욱이 다른 앱들간에도 간섭이 발생할 수 있으므로 패키지명으로 이름을 부여하는 것을 추천한다.

  static const MethodChannel _channel =
      const MethodChannel('com.example.methodchanneltest');

 

실제 안드로이드의 메소드를 호출하는 방법은 다음과 같다. 위에서 생성한 채널의 인스턴스를 통해 invokeMethod 메소드를 호출한다. 이 때 파라미터로 호출할 메소드의 이름을 입력한다.

  Future<String> getPlatformVersion() async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

 

3. MainActivity.java 작성

Flutter로부터 메소드 호출을 받는 안드로이드 측의 소스코드는 다음과 같다.

package com.example.methodchanneltest;

import android.os.Build;

import androidx.annotation.NonNull;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
        final MethodChannel channel = new MethodChannel(flutterEngine.getDartExecutor(), "com.example.methodchanneltest");
        channel.setMethodCallHandler(handler);
    }

    private MethodChannel.MethodCallHandler handler = (methodCall, result) -> {
        if (methodCall.method.equals("getPlatformVersion")) {
            result.success("Android Version: " + Build.VERSION.RELEASE);
        } else {
            result.notImplemented();
        }
    };
}

 

MethodChannel의 생성은 다음과 같이 한다. Flutter와 동일한 채널의 이름을 할당해야 한다. 또한 Flutter로부터의 메소드 호출 이벤트를 수신할 MethodCallHandler를 채널에 등록한다.

        final MethodChannel channel = new MethodChannel(flutterEngine.getDartExecutor(), "com.example.methodchanneltest");
        channel.setMethodCallHandler(handler);

 

채널에 등록할 MethodCallHandler는 다음과 같이 구현할 수 있다.

    private MethodChannel.MethodCallHandler handler = (methodCall, result) -> {
        if (methodCall.method.equals("getPlatformVersion")) {
            result.success("Android Version: " + Build.VERSION.RELEASE);
        } else {
            result.notImplemented();
        }
    };

람다 형식으로, 메소드호출을 수신할 methodCall과 결과를 응답할 result 아규먼트를 입력받는다.

methodCall의 method를 파싱하여 실제 호출할 메소드(혹은 변수)를 확인할 수 있으며, result를 이용해 호출의 성공이나 에러, 미구현들을 반환할 수 있다.

 

4. 앱 실행 결과

실행 결과는 다음과 같다. 화면상의 버튼을 클릭하면 안드로이드측의 getPlatformVersion이란 이름의 메소드 호출이 전달되고, 안드로이드에서는 해당 디바이스의 안드로이드 빌드 버전 정보를 반환한다. 최종적으로 다음과 같이 안드로이드 버전 정보를 출력하게 된다.

 

 

이번 강좌에서는 MethodChannel을 이용해서 Flutter로부터 Android로 메소드 호출 요청을 전달하고 그 결과를 반환하는 방법에 대해서 알아봤다.

 

사족으로, 우리가 흔히 pub.dev 사이트에서 검색해서 이용하는 Flutter 패키지(플러그인)의 상당수가 이런식으로 안드로이드의 네이티브 메소드를 호출하는 기능을 구현한 것이다. Flutter만으로는 플랫폼 특화된 기능을 이용할 수 없기 때문이다. 실제 이번 강좌에서 활용한 소스코드 역시 Android Studio의 Plugin 프로젝트의 템플릿 코드를 참고해서 작성한 것이다. 

 

이번 강좌까지 진행하면서, 안드로이드와 네이티브 라이브러리간 함수 호출과, 플러터와 안드로이드간의 메소드 호출의 방법에 대해서 알아봤다. 그렇다면 Flutter에서 시작한 호출이 네이티브 라이브러리까지 전달되어 반환될 순 없을까? 있다. 지금까지 강좌에서 실습한 방법을 머지하면 가능하다. 다음 강좌에서는 Flutter에서 네이티브 라이브러리까지 함수 호출을 전달하는 방법에 대해서 알아본다.

 

Comments