Flutter - Firebase Cloud Messaging 연동 - 3. Flutter 프로젝트 만들기

2020. 5. 14. 18:46난장 Dev/Flutter - Dart


이번 포스팅에서는 앞에서 진행했던 작업들을 실제 시스템에 적용해 보는 시간을 갖도록 하겠다.

기본적으로 Android Studio 가 설치되어 있고, Flutter Plugin 도 설치되어 있다는 전재로 진행한다.

 

만약 설치하지 않았다면 전에 올린 자료를 참고해서 설치 필요!

 

2020/05/13 - [난장 Dev/Flutter] - Flutter - macOS 에 Flutter 설치하기

 

Flutter - macOS 에 Flutter 설치하기

한글화 사이트에서 자세하게 설명되어 있었지만, 그래도 남겨보는 것도 의미가 있겠지. 설치방법은 아래 사이트에서 순서대로 한글: https://flutter-ko.dev/docs/get-started/install/macos 맥OS에서 설치 flutte

naan.co.kr

 

프로그램을 실행하면 아래와 같이 뜨고, 두번째 "Start a new Flutter project"를 클릭한다.

 

애플리케이션으로 진행해야 하므로 첫번째 "Flutter Application"을 선택.

 

프로젝트 이름은 편하게 작성해도 된다. test는 입력이 안되는 듯.

test_app로 입력하였다.

 

프로젝트 생성하면서 가장 중요한 "Package Name". FCM에서 입력했던 것과 동일하게 해야 한다. 프로젝트를 먼저 생성했다면 여기서 만든 패키지 이름을 FCM에서 설정해서 사용하여야 한다.

 

프로젝트가 생성되면 다음과 같은 화면으로 초기화 된다.

 

 


  

 

 

가장 먼저 해야하는 작업은 Firebase Cloud Messaging을 사용하기 위한 패키지를 등록해야 한다.

등록을 위해 다음 사이트로 접속한다. https://pub.dev 

 

Dart packages

Pub is the package manager for the Dart programming language, containing reusable libraries & packages for Flutter, AngularDart, and general Dart programs.

pub.dev

그리고 packages 를 다음과 같이 검색한다.

" firebase messaging "

 

다른 패키지를 안써봐서 모르겠지만, firebase.google.com 에서 만든 거면 가장 알맞게 만들지 않았을까?

버전도 높고, 나도 이걸로 써봐서,,, 일단 클릭해서 들어가보자.

 

일단 여기에서 나온 내용을 차례대로 진행해 보면.

먼저 플러그인을 추가하는 작업부터 시작한다. "pubspec.yaml" 파일을 열어 추가한다.

아래는 추가한 거 캡쳐. 확대해서 확인하면 된다.

3번으로 표시된 "Pub get" 부분을 꼭 클릭해줘야 추가가 된다.

 firebase_messaging: 6.0.15

 

추가가 완료되면 다음과 같이 보여진다.

 

여기서부터는 내용이 길어지게 되어 구분해서 작성하고자 한다.

 

 

 

 

1. 안드로이드 설정

설명된 내용을 보면 아래와 같다.

https://pub.dev/packages/firebase_messaging#-readme-tab-

 

첫 번째로 지난 포스팅에서 작성한 안드로이드 구성파일을 이 프로젝트에 등록하는 일이다.

https://pub.dev/packages/firebase_messaging#-readme-tab-

"google-services.json"파일을 android/app 안에다 넣으면 된다.

 

 

두 번째 작업은 프로젝트 단의 gradle에 의존성을 추가해준다.

 

https://pub.dev/packages/firebase_messaging#-readme-tab-

dependencies {
  // Example existing classpath
  classpath 'com.android.tools.build:gradle:3.5.3'
  // Add the google services classpath
  classpath 'com.google.gms:google-services:4.3.2'
}

위치를 잘 모르겠다면, 아래 캡쳐를 확인해서 넣도록 한다.

 

