개발 창고/Android

[Android] Background에 있는 어플에 firebase 호출 시 onMessageReceived가 호출되지 않는 오류 처리

로이제로 2020. 9. 16. 11:14
반응형

다음과 같은 설정으로 Customized 된 FCM을 받을 때, onMessageReceived를 받아지지 않아 Data 전달하지 못하고 있었습니다.

 

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d("Firebase", "From: " + remoteMessage.getFrom());

        if (remoteMessage.getData().size() > 0) {
            LogUtils.debug("Message data payload: " + remoteMessage.getData());
        }

        if (remoteMessage.getNotification() != null) {
            RemoteMessage.Notification noti = remoteMessage.getNotification();
            String title = noti.getTitle();
            String body = noti.getBody();
            String linkUrl = noti.getClickAction();

            LogUtils.debug("Message Notification Body: " + body);

            sendNotification(title, body, clickAction);
        }
    }

    // 신규 토큰 발급
    @Override
    public void onNewToken(String token) {
        Log.d("Firebase", "Refreshed token: " + token);

        sendRegistrationToServer(token);
    }

    private void sendRegistrationToServer(String token) {}
    
    // 알림 발송
    private void sendNotification(String title, String body, String linkUrl) {
        Log.d("Firebase", title);

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("LOAD_URL", linkUrl);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);

        String channelId  = getString(R.string.fcm_notification_channel_id);
        String channelName = getString(R.string.fcm_notification_channel_name);
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(this, channelId)
                        .setSmallIcon(R.drawable.ic_action_name)
                        .setContentTitle(title)
                        .setContentText(body)
                        .setAutoCancel(true)
                        .setSound(defaultSoundUri)
                        .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(channel);
        }

        notificationManager.notify(0, notificationBuilder.build());
    }
}

목표는 데이터의 전달을 받는 거였는데 onReceivedMessage에서 받아지지 않는게 문제였습니다.

 

해결책을 찾다보니 clickAction에 넣지 말고 data에 넣어라는 말이 많았는데

 

stackoverflow.com/questions/37358462/firebase-onmessagereceived-not-called-when-app-in-background

 

Firebase onMessageReceived not called when app in background

I'm working with Firebase and testing sending notifications to my app from my server while the app is in the background. The notification is sent successfully, it even appears on the notification c...

stackoverflow.com

 

이를 가지고 해결한 방법은 일단 가장 중요한 건 데이터의 전송을 받는 것이었기 때문에

 

다음과 같이 clickAction에서 받는 데이터를 message의 데이터에서 바당 처리해주도록 변경해주고

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        ...
        
        // String linkUrl = noti.getClickAction();
        String linkUrl = remoteMessage.getData().get("LOAD_URL");
        
        ...
    }
    
    // 알림 발송
    private void sendNotification(String title, String body, String linkUrl) {
        ...

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("LOAD_URL", linkUrl);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);

        ...
    }
}

 

 MainActivity에서 getIntent의 getExtras나 getStringExtra로 값을 받아 처리하면 가능한 부분이었습니다.

public class MainActivity extends AppCompatActivity {

	...

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

        String url = getIntent().getStringExtra("LOAD_URL");
        
        ...
    }
    
    ...
}

 

 전송은 json의 경우

{
  "to": "디바이스 토큰 목록",
  "notification": {
    "body": "본문내용",
    "title": "제목"
  },
  "data": {
    "body": "알림본문내용",
    "title": "알림본문제목",
    "LOAD_URL": "링크데이터"
  }
}

다음과 같이 호출하면 되고

 

 Java에서의 전송은

            // message 작성
            AndroidNotification noti = AndroidNotification
                    .builder()
                    .setTitle("알림제목")
                    .setBody("알림내용")
                    // .setClickAction(linkUrl)
                    .build();
            
            AndroidConfig config = AndroidConfig
                    .builder()
                    .setTtl(3500 * 1000)
                    .setPriority(AndroidConfig.Priority.NORMAL)
                    .setNotification(noti)
                    .build();
            
            Message msg = Message
                    .builder()
                    .setAndroidConfig(config)
                    .setToken(registrationToken)
                    .putData("LOAD_URL", "링크경로")
                    .build();
            
            String response = FirebaseMessaging.getInstance().send(msg);

 

다음과 같은 형태로 putData에 값을 추가해 보내서 해결하도록 하였습니다.

반응형