1 package host.exp.exponent.fcm 2 3 import android.content.Context 4 import com.google.firebase.messaging.RemoteMessage 5 import expo.modules.notifications.notifications.model.NotificationContent 6 import expo.modules.notifications.notifications.model.NotificationRequest 7 import expo.modules.notifications.notifications.model.triggers.FirebaseNotificationTrigger 8 import expo.modules.notifications.service.delegates.FirebaseMessagingDelegate 9 import host.exp.exponent.ABIVersion 10 import host.exp.exponent.Constants 11 import host.exp.exponent.analytics.EXL 12 import host.exp.exponent.notifications.NotificationConstants 13 import host.exp.exponent.notifications.PushNotificationHelper 14 import host.exp.exponent.notifications.model.ScopedNotificationRequest 15 import host.exp.exponent.storage.ExponentDB 16 import org.json.JSONException 17 18 class ExpoFirebaseMessagingDelegate(context: Context) : FirebaseMessagingDelegate(context) { 19 override fun onNewToken(token: String) { 20 if (!Constants.FCM_ENABLED) { 21 return 22 } 23 super.onNewToken(token) 24 FcmRegistrationIntentService.registerForeground(context.applicationContext, token) 25 } 26 27 override fun onMessageReceived(remoteMessage: RemoteMessage) { 28 if (!Constants.FCM_ENABLED) { 29 return 30 } 31 32 val scopeKey = remoteMessage.data[NotificationConstants.NOTIFICATION_EXPERIENCE_SCOPE_KEY_KEY] 33 if (scopeKey == null) { 34 EXL.e("expo-notifications", "No scope key found in notification") 35 return 36 } 37 38 val exponentDBObject = try { 39 ExponentDB.experienceScopeKeyToExperienceSync(scopeKey) 40 } catch (e: JSONException) { 41 e.printStackTrace() 42 EXL.e("expo-notifications", "Error getting experience for scope key $scopeKey") 43 return 44 } 45 46 if (exponentDBObject == null) { 47 EXL.e("expo-notifications", "No experience found for scope key $scopeKey") 48 return 49 } 50 51 val sdkVersionString = exponentDBObject.manifest.getSDKVersion() 52 if (sdkVersionString == null) { 53 dispatchToNextNotificationModule(remoteMessage) 54 return 55 } 56 57 val sdkVersion = ABIVersion.toNumber(sdkVersionString) / 10000 58 59 // Remove the entire legacy notifications API after we drop SDK 40 60 if (sdkVersion <= 40 && !exponentDBObject.manifest.shouldUseNextNotificationsApi()) { 61 dispatchToLegacyNotificationModule(remoteMessage) 62 } else { 63 dispatchToNextNotificationModule(remoteMessage) 64 } 65 } 66 67 private fun dispatchToNextNotificationModule(remoteMessage: RemoteMessage) { 68 super.onMessageReceived(remoteMessage) 69 } 70 71 private fun dispatchToLegacyNotificationModule(remoteMessage: RemoteMessage) { 72 PushNotificationHelper.instance.onMessageReceived( 73 context, 74 remoteMessage.data[NotificationConstants.NOTIFICATION_EXPERIENCE_SCOPE_KEY_KEY]!!, 75 remoteMessage.data["channelId"], 76 remoteMessage.data["message"], 77 remoteMessage.data["body"], 78 remoteMessage.data["title"], 79 remoteMessage.data["categoryId"] 80 ) 81 } 82 83 override fun createNotificationRequest( 84 identifier: String, 85 content: NotificationContent, 86 notificationTrigger: FirebaseNotificationTrigger 87 ): NotificationRequest { 88 if (Constants.isStandaloneApp()) { 89 return super.createNotificationRequest(identifier, content, notificationTrigger) 90 } 91 92 val data = notificationTrigger.remoteMessage.data 93 return ScopedNotificationRequest( 94 identifier, 95 content, 96 notificationTrigger, 97 data[NotificationConstants.NOTIFICATION_EXPERIENCE_SCOPE_KEY_KEY] 98 ) 99 } 100 } 101