세 번째 작업은 app안에 있는 gradle에 추가하는 것이다. 이건 제일 아래에 추가만 해놓으면 된다.

https://pub.dev/packages/firebase_messaging#-readme-tab-

apply plugin: 'com.google.gms.google-services'


이렇게만 놓으면 gradle에 넣었던 의존성 라이브러리들을 자동으로 가지고 올수가 없다. 귀찮지만 안드로이드 스튜디오를 프로젝트 단으로 실행할 필요가 있다.

 

위에서 작업한 창 오른쪽 위를 보면 "Open for Editing in Android Studio"가 보인다. 클릭한다.

 

클릭하면 프로젝트를 어떻게 열지 물어보는데, 현재 flutter를 끄지 않기 위해 "New Window"를 클릭하여 새 창으로 프로젝트를 연다

열면 알아서 다운로드가 시작되는데, 여유를 가지고 3분정도(?) 물론 환경에 따라 다르겠지만 완료가 된다.

 

완료가 되면 보이지 않았던 "firebase_messaging"가 보인다. 이러면 설정이 끝. 더이상 할 것이 없으므로 프로젝트를 종료한다.

 

네 번째로하는 것은 옵션인데... 그래도 혹시 모르니 추가는 해 놓고 시작하자.

https://pub.dev/packages/firebase_messaging#-readme-tab-

<intent-filter>
      <action android:name="FLUTTER_NOTIFICATION_CLICK" />
      <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

android/app/src/main/AndroidManifest.xml 을 열어 위 코드를 추가한다.

 

이제 안드로이드 설정이 종료되었다.

 

 

2. iOS 설정

iOS에서 하라는 내용은 좀 있는데, 전 단계에서 다 해놓은 거라 특별히 할 것이라곤 2번 만 하면 된다.

https://pub.dev/packages/firebase_messaging#-readme-tab-

 

첫 번째로 Firebase의 안내에 따라서 푸시 인증에 필요한 인증서를 생성하라고 했는데 우린 firebase 설정을 이미 했기에... 모르겠다면 이전 포스팅 참조.

https://pub.dev/packages/firebase_messaging#-readme-tab-

 

두 번째로 해야 하는 작업은 Firebase Console에서 다운 받은 파일을 등록하는 작업이다.

https://pub.dev/packages/firebase_messaging#-readme-tab-

 

간단하게 지난 포스팅에서 다운로드한 "GoogleService-Info.plist"를 "ios/Runner"에 추가한다.

 

추가하고 나서 ios 폴더를 클릭한 상태에서 마우스 오른쪽을 누르고 "Flutter > Open iOS module in Xcode"를 눌러 Xcode를 실행한다.

 

Runner/Runner 폴더를 클릭하고 마우스 오른쪽 키를 누르고 "Add Files to "Runner"... "을 누른다

그리고 위에서 추가한 "GoogleService-Info.plist"를 선택하고 "Add"를 누른다.

 

정상적으로 추가된것이 확인 된다면 Xcode를 종료한다.

iOS 설정도 마무리 됐다.

이제 실제 앱에서 테스트 할 수 있도록 진행해보고자 한다.

 

 

3. main.dart 코드 수정

lib/main.dart를 열고 코드를 수정한다.

import 'package:flutter/material.dart';

import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';

final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Test',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          appBar: AppBar(
            title: Text('FCM'),
          ),
          body: MyHomePage(),
        )
    );
  }
}

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

class _MyHomePageState extends State<MyHomePage> {
  var tokens = '';
  @override
  void initState(){
    super.initState();
    _firebaseCloudMessaging_Listeners();
  }

