diff --git a/native/android/app/src/main/java/app/comm/android/MainApplication.java b/native/android/app/src/main/java/app/comm/android/MainApplication.java --- a/native/android/app/src/main/java/app/comm/android/MainApplication.java +++ b/native/android/app/src/main/java/app/comm/android/MainApplication.java @@ -28,6 +28,7 @@ extends MultiDexApplication implements ReactApplication { static { + System.loadLibrary("fbjni"); System.loadLibrary("comm_jni_module"); } diff --git a/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java b/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java --- a/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java +++ b/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java @@ -1,10 +1,16 @@ package app.comm.android.notifications; +import android.app.ActivityManager; +import android.app.Notification; import android.app.NotificationManager; import android.content.Context; +import android.graphics.BitmapFactory; +import android.os.Bundle; import android.service.notification.StatusBarNotification; import android.util.Log; +import androidx.core.app.NotificationCompat; import app.comm.android.ExpoUtils; +import app.comm.android.R; import app.comm.android.fbjni.CommSecureStore; import app.comm.android.fbjni.GlobalDBSingleton; import app.comm.android.fbjni.MessageOperationsUtilities; @@ -49,6 +55,13 @@ private static final String THREAD_ID_KEY = "threadID"; private static final String SET_UNREAD_STATUS_KEY = "setUnreadStatus"; private static final String MESSAGE_INFOS_KEY = "messageInfos"; + private static final String NOTIF_ID_KEY = "id"; + private static final String TITLE_KEY = "title"; + private static final String PREFIX_KEY = "prefix"; + private static final String BODY_KEY = "body"; + + private static final String CHANNEL_ID = "default"; + private static final long[] VIBRATION_SPEC = {500, 500}; private NotificationManager notificationManager; @Override @@ -102,7 +115,11 @@ Log.w("COMM", "Database not existing yet. Skipping notification"); } - super.onMessageReceived(message); + if (this.isAppInForeground()) { + super.onMessageReceived(message); + return; + } + this.displayNotification(message); } private void handleNotificationRescind(RemoteMessage message) { @@ -131,4 +148,48 @@ } } } + + private boolean isAppInForeground() { + ActivityManager.RunningAppProcessInfo runningAppProcessInfo = + new ActivityManager.RunningAppProcessInfo(); + ActivityManager.getMyMemoryState(runningAppProcessInfo); + return runningAppProcessInfo.importance == + ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; + } + + private void displayNotification(RemoteMessage message) { + if (message.getData().get(RESCIND_KEY) != null) { + // don't attempt to display rescinds + return; + } + String id = message.getData().get(NOTIF_ID_KEY); + String title = message.getData().get(TITLE_KEY); + String prefix = message.getData().get(PREFIX_KEY); + String body = message.getData().get(BODY_KEY); + String threadID = message.getData().get(THREAD_ID_KEY); + + if (prefix != null) { + body = prefix + " " + body; + } + + Bundle data = new Bundle(); + data.putString(THREAD_ID_KEY, threadID); + + NotificationCompat.Builder notificationBuilder = + new NotificationCompat.Builder(this.getApplicationContext()) + .setDefaults(Notification.DEFAULT_ALL) + .setContentText(body) + .setExtras(data) + .setChannelId(CHANNEL_ID) + .setVibrate(VIBRATION_SPEC) + .setSmallIcon(R.drawable.notif_icon) + .setLargeIcon(BitmapFactory.decodeResource( + this.getApplicationContext().getResources(), + R.mipmap.ic_launcher)) + .setAutoCancel(true); + if (title != null) { + notificationBuilder = notificationBuilder.setContentTitle(title); + } + notificationManager.notify(id, id.hashCode(), notificationBuilder.build()); + } } diff --git a/native/push/android.js b/native/push/android.js --- a/native/push/android.js +++ b/native/push/android.js @@ -5,11 +5,7 @@ import { mergePrefixIntoBody } from 'lib/shared/notif-utils'; -import { store } from '../redux/redux-setup'; -import { getFirebase } from './firebase'; - const androidNotificationChannelID = 'default'; -const vibrationSpec = [500, 500]; function handleAndroidMessage( message: RemoteMessage, @@ -19,7 +15,6 @@ texts: { body: string, title: ?string }, ) => boolean, ) { - const firebase = getFirebase(); const { data } = message; const { rescind, rescindID } = data; @@ -28,7 +23,7 @@ return; } - const { id, title, prefix, threadID } = data; + const { title, prefix, threadID } = data; let { body } = data; ({ body } = mergePrefixIntoBody({ body, title, prefix })); @@ -39,31 +34,6 @@ return; } } - - const notification = new firebase.notifications.Notification() - .setNotificationId(id) - .setBody(body) - .setData({ threadID }) - .android.setTag(id) - .android.setChannelId(androidNotificationChannelID) - .android.setDefaults([firebase.notifications.Android.Defaults.All]) - .android.setVibrate(vibrationSpec) - .android.setAutoCancel(true) - .android.setLargeIcon('@mipmap/ic_launcher') - .android.setSmallIcon('@drawable/notif_icon'); - if (title) { - notification.setTitle(title); - } - firebase.notifications().displayNotification(notification); -} - -async function androidBackgroundMessageTask(message: RemoteMessage) { - const { updatesCurrentAsOf } = store.getState(); - handleAndroidMessage(message, updatesCurrentAsOf); } -export { - androidNotificationChannelID, - handleAndroidMessage, - androidBackgroundMessageTask, -}; +export { androidNotificationChannelID, handleAndroidMessage }; diff --git a/native/push/push-handler.react.js b/native/push/push-handler.react.js --- a/native/push/push-handler.react.js +++ b/native/push/push-handler.react.js @@ -2,13 +2,7 @@ import * as Haptics from 'expo-haptics'; import * as React from 'react'; -import { - AppRegistry, - Platform, - Alert, - LogBox, - NativeModules, -} from 'react-native'; +import { Platform, Alert, LogBox, NativeModules } from 'react-native'; import type { RemoteMessage, NotificationOpen } from 'react-native-firebase'; import { Notification as InAppNotification } from 'react-native-in-app-message'; import NotificationsIOS from 'react-native-notifications'; @@ -53,11 +47,7 @@ import type { EventSubscription } from '../types/react-native'; import { type GlobalTheme } from '../types/themes'; import { type NotifPermissionAlertInfo } from './alerts'; -import { - androidNotificationChannelID, - handleAndroidMessage, - androidBackgroundMessageTask, -} from './android'; +import { androidNotificationChannelID, handleAndroidMessage } from './android'; import { getFirebase } from './firebase'; import InAppNotif from './in-app-notif.react'; import { @@ -580,11 +570,6 @@ } } -AppRegistry.registerHeadlessTask( - 'RNFirebaseBackgroundMessage', - () => androidBackgroundMessageTask, -); - const ConnectedPushHandler: React.ComponentType = React.memo( function ConnectedPushHandler(props: BaseProps) { const navContext = React.useContext(NavContext);