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 380760a87..f76094d13 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationListenerService.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationListenerService.java @@ -56,7 +56,7 @@ public void onMessageReceived(String from, final Bundle bundle) { handler.post(new Runnable() { public void run() { // Construct and load our normal React JS code bundle - ReactInstanceManager mReactInstanceManager = ((ReactApplication) getApplication()).getReactNativeHost().getReactInstanceManager(); + final ReactInstanceManager mReactInstanceManager = ((ReactApplication) getApplication()).getReactNativeHost().getReactInstanceManager(); ReactContext context = mReactInstanceManager.getCurrentReactContext(); // If it's constructed, send a notification if (context != null) { @@ -66,6 +66,7 @@ public void run() { mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() { public void onReactContextInitialized(ReactContext context) { handleRemotePushNotification((ReactApplicationContext) context, bundle); + mReactInstanceManager.removeReactInstanceEventListener(this); } }); if (!mReactInstanceManager.hasStartedCreatingInitialContext()) { @@ -97,7 +98,6 @@ private void handleRemotePushNotification(ReactApplicationContext context, Bundl 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 diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationPublisher.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationPublisher.java index 8f75f91ba..9e3fce823 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationPublisher.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationPublisher.java @@ -1,26 +1,115 @@ package com.dieam.reactnativepushnotification.modules; +import android.app.ActivityManager; +import android.app.ActivityManager.RunningAppProcessInfo; import android.app.Application; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +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; public class RNPushNotificationPublisher extends BroadcastReceiver { final static String NOTIFICATION_ID = "notificationId"; @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(final Context context, Intent intent) { int id = intent.getIntExtra(NOTIFICATION_ID, 0); long currentTime = System.currentTimeMillis(); Log.i(LOG_TAG, "NotificationPublisher: Prepare To Publish: " + id + ", Now Time: " + currentTime); - Application applicationContext = (Application) context.getApplicationContext(); + final Bundle bundle = intent.getExtras(); + + 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 + final ReactInstanceManager mReactInstanceManager = ((ReactApplication) context.getApplicationContext()).getReactNativeHost().getReactInstanceManager(); + ReactContext context = mReactInstanceManager.getCurrentReactContext(); + // If it's constructed, send a notification + if (context != null) { + handleLocalNotification((ReactApplicationContext) context, bundle); + } else { + // Otherwise wait for construction, then send the notification + mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() { + public void onReactContextInitialized(ReactContext context) { + handleLocalNotification((ReactApplicationContext) context, bundle); + mReactInstanceManager.removeReactInstanceEventListener(this); + } + }); + if (!mReactInstanceManager.hasStartedCreatingInitialContext()) { + // Construct it in the background + mReactInstanceManager.createReactContextInBackground(); + } + } + } + }); + } + + private void handleLocalNotification(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(context); + + RNPushNotificationJsDelivery jsDelivery = new RNPushNotificationJsDelivery(context); + bundle.putBoolean("foreground", isForeground); + 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); + + if (!isForeground) { + Application applicationContext = (Application) context.getApplicationContext(); + RNPushNotificationHelper pushNotificationHelper = new RNPushNotificationHelper(applicationContext); + pushNotificationHelper.sendToNotificationCentre(bundle); + } + } - new RNPushNotificationHelper(applicationContext) - .sendToNotificationCentre(intent.getExtras()); + private boolean isApplicationInForeground(ReactApplicationContext context) { + ActivityManager activityManager = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE); + List processInfos = activityManager.getRunningAppProcesses(); + if (processInfos != null) { + for (RunningAppProcessInfo processInfo : processInfos) { + Application applicationContext = (Application) context.getApplicationContext(); + if (processInfo.processName.equals(applicationContext.getPackageName())) { + if (processInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { + for (String d : processInfo.pkgList) { + return true; + } + } + } + } + } + return false; } }