  // 화면 리플래시...
  void _incrementToken(var item) {
    setState(() {
      tokens = item;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(tokens),
    );
  }

  // firebase
  void _firebaseCloudMessaging_Listeners(){
    if(Platform.isIOS) _iOS_Permission();

    // token
    _firebaseMessaging.getToken().then((token){
      print('token: $token');
      // 토큰을 출력
      _incrementToken( token );
    });

    // push notification
    _firebaseMessaging.configure(
      // 메시지가 왔을 때
      onMessage: (Map<String, dynamic> message) async {
        print('on message $message');

        // 메시지가 제대로 들어오는지 확
        if( message != null && message['notification']['title'] != null && message['notification']['body'] != null) {
          // 메시지 별 차이점 확인...

          // 메시지를 어케 받는지 확인 됐다면...
          showDialog(
            context: context,
            builder: (context) =>
                AlertDialog(
                  content: ListTile(
                    title: Text(message['notification']['title']),
                    subtitle: Text(message['notification']['body']),
                  ),
                  actions: <Widget>[
                    FlatButton(
                      child: Text('확인'),
                      onPressed: () => Navigator.of(context).pop(),
                    ),
                  ],
                ),
          );
        }

      },
      onResume: (Map<String, dynamic> message) async {
        print('on resume $message');
      },
      onLaunch: (Map<String, dynamic> message) async {
        print('on launch $message');
      },
    );
  }

  void _iOS_Permission(){
    _firebaseMessaging.requestNotificationPermissions(
        IosNotificationSettings(sound: true, badge: true, alert: true)
    );

    _firebaseMessaging.onIosSettingsRegistered.listen((IosNotificationSettings settings) {
      print("Settings registereded: $settings");
    });
  }
}

 

이제 푸시 서비스를 위한 모든 구성이 마무리 됐다.

테스트를 해보고 문제가 없는지 확인해 보자.

 

 

4. 테스트

테스트를 위해서 난 Postman을 사용하였다.

쉽고 간편하고 일단 남들이 올려 좋은게 있으니 테스트하기 너무 좋은 것 같다.

 

일단 Postman ( https://www.postman.com/downloads/ ) 에 접속해서 다운로드 받고 로그인까지 완료해 보자. 

 

Download Postman App

Download Postman! Join the 10 million developers and 500,000 companies who rely on Postman as the only complete API development environment.

www.postman.com

 

실행하자마자 왼쪽 상단에 보이는 "New"를 클릭하자.

그리고 Templates 탭을 선택하고 검색어에 "firebase"를 입력한다. 그리고 보이는 "Firebase Notification REST API UMH"를 클릭한다.

Collections에 방금전 선택한 "Firebase Notification REST API UMH"를 확인하고 안에 있는 "Send Notification"를 클릭한다.

 

Headers에 입력해야 하는 키는 (  {{serverkey}} ) Firebase Console로 들어가 지금 작업 중인 프로젝트로 들어간다. 그리고 "클라우드 메시징" 을 클릭하면 보이는 서버 키가 위에 입력해야 하는 키이다. 길지만 모두 입력해야 하고, 남들에게 공개되지 않도록 보안에 신경써야 한다.

 

그리고 Body로 이동하면 기본 레이아웃이 있는데 난 테스트를 위해 아래와 같이 입력하였다.

{
  "priority":"HIGH",
  "notification":{
  	"title":"알림",
  	"body":"일반 알림인 경우"
  },
  "data":{
	"title":"T1",
	"message":"https://naan.co.kr"
  },
  "to":"디바이스 토큰 값"
}

 

참고로 디바이스 토큰 값이 있어야 해당 디바이스로 푸시메시지를 보낼 수 있는데 이건 일단 위에서 작업이 끝난 Flutter 프로젝트를 빌드하면 된다.

 

빌드하면 화면에 이 기기의 토큰 값이 출력된다. 이걸 이대로 일일이 쳐가면서 하는게 아니고 그 일을 대비해 console에 보면 토큰 값이 보이는 것을 확인할 수 있다.

 

여기에서 보이는 토큰 값을 가지고 입력하고 테스트를 진행해 본다.

 

푸시가 정상적으로 들어오면 아래와 같이 로그가 남겨진다.

화면은 아래와 같이 보여지게 된다.

 

01