북극곰의 개발일기

FCM을 이용해서 안드로이드에서 푸시 메시지 날리기





posted by purplebeen on Sat Feb 03 2018 23:38:08 GMT+0900 (KST) in Android


FCM은 Firebase Cloud Messaging의 약자로, Firebase에서 모바일(iOS, Android)나 웹 (크롬) 상에서 알림을 띄우기 위해서 사용된다.

오늘은 이중에서 안드로이드에서 Notification을 주는 방법에 대해서 알아볼려고 한다.

FCM은 기본적으로 JSON 형태로 firebase 서버에 전송된다.

notification에는 백그라운드에서 들어갈 알림에 대한 데이터가, data 에는 foreground에서 들어갈 알림의 데이터가 담겨 있다.

{
  "to" : "dzs3phj…",
  "priority" : "high",
  "notification" : {
    "body" : "Background Message",
    "title" : "BG Title"
  },
  "data" : {
    "title" : "FG Title",
    "message" : "Foreground Message"
  }
}

이런 형태로 서버에 전송된다. 안드로이드 클라이언트에서 이러한 알림을 받기 위해 무엇을 해야할지 알아보자.

먼저 서비스 2개를 등록해야한다.

한 서비스는 Firebase 서버로부터 클라우드 메시지를 받아줄 서비스고,

하나는 Firebase와 토큰을 연계해서 토픽 구독 정보같은 것을 업데이트 해줄 서비스이다.

manifest에 서비스를 추가시켜준다.

	<service
            android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>

        <service
            android:name=".MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

메시지를 받기 위한 MyFirebaseMessagingService와

인스턴스 아이디 관련된 부분을 처리해줄 MyFirebaseInstanceIDService를 정의했다.

MyFirebaseMessagingService부터 먼저 살펴보자.

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG="FirebaseMessageService";

    //start receive_message

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
//        super.onMessageReceived(remoteMessage);
        String messageBody = remoteMessage.getData().get("message");
        String title = remoteMessage.getData().get("title");
        sendNotification(messageBody, title);
    }

    private void sendNotification(String messageBody,String title) {
        Intent intent = new Intent(this,MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = 
           PendingIntent.getActivity(this, 0 /*request code*/, intent, PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(title+"님 의 메시지입니다.")
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) 
                                             getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0,notificationBuilder.build());
    }
}

서버에서 메시지를 받았을 때 message와 title을 받아서 알림을 띄워준다.

이 부분은 앱이 실행중일때 실행된다.

즉, 백그라운드에서의 알림은 서버에서 전송해주는 값에 따라서 작동하게 된다.

인스턴스 아이디와 관련된 부분을 보자

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";

    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);
    }
}

인스턴스의 토큰이 바뀌었을때 토큰을 다시 얻어준다. 이 결과 백그라운드에서도 토큰을 잃지 않고 돌아가게 할 수 있다.

자 그러면 이제 알림을 받을 수 있도록 메인 액티비티에서 FirebaseMessaging과 FirebaseInstanceID 관련된 설정을 해줘야한다.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FirebaseMessaging.getInstance().subscribeToTopic("news");
        FirebaseInstanceId.getInstance().getToken();
    }
}

나의 경우에는 Firebase Messaging에서 특정 토픽으로 지정한 알림만 받아오기 위해서

subscribeToTopic 메소드를 이용해서 토픽 구독을 요청했다. 또한 인스턴스 아이디의 토큰을 가져왔다.

이러한 설정을 끝내게 되면 서버에서 API키를 Authroization:key = 에 인자값으로 넣고

REST API로 Firebase 서버에 Request를 보내면 안드로이드 폰에서 알림이 foreground이든 background 이든 정상적으로 오는 것을 확인할 수 있다.

github 링크

깃허브의 링크에 들어가면 보다 자세한 소스를 확인할 수 있다.