diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationListenerService.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationListenerService.java index 40fec92d9..3ac932e5d 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationListenerService.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationListenerService.java @@ -1,154 +1,16 @@ package com.dieam.reactnativepushnotification.modules; -import java.util.Map; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; -import android.app.ActivityManager; -import android.app.ActivityManager.RunningAppProcessInfo; -import android.app.Application; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; - -import com.dieam.reactnativepushnotification.helpers.ApplicationBadgeHelper; -import com.facebook.react.ReactApplication; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; - -import org.json.JSONObject; - -import java.util.List; -import java.util.Random; - -import static com.dieam.reactnativepushnotification.modules.RNPushNotification.LOG_TAG; +import com.dieam.reactnativepushnotification.modules.RNReceivedMessageHandler; public class RNPushNotificationListenerService extends FirebaseMessagingService { + private RNReceivedMessageHandler mMessageReceivedHandler = new RNReceivedMessageHandler(this); + @Override public void onMessageReceived(RemoteMessage message) { - String from = message.getFrom(); - RemoteMessage.Notification remoteNotification = message.getNotification(); - - final Bundle bundle = new Bundle(); - // Putting it from remoteNotification first so it can be overriden if message - // data has it - if (remoteNotification != null) { - // ^ It's null when message is from GCM - bundle.putString("title", remoteNotification.getTitle()); - bundle.putString("message", remoteNotification.getBody()); - } - - for(Map.Entry entry : message.getData().entrySet()) { - bundle.putString(entry.getKey(), entry.getValue()); - } - JSONObject data = getPushData(bundle.getString("data")); - // Copy `twi_body` to `message` to support Twilio - if (bundle.containsKey("twi_body")) { - bundle.putString("message", bundle.getString("twi_body")); - } - - if (data != null) { - if (!bundle.containsKey("message")) { - bundle.putString("message", data.optString("alert", null)); - } - if (!bundle.containsKey("title")) { - bundle.putString("title", data.optString("title", null)); - } - if (!bundle.containsKey("sound")) { - bundle.putString("soundName", data.optString("sound", null)); - } - if (!bundle.containsKey("color")) { - bundle.putString("color", data.optString("color", null)); - } - - final int badge = data.optInt("badge", -1); - if (badge >= 0) { - ApplicationBadgeHelper.INSTANCE.setApplicationIconBadgeNumber(this, badge); - } - } - - Log.v(LOG_TAG, "onMessageReceived: " + bundle); - - // We need to run this on the main thread, as the React code assumes that is true. - // Namely, DevServerHelper constructs a Handler() without a Looper, which triggers: - // "Can't create handler inside thread that has not called Looper.prepare()" - Handler handler = new Handler(Looper.getMainLooper()); - handler.post(new Runnable() { - public void run() { - // Construct and load our normal React JS code bundle - ReactInstanceManager mReactInstanceManager = ((ReactApplication) getApplication()).getReactNativeHost().getReactInstanceManager(); - ReactContext context = mReactInstanceManager.getCurrentReactContext(); - // If it's constructed, send a notification - if (context != null) { - handleRemotePushNotification((ReactApplicationContext) context, bundle); - } else { - // Otherwise wait for construction, then send the notification - mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() { - public void onReactContextInitialized(ReactContext context) { - handleRemotePushNotification((ReactApplicationContext) context, bundle); - } - }); - if (!mReactInstanceManager.hasStartedCreatingInitialContext()) { - // Construct it in the background - mReactInstanceManager.createReactContextInBackground(); - } - } - } - }); - } - - private JSONObject getPushData(String dataString) { - try { - return new JSONObject(dataString); - } catch (Exception e) { - return null; - } - } - - private void handleRemotePushNotification(ReactApplicationContext context, Bundle bundle) { - - // If notification ID is not provided by the user for push notification, generate one at random - if (bundle.getString("id") == null) { - Random randomNumberGenerator = new Random(System.currentTimeMillis()); - bundle.putString("id", String.valueOf(randomNumberGenerator.nextInt())); - } - - Boolean isForeground = isApplicationInForeground(); - - RNPushNotificationJsDelivery jsDelivery = new RNPushNotificationJsDelivery(context); - bundle.putBoolean("foreground", isForeground); - bundle.putBoolean("userInteraction", false); - jsDelivery.notifyNotification(bundle); - - // If contentAvailable is set to true, then send out a remote fetch event - if (bundle.getString("contentAvailable", "false").equalsIgnoreCase("true")) { - jsDelivery.notifyRemoteFetch(bundle); - } - - Log.v(LOG_TAG, "sendNotification: " + bundle); - - Application applicationContext = (Application) context.getApplicationContext(); - RNPushNotificationHelper pushNotificationHelper = new RNPushNotificationHelper(applicationContext); - pushNotificationHelper.sendToNotificationCentre(bundle); - } - - private boolean isApplicationInForeground() { - ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE); - List processInfos = activityManager.getRunningAppProcesses(); - if (processInfos != null) { - for (RunningAppProcessInfo processInfo : processInfos) { - if (processInfo.processName.equals(getApplication().getPackageName())) { - if (processInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { - for (String d : processInfo.pkgList) { - return true; - } - } - } - } - } - return false; + mMessageReceivedHandler.handleReceivedMessage(message); } } diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNReceivedMessageHandler.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNReceivedMessageHandler.java new file mode 100644 index 000000000..05c0004dc --- /dev/null +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNReceivedMessageHandler.java @@ -0,0 +1,158 @@ +package com.dieam.reactnativepushnotification.modules; + +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; + +import android.app.ActivityManager; +import android.app.Application; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.support.annotation.NonNull; +import android.util.Log; + +import com.dieam.reactnativepushnotification.helpers.ApplicationBadgeHelper; +import com.dieam.reactnativepushnotification.modules.RNPushNotificationHelper; +import com.dieam.reactnativepushnotification.modules.RNPushNotificationJsDelivery; +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContext; + +import org.json.JSONObject; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +import static android.content.Context.ACTIVITY_SERVICE; +import static com.dieam.reactnativepushnotification.modules.RNPushNotification.LOG_TAG; + +public class RNReceivedMessageHandler { + private FirebaseMessagingService mFirebaseMessagingService; + + public RNReceivedMessageHandler(@NonNull FirebaseMessagingService service) { + this.mFirebaseMessagingService = service; + } + + public void handleReceivedMessage(RemoteMessage message) { + final Bundle bundle = new Bundle(); + RemoteMessage.Notification remoteNotification = message.getNotification(); + + // Putting it from remoteNotification first so it can be overriden if message + // data has it + if (remoteNotification != null) { + // ^ It's null when message is from GCM + bundle.putString("title", remoteNotification.getTitle()); + bundle.putString("message", remoteNotification.getBody()); + } + + for(Map.Entry entry : message.getData().entrySet()) { + bundle.putString(entry.getKey(), entry.getValue()); + } + JSONObject data = getPushData(bundle.getString("data")); + // Copy `twi_body` to `message` to support Twilio + if (bundle.containsKey("twi_body")) { + bundle.putString("message", bundle.getString("twi_body")); + } + + if (data != null) { + if (!bundle.containsKey("message")) { + bundle.putString("message", data.optString("alert", null)); + } + if (!bundle.containsKey("title")) { + bundle.putString("title", data.optString("title", null)); + } + if (!bundle.containsKey("sound")) { + bundle.putString("soundName", data.optString("sound", null)); + } + if (!bundle.containsKey("color")) { + bundle.putString("color", data.optString("color", null)); + } + + final int badge = data.optInt("badge", -1); + if (badge >= 0) { + ApplicationBadgeHelper.INSTANCE.setApplicationIconBadgeNumber(mFirebaseMessagingService, badge); + } + } + + // We need to run this on the main thread, as the React code assumes that is true. + // Namely, DevServerHelper constructs a Handler() without a Looper, which triggers: + // "Can't create handler inside thread that has not called Looper.prepare()" + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + public void run() { + // Construct and load our normal React JS code bundle + ReactInstanceManager mReactInstanceManager = ((ReactApplication) mFirebaseMessagingService.getApplication()).getReactNativeHost().getReactInstanceManager(); + ReactContext context = mReactInstanceManager.getCurrentReactContext(); + // If it's constructed, send a notification + if (context != null) { + handleRemotePushNotification((ReactApplicationContext) context, bundle); + } else { + // Otherwise wait for construction, then send the notification + mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() { + public void onReactContextInitialized(ReactContext context) { + handleRemotePushNotification((ReactApplicationContext) context, bundle); + } + }); + if (!mReactInstanceManager.hasStartedCreatingInitialContext()) { + // Construct it in the background + mReactInstanceManager.createReactContextInBackground(); + } + } + } + }); + } + + private JSONObject getPushData(String dataString) { + try { + return new JSONObject(dataString); + } catch (Exception e) { + return null; + } + } + + private void handleRemotePushNotification(ReactApplicationContext context, Bundle bundle) { + + // If notification ID is not provided by the user for push notification, generate one at random + if (bundle.getString("id") == null) { + Random randomNumberGenerator = new Random(System.currentTimeMillis()); + bundle.putString("id", String.valueOf(randomNumberGenerator.nextInt())); + } + + Boolean isForeground = isApplicationInForeground(); + + RNPushNotificationJsDelivery jsDelivery = new RNPushNotificationJsDelivery(context); + bundle.putBoolean("foreground", isForeground); + bundle.putBoolean("userInteraction", false); + jsDelivery.notifyNotification(bundle); + + // If contentAvailable is set to true, then send out a remote fetch event + if (bundle.getString("contentAvailable", "false").equalsIgnoreCase("true")) { + jsDelivery.notifyRemoteFetch(bundle); + } + + Log.v(LOG_TAG, "sendNotification: " + bundle); + + Application applicationContext = (Application) context.getApplicationContext(); + RNPushNotificationHelper pushNotificationHelper = new RNPushNotificationHelper(applicationContext); + pushNotificationHelper.sendToNotificationCentre(bundle); + } + + private boolean isApplicationInForeground() { + ActivityManager activityManager = (ActivityManager) mFirebaseMessagingService.getSystemService(ACTIVITY_SERVICE); + List processInfos = activityManager.getRunningAppProcesses(); + if (processInfos != null) { + for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) { + if (processInfo.processName.equals(mFirebaseMessagingService.getApplication().getPackageName())) { + if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { + for (String d : processInfo.pkgList) { + return true; + } + } + } + } + } + return false; + } +} diff --git a/package.json b/package.json index d102bb89f..e222968f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-push-notification", - "version": "3.1.3", + "version": "3.2.0", "description": "React Native Local and Remote Notifications", "main": "index", "scripts